Example #1
0
  def testDestroyWithEC2EnvironmentVariables(self):
    # if the user wants us to use their EC2 credentials when running AppScale,
    # we should make sure they get set
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1,
      'EC2_ACCESS_KEY' : 'access key',
      'EC2_SECRET_KEY' : 'secret key'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-terminate-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('terminate_instances')
    appscale.destroy()

    self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
    self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
Example #2
0
  def destroy(self):
    """'destroy' provides a nicer experience for users than the
    appscale-terminate-instances command, by using the configuration options
    present in the AppScalefile found in the current working directory.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()

    # Construct a terminate-instances command from the file's contents
    command = []
    contents_as_yaml = yaml.safe_load(contents)
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml['keyname'])

    if 'verbose' in contents_as_yaml:
      command.append("--verbose")

    # Finally, exec the command. Don't worry about validating it -
    # appscale-terminate-instances will do that for us.
    options = ParseArgs(command, "appscale-terminate-instances").args
    try:
      AppScaleTools.terminate_instances(options)
    except Exception as e:
      AppScaleLogger.warn(str(e))
Example #3
0
    def logs(self, location):
        """ 'logs' provides a cleaner experience for users than the
    appscale-gather-logs command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      location: The path on the local filesystem where logs should be copied to.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # construct the appscale-gather-logs command
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--location")
        command.append(location)

        # and exec it
        options = ParseArgs(command, "appscale-gather-logs").args
        AppScaleTools.gather_logs(options)
Example #4
0
    def set(self, property_name, property_value):
        """ 'set' provides a cleaner experience for users than the
    appscale-set-property command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      property_name: A str naming the AppController instance variable that
        should be overwritten.
      property_value: The new value that should be used for the named property.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # construct the appscale-set-property command
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--property_name")
        command.append(property_name)

        command.append("--property_value")
        command.append(property_value)

        # and exec it
        options = ParseArgs(command, "appscale-set-property").args
        AppScaleTools.set_property(options)
Example #5
0
    def upgrade(self):
        """ Allows users to upgrade to the latest version of AppScale."""
        contents_as_yaml = yaml.safe_load(self.read_appscalefile())

        # Construct the appscale-upgrade command from argv and the contents of
        # the AppScalefile.
        command = []

        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml['keyname'])

        if 'verbose' in contents_as_yaml and contents_as_yaml[
                'verbose'] == True:
            command.append("--verbose")

        if 'ips_layout' in contents_as_yaml:
            command.append('--ips_layout')
            command.append(
                base64.b64encode(yaml.dump(contents_as_yaml['ips_layout'])))

        if 'login' in contents_as_yaml:
            command.extend(['--login', contents_as_yaml['login']])

        if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
            command.append('--test')

        options = ParseArgs(command, 'appscale-upgrade').args
        options.ips = yaml.safe_load(base64.b64decode(options.ips_layout))
        AppScaleTools.upgrade(options)
Example #6
0
  def testUpWithEC2EnvironmentVariables(self):
    # if the user wants us to use their EC2 credentials when running AppScale,
    # we should make sure they get set
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1,
      'EC2_ACCESS_KEY' : 'access key',
      'EC2_SECRET_KEY' : 'secret key'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, pretend that our ec2 image to use exists
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto)
    boto.should_receive('connect_ec2').with_args('access key', 'secret key') \
      .and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()

    self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
    self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
  def run_add_keypair(self):
    """ Sets up the add keypair arguments and attempts to add the
    keyname generated.

    Returns:
      True on success, False otherwise.
    """
    self.state = self.INIT_STATE
    add_keypair_args = ['--keyname', self.keyname, '--ips_layout', 
      self.ips_yaml_b64, "--root_password", self.root_pass, "--auto"]
    options = parse_args.ParseArgs(add_keypair_args, "appscale-add-keypair"). \
      args
    try:
      AppScaleTools.add_keypair(options)
      logging.info("AppScale add key pair was successful")
    except BadConfigurationException as bad_config:
      self.state = self.ERROR_STATE
      logging.error(str(bad_config))
      self.err_message = "Bad configuration. Unable to set up keypairs."
      return False
    except Exception as exception:
      self.state = self.ERROR_STATE
      logging.exception(exception)
      self.err_message = "Exception when running add key pair: {0}". \
        format(exception)
      return False
    return True
    def run_add_keypair(self):
        """ Sets up the add keypair arguments and attempts to add the
    keyname generated.

    Returns:
      True on success, False otherwise.
    """
        self.state = self.INIT_STATE
        add_keypair_args = [
            '--keyname', self.keyname, '--ips_layout', self.ips_yaml_b64,
            "--root_password", self.root_pass, "--auto"
        ]
        options = parse_args.ParseArgs(add_keypair_args, "appscale-add-keypair"). \
          args
        try:
            AppScaleTools.add_keypair(options)
            logging.info("AppScale add key pair was successful")
        except BadConfigurationException as bad_config:
            self.state = self.ERROR_STATE
            logging.error(str(bad_config))
            self.err_message = "Bad configuration. Unable to set up keypairs."
            return False
        except Exception as exception:
            self.state = self.ERROR_STATE
            logging.exception(exception)
            self.err_message = "Exception when running add key pair: {0}". \
              format(exception)
            return False
        return True
Example #9
0
  def logs(self, location):
    """'logs' provides a cleaner experience for users than the
    appscale-gather-logs command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      location: The path on the local filesystem where logs should be copied to.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()
    contents_as_yaml = yaml.safe_load(contents)

    # construct the appscale-gather-logs command
    command = []
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml["keyname"])

    command.append("--location")
    command.append(location)

    # and exec it
    options = ParseArgs(command, "appscale-gather-logs").args
    try:
      AppScaleTools.gather_logs(options)
    except Exception as e:
      AppScaleLogger.warn(str(e))
Example #10
0
    def undeploy(self, appid):
        """ 'undeploy' is a more accessible way to tell an AppScale deployment to
    stop hosting a Google App Engine application than 'appscale-remove-app'. It
    calls that command with the configuration options found in the AppScalefile
    in the current working directory.

    Args:
      appid: The name of the application that we should remove.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()

        # Construct an remove-app command from the file's contents
        command = []
        contents_as_yaml = yaml.safe_load(contents)
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml['keyname'])

        if 'verbose' in contents_as_yaml and contents_as_yaml[
                'verbose'] == True:
            command.append("--verbose")

        if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
            command.append('--confirm')

        command.append("--appname")
        command.append(appid)

        # Finally, exec the command. Don't worry about validating it -
        # appscale-upload-app will do that for us.
        options = ParseArgs(command, "appscale-remove-app").args
        AppScaleTools.remove_app(options)
  def test_all_ok(self):
    # If the user wants to relocate their app to port X, and nothing else
    # runs on that port, this should succeed.

    # Assume that the AppController is running, so is our app, and that other
    # apps are not running on port 80.
    fake_appcontroller = flexmock(name='fake_appcontroller')
    fake_appcontroller.should_receive('get_app_info_map').with_args(
      'the secret').and_return(json.dumps({
      self.appid : {
        'nginx' : 8080
      },
      'a-different-app' : {
        'nginx' : 81
      }
    }))
    fake_appcontroller.should_receive('relocate_app').with_args(self.appid, 80,
      443, 'the secret').and_return("OK")
    flexmock(SOAPpy)
    SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
      .and_return(fake_appcontroller)

    argv = [
      '--keyname', self.keyname,
      '--appname', self.appid,
      '--http_port', '80',
      '--https_port', '443'
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.relocate_app(options)
Example #12
0
  def deploy(self, app):
    """'deploy' is a more accessible way to tell an AppScale deployment to run a
    Google App Engine application than 'appscale-upload-app'. It calls that
    command with the configuration options found in the AppScalefile in the
    current working directory.

    Args:
      app: The path (absolute or relative) to the Google App Engine application
        that should be uploaded.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()

    # Construct an upload-app command from the file's contents
    command = []
    contents_as_yaml = yaml.safe_load(contents)
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml['keyname'])

    if 'test' in contents_as_yaml:
      command.append("--test")

    if 'verbose' in contents_as_yaml:
      command.append("--verbose")

    command.append("--file")
    command.append(app)

    # Finally, exec the command. Don't worry about validating it -
    # appscale-upload-app will do that for us.
    options = ParseArgs(command, "appscale-upload-app").args
    AppScaleTools.upload_app(options)
Example #13
0
  def testUndeployWithCloudAppScalefile(self):
    # calling 'appscale undeploy app' with an AppScalefile in the local
    # directory should collect any parameters needed for the
    # 'appscale-remove-app' command and then exec it
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('remove_app')
    app = 'barapp'
    appscale.undeploy(app)
  def testUndeployWithCloudAppScalefile(self):
    # calling 'appscale undeploy app' with an AppScalefile in the local
    # directory should collect any parameters needed for the
    # 'appscale-remove-app' command and then exec it
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('remove_app')
    app = 'barapp'
    appscale.undeploy(app)
Example #15
0
  def testDeployWithCloudAppScalefile(self):
    # calling 'appscale deploy app' with an AppScalefile in the local
    # directory should collect any parameters needed for the
    # 'appscale-upload-app' command and then exec it
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-run-instances call
    fake_port = 8080
    fake_host = 'fake_host'
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('upload_app').and_return(
      (fake_host, fake_port))
    app = '/bar/app'
    (host, port) = appscale.deploy(app)
    self.assertEquals(fake_host, host)
    self.assertEquals(fake_port, port)
Example #16
0
  def testUpWithMalformedClusterAppScalefile(self):
    # if we try to use an IPs layout that isn't a dictionary, we should throw up
    # and die
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file, with an IPs layout that is a str
    contents = {
      'ips_layout': "'master' 'ip1' 'appengine' 'ip1'",
      'keyname': 'boobazblarg', 'group' : 'boobazblarg'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # finally, mock out the actual appscale tools calls. since we're running
    # via a cluster, this means we call add-keypair to set up SSH keys, then
    # run-instances to start appscale
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('add_keypair')

    self.assertRaises(BadConfigurationException, appscale.up)
  def testDeployWithCloudAppScalefileAndTestFlag(self):
    # same as before, but with the 'test' flag in our AppScalefile
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1,
      'test' : True
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-run-instances call
    fake_port = 8080
    fake_host = 'fake_host'
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('upload_app').and_return(
      (fake_host, fake_port))
    app = '/bar/app'
    (host, port) = appscale.deploy(app)
    self.assertEquals(fake_host, host)
    self.assertEquals(fake_port, port)
Example #18
0
  def set(self, property_name, property_value):
    """ 'set' provides a cleaner experience for users than the
    appscale-set-property command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      property_name: A str naming the AppController instance variable that
        should be overwritten.
      property_value: The new value that should be used for the named property.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()
    contents_as_yaml = yaml.safe_load(contents)

    # construct the appscale-set-property command
    command = []
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml["keyname"])

    command.append("--property_name")
    command.append(property_name)

    command.append("--property_value")
    command.append(property_value)

    # and exec it
    options = ParseArgs(command, "appscale-set-property").args
    AppScaleTools.set_property(options)
Example #19
0
  def upgrade(self):
    """ Allows users to upgrade to the latest version of AppScale."""
    contents_as_yaml = yaml.safe_load(self.read_appscalefile())

    # Construct the appscale-upgrade command from argv and the contents of
    # the AppScalefile.
    command = []

    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml['keyname'])

    if 'verbose' in contents_as_yaml and contents_as_yaml['verbose'] == True:
      command.append("--verbose")

    if 'ips_layout' in contents_as_yaml:
      command.append('--ips_layout')
      command.append(
        base64.b64encode(yaml.dump(contents_as_yaml['ips_layout'])))

    if 'login' in contents_as_yaml:
      command.extend(['--login', contents_as_yaml['login']])

    if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
      command.append('--test')

    options = ParseArgs(command, 'appscale-upgrade').args
    options.ips = yaml.safe_load(base64.b64decode(options.ips_layout))
    AppScaleTools.upgrade(options)
  def testDestroyWithEC2EnvironmentVariables(self):
    # if the user wants us to use their EC2 credentials when running AppScale,
    # we should make sure they get set
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1,
      'EC2_ACCESS_KEY' : 'access key',
      'EC2_SECRET_KEY' : 'secret key'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-terminate-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('terminate_instances')
    appscale.destroy()

    self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
    self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
Example #21
0
  def testUpWithCloudAppScalefile(self):
    # calling 'appscale up' if there is an AppScalefile present
    # should call appscale-run-instances with the given config
    # params. here, we assume that the file is intended for use
    # on EC2
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # throw in some mocks for the argument parsing
    for credential in EC2Agent.REQUIRED_CREDENTIALS:
      os.environ[credential] = "baz"

    # finally, pretend that our ec2 image to use exists
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto)
    boto.should_receive('connect_ec2').with_args('baz', 'baz').and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()
Example #22
0
    def test_appscale_in_two_node_virt_deployment(self):
        # pretend that the place we're going to put logs into doesn't exist
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args('/tmp/foobaz').and_return(
            False)

        # and mock out the mkdir operation
        flexmock(os)
        os.should_receive('mkdir').with_args('/tmp/foobaz').and_return()

        # next, mock out finding the login ip address
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_nodes_json")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([{
                "public_ip": "public1",
                "private_ip": "private1",
                "jobs": ["shadow", "login"]
            }]))
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)

        # mock out writing the secret key to ~/.appscale, as well as reading it
        # later
        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # and slip in a fake appcontroller to report on the two IP addrs
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_all_public_ips').with_args(
            'the secret').and_return(json.dumps(['public1', 'public2']))
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        # fake the creation of the log directories locally
        os.should_receive('mkdir').with_args(
            '/tmp/foobaz/public1').and_return()
        os.should_receive('mkdir').with_args(
            '/tmp/foobaz/public2').and_return()

        # finally, fake the copying of the log files
        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('/var/log/appscale'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        argv = ["--keyname", self.keyname, "--location", "/tmp/foobaz"]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.gather_logs(options)
  def testDeployWithCloudAppScalefile(self):
    # calling 'appscale deploy app' with an AppScalefile in the local
    # directory should collect any parameters needed for the
    # 'appscale-upload-app' command and then exec it
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-run-instances call
    fake_port = 8080
    fake_host = 'fake_host'
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('upload_app').and_return(
      (fake_host, fake_port))
    app = '/bar/app'
    (host, port) = appscale.deploy(app)
    self.assertEquals(fake_host, host)
    self.assertEquals(fake_port, port)
  def testUpWithMalformedClusterAppScalefile(self):
    # if we try to use an IPs layout that isn't a dictionary, we should throw up
    # and die
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file, with an IPs layout that is a str
    contents = {
      'ips_layout': "'master' 'ip1' 'appengine' 'ip1'",
      'keyname': 'boobazblarg', 'group' : 'boobazblarg'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # finally, mock out the actual appscale tools calls. since we're running
    # via a cluster, this means we call add-keypair to set up SSH keys, then
    # run-instances to start appscale
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('add_keypair')

    self.assertRaises(BadConfigurationException, appscale.up)
Example #25
0
  def undeploy(self, appid):
    """ 'undeploy' is a more accessible way to tell an AppScale deployment to
    stop hosting a Google App Engine application than 'appscale-remove-app'. It
    calls that command with the configuration options found in the AppScalefile
    in the current working directory.

    Args:
      appid: The name of the application that we should remove.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()

    # Construct an remove-app command from the file's contents
    command = []
    contents_as_yaml = yaml.safe_load(contents)
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml['keyname'])

    if 'verbose' in contents_as_yaml and contents_as_yaml['verbose'] == True:
      command.append("--verbose")

    command.append("--appname")
    command.append(appid)

    # Finally, exec the command. Don't worry about validating it -
    # appscale-upload-app will do that for us.
    options = ParseArgs(command, "appscale-remove-app").args
    AppScaleTools.remove_app(options)
    def testUpWithEC2EnvironmentVariables(self):
        # if the user wants us to use their EC2 credentials when running AppScale,
        # we should make sure they get set
        appscale = AppScale()

        # Mock out the actual file reading itself, and slip in a YAML-dumped
        # file
        contents = {
            'infrastructure': 'ec2',
            'machine': 'ami-ABCDEFG',
            'keyname': 'bookey',
            'group': 'boogroup',
            'min': 1,
            'max': 1,
            'EC2_ACCESS_KEY': 'access key',
            'EC2_SECRET_KEY': 'secret key'
        }
        yaml_dumped_contents = yaml.dump(contents)
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        # finally, pretend that our ec2 image to use exists
        fake_ec2 = flexmock(name="fake_ec2")
        fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
          .and_return()
        flexmock(boto)
        boto.should_receive('connect_ec2').with_args('access key', 'secret key') \
          .and_return(fake_ec2)

        # finally, mock out the actual appscale-run-instances call
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('run_instances')
        appscale.up()

        self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
        self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
Example #27
0
  def testDeployWithCloudAppScalefileAndTestFlag(self):
    # same as before, but with the 'test' flag in our AppScalefile
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1,
      'test' : True
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-run-instances call
    fake_port = 8080
    fake_host = 'fake_host'
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('upload_app').and_return(
      (fake_host, fake_port))
    app = '/bar/app'
    (host, port) = appscale.deploy(app)
    self.assertEquals(fake_host, host)
    self.assertEquals(fake_port, port)
    def test_all_ok(self):
        # If the user wants to relocate their app to port X, and nothing else
        # runs on that port, this should succeed.

        # Assume that the AppController is running, so is our app, and that other
        # apps are not running on port 80.
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_app_info_map').with_args(
            'the secret').and_return(
                json.dumps({
                    self.appid: {
                        'nginx': 8080
                    },
                    'a-different-app': {
                        'nginx': 81
                    }
                }))
        fake_appcontroller.should_receive('relocate_app').with_args(
            self.appid, 80, 443, 'the secret').and_return("OK")
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        argv = [
            '--keyname', self.keyname, '--appname', self.appid, '--http_port',
            '80', '--https_port', '443'
        ]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.relocate_app(options)
Example #29
0
  def up(self):
    """ Starts an AppScale deployment with the configuration options from the
    AppScalefile in the current directory.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current
      directory.
    """
    contents = self.read_appscalefile()

    # If running in a cluster environment, we first need to set up SSH keys
    contents_as_yaml = yaml.safe_load(contents)
    if not LocalState.ensure_appscalefile_is_up_to_date():
      contents = self.read_appscalefile()
      contents_as_yaml = yaml.safe_load(contents)

    # Construct a run-instances command from the file's contents
    command = []
    for key, value in contents_as_yaml.items():
      if key in ["EC2_ACCESS_KEY", "EC2_SECRET_KEY", "EC2_URL"]:
        os.environ[key] = value
        continue

      if value is True:
        command.append(str("--%s" % key))
      elif value is False:
        pass
      else:
        if key == "ips_layout":
          command.append("--ips_layout")
          command.append(base64.b64encode(yaml.dump(value)))
        elif key == "disks":
          command.append("--disks")
          command.append(base64.b64encode(yaml.dump(value)))
        elif key == "user_commands":
          command.append("--user_commands")
          command.append(base64.b64encode(yaml.dump(value)))
        else:
          command.append(str("--%s" % key))
          command.append(str("%s" % value))

    run_instances_opts = ParseArgs(command, "appscale-run-instances").args

    if 'infrastructure' not in contents_as_yaml:
      # Generate a new keypair if necessary.
      if not self.valid_ssh_key(contents_as_yaml, run_instances_opts):
        add_keypair_command = []
        if 'keyname' in contents_as_yaml:
          add_keypair_command.append('--keyname')
          add_keypair_command.append(str(contents_as_yaml['keyname']))

        add_keypair_command.append('--ips_layout')
        add_keypair_command.append(
          base64.b64encode(yaml.dump(contents_as_yaml['ips_layout'])))
        add_keypair_opts = ParseArgs(
          add_keypair_command, 'appscale-add-keypair').args
        AppScaleTools.add_keypair(add_keypair_opts)

    AppScaleTools.run_instances(run_instances_opts)
  def test_appscale_in_two_node_virt_deployment(self):
    # pretend that the place we're going to put logs into doesn't exist
    flexmock(os.path)
    os.path.should_call('exists')  # set the fall-through
    os.path.should_receive('exists').with_args('/tmp/foobaz').and_return(False)

    # and mock out the mkdir operation
    flexmock(os)
    os.should_receive('mkdir').with_args('/tmp/foobaz').and_return()

    # next, mock out finding the login ip address
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return(True)

    fake_nodes_json = flexmock(name="fake_nodes_json")
    fake_nodes_json.should_receive('read').and_return(json.dumps([{
      "public_ip" : "public1",
      "private_ip" : "private1",
      "jobs" : ["shadow", "login"]
    }]))
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_nodes_json)

    # mock out writing the secret key to ~/.appscale, as well as reading it
    # later
    secret_key_location = LocalState.get_secret_key_location(self.keyname)
    fake_secret = flexmock(name="fake_secret")
    fake_secret.should_receive('read').and_return('the secret')
    builtins.should_receive('open').with_args(secret_key_location, 'r') \
      .and_return(fake_secret)

    # and slip in a fake appcontroller to report on the two IP addrs
    fake_appcontroller = flexmock(name='fake_appcontroller')
    fake_appcontroller.should_receive('get_all_public_ips').with_args(
      'the secret').and_return(json.dumps(['public1', 'public2']))
    flexmock(SOAPpy)
    SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
      .and_return(fake_appcontroller)

    # fake the creation of the log directories locally
    os.should_receive('mkdir').with_args('/tmp/foobaz/public1').and_return()
    os.should_receive('mkdir').with_args('/tmp/foobaz/public2').and_return()

    # finally, fake the copying of the log files
    flexmock(subprocess)
    subprocess.should_receive('Popen').with_args(re.compile('/var/log/appscale'),
      shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
      .and_return(self.success)

    argv = [
      "--keyname", self.keyname,
      "--location", "/tmp/foobaz"
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.gather_logs(options)
Example #31
0
    def test_describe_instances_with_two_nodes(self):
        # mock out writing the secret key to ~/.appscale, as well as reading it
        # later
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')  # set the fall-through

        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        fake_secret.should_receive('write').and_return()
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # mock out the SOAP call to the AppController and assume it succeeded
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_all_public_ips').with_args('the secret') \
          .and_return(json.dumps(['public1', 'public2']))
        fake_appcontroller.should_receive('status').with_args('the secret') \
          .and_return('nothing interesting here') \
          .and_return('Database is at not-up-yet') \
          .and_return('Database is at 1.2.3.4')
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public2:17443') \
          .and_return(fake_appcontroller)

        # mock out reading the locations.json file, and slip in our own json
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_nodes_json")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([
                {
                    "public_ip": "public1",
                    "private_ip": "private1",
                    "jobs": ["shadow", "login"]
                },
                {
                    "public_ip": "public2",
                    "private_ip": "private2",
                    "jobs": ["appengine"]
                },
            ]))
        fake_nodes_json.should_receive('write').and_return()
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)
        # assume that there are two machines running in our deployment

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.describe_instances(options)
  def test_remove_app_and_app_is_running(self):
    # mock out reading from stdin, and assume the user says 'YES'
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_receive('raw_input').and_return('YES')

    # mock out reading the secret key
    builtins.should_call('open')  # set the fall-through

    secret_key_location = LocalState.get_secret_key_location(self.keyname)
    fake_secret = flexmock(name="fake_secret")
    fake_secret.should_receive('read').and_return('the secret')
    builtins.should_receive('open').with_args(secret_key_location, 'r') \
      .and_return(fake_secret)

    # mock out the SOAP call to the AppController and assume it succeeded
    fake_appcontroller = flexmock(name='fake_appcontroller')
    fake_appcontroller.should_receive('status').with_args('the secret') \
      .and_return('Database is at public1')
    fake_appcontroller.should_receive('stop_app').with_args('blargapp',
      'the secret').and_return('OK')
    fake_appcontroller.should_receive('is_app_running').with_args('blargapp',
      'the secret').and_return(True).and_return(True).and_return(False)
    flexmock(SOAPpy)
    SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
      .and_return(fake_appcontroller)

    # mock out reading the locations.json file, and slip in our own json
    flexmock(os.path)
    os.path.should_call('exists')  # set the fall-through
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return(True)

    fake_nodes_json = flexmock(name="fake_nodes_json")
    fake_nodes_json.should_receive('read').and_return(json.dumps([{
      "public_ip" : "public1",
      "private_ip" : "private1",
      "jobs" : ["shadow", "login"]
    }]))
    fake_nodes_json.should_receive('write').and_return()
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_nodes_json)

    # mock out calls to the UserAppServer and presume that the app does exist
    fake_userappserver = flexmock(name='fake_uaserver')
    fake_userappserver.should_receive('get_app_data').with_args(
      'blargapp', 'the secret').and_return(json.dumps({
        'hosts' : { '192.168.1.1' : { 'http' : '80', 'https' : '443' }}}))
    SOAPpy.should_receive('SOAPProxy').with_args('https://public1:4343') \
      .and_return(fake_userappserver)

    argv = [
      "--appname", "blargapp",
      "--keyname", self.keyname
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.remove_app(options)
  def test_describe_instances_with_two_nodes(self):
    # mock out writing the secret key to ~/.appscale, as well as reading it
    # later
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')  # set the fall-through

    secret_key_location = LocalState.get_secret_key_location(self.keyname)
    fake_secret = flexmock(name="fake_secret")
    fake_secret.should_receive('read').and_return('the secret')
    fake_secret.should_receive('write').and_return()
    builtins.should_receive('open').with_args(secret_key_location, 'r') \
      .and_return(fake_secret)

    # mock out the SOAP call to the AppController and assume it succeeded
    fake_appcontroller = flexmock(name='fake_appcontroller')
    fake_appcontroller.should_receive('get_all_public_ips').with_args('the secret') \
      .and_return(json.dumps(['public1', 'public2']))
    fake_appcontroller.should_receive('status').with_args('the secret') \
      .and_return('nothing interesting here') \
      .and_return('Database is at not-up-yet') \
      .and_return('Database is at 1.2.3.4')
    flexmock(SOAPpy)
    SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
      .and_return(fake_appcontroller)
    SOAPpy.should_receive('SOAPProxy').with_args('https://public2:17443') \
      .and_return(fake_appcontroller)

    # mock out reading the locations.json file, and slip in our own json
    flexmock(os.path)
    os.path.should_call('exists')  # set the fall-through
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return(True)

    fake_nodes_json = flexmock(name="fake_nodes_json")
    fake_nodes_json.should_receive('read').and_return(json.dumps([{
      "public_ip" : "public1",
      "private_ip" : "private1",
      "jobs" : ["shadow", "login"]
    },
    {
      "public_ip" : "public2",
      "private_ip" : "private2",
      "jobs" : ["appengine"]
    },
    ]))
    fake_nodes_json.should_receive('write').and_return()
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_nodes_json)
    # assume that there are two machines running in our deployment

    argv = [
      "--keyname", self.keyname
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.describe_instances(options)
Example #34
0
    def test_remove_app_and_app_is_running(self):
        # mock out reading from stdin, and assume the user says 'YES'
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_receive('raw_input').and_return('YES')

        # mock out reading the secret key
        builtins.should_call('open')  # set the fall-through

        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # mock out the SOAP call to the AppController and assume it succeeded
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('status').with_args('the secret') \
          .and_return('Database is at public1')
        fake_appcontroller.should_receive('stop_app').with_args(
            'blargapp', 'the secret').and_return('OK')
        fake_appcontroller.should_receive('is_app_running').with_args(
            'blargapp',
            'the secret').and_return(True).and_return(True).and_return(False)
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        # mock out reading the locations.json file, and slip in our own json
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_nodes_json")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([{
                "public_ip": "public1",
                "private_ip": "private1",
                "jobs": ["shadow", "login"]
            }]))
        fake_nodes_json.should_receive('write').and_return()
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)

        # mock out calls to the UserAppServer and presume that the app does exist
        fake_userappserver = flexmock(name='fake_uaserver')
        fake_userappserver.should_receive('get_app_data').with_args(
            'blargapp', 'the secret').and_return('\nnum_ports:2\n')
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:4343') \
          .and_return(fake_userappserver)

        argv = ["--appname", "blargapp", "--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.remove_app(options)
Example #35
0
    def test_reset_password_for_user_that_exists(self):
        # put in a mock for reading the secret file
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')  # set the fall-through

        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # mock out reading the username and new password from the user
        builtins.should_receive('raw_input').and_return('*****@*****.**')
        flexmock(getpass)
        getpass.should_receive('getpass').and_return('the password')

        # mock out finding the login node's IP address from the json file
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_secret")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([{
                'public_ip': 'public1',
                'private_ip': 'private1',
                'jobs': ['login', 'db_master']
            }]))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)

        # mock out grabbing the userappserver ip from an appcontroller
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('status').with_args('the secret') \
          .and_return('nothing interesting here') \
          .and_return('Database is at not-up-yet') \
          .and_return('Database is at public1')

        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@foo.goo', str, 'the secret').and_return('true')
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:4343') \
          .and_return(fake_userappserver)

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.reset_password(options)
  def test_reset_password_for_user_that_exists(self):
    # put in a mock for reading the secret file
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')  # set the fall-through

    secret_key_location = LocalState.get_secret_key_location(self.keyname)
    fake_secret = flexmock(name="fake_secret")
    fake_secret.should_receive('read').and_return('the secret')
    builtins.should_receive('open').with_args(secret_key_location, 'r') \
      .and_return(fake_secret)

    # mock out reading the username and new password from the user
    builtins.should_receive('raw_input').and_return('*****@*****.**')
    flexmock(getpass)
    getpass.should_receive('getpass').and_return('the password')

    # mock out finding the login node's IP address from the json file
    flexmock(os.path)
    os.path.should_call('exists')  # set the fall-through
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return(True)

    fake_nodes_json = flexmock(name="fake_secret")
    fake_nodes_json.should_receive('read').and_return(json.dumps([{
      'public_ip' : 'public1',
      'private_ip' : 'private1',
      'jobs' : ['login', 'db_master']
     }]))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_nodes_json)

    # mock out grabbing the userappserver ip from an appcontroller
    fake_appcontroller = flexmock(name='fake_appcontroller')
    fake_appcontroller.should_receive('status').with_args('the secret') \
      .and_return('nothing interesting here') \
      .and_return('Database is at not-up-yet') \
      .and_return('Database is at public1')

    flexmock(SOAPpy)
    SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@foo.goo', str, 'the secret').and_return('true')
    SOAPpy.should_receive('SOAPProxy').with_args('https://public1:4343') \
      .and_return(fake_userappserver)

    argv = [
      "--keyname", self.keyname
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.reset_password(options)
Example #37
0
    def up(self):
        """Starts an AppScale deployment with the configuration options from the
    AppScalefile in the current directory.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current
      directory.
    """
        contents = self.read_appscalefile()

        # If running in a cluster environment, we first need to set up SSH keys
        contents_as_yaml = yaml.safe_load(contents)
        if "ips_layout" in contents_as_yaml:
            ips_layout = base64.b64encode(
                yaml.dump(contents_as_yaml["ips_layout"]))

        if not "infrastructure" in contents_as_yaml:
            # Only run add-keypair if there is no ssh key present,
            # or if it doesn't log into all the machines specified.
            if not self.valid_ssh_key(contents_as_yaml):
                add_keypair_command = []
                if "keyname" in contents_as_yaml:
                    add_keypair_command.append("--keyname")
                    add_keypair_command.append(str(
                        contents_as_yaml["keyname"]))

                add_keypair_command.append("--ips_layout")
                add_keypair_command.append(ips_layout)
                options = ParseArgs(add_keypair_command,
                                    "appscale-add-keypair").args
                AppScaleTools.add_keypair(options)

        # Construct a run-instances command from the file's contents
        command = []
        for key, value in contents_as_yaml.items():
            if key in ["EC2_ACCESS_KEY", "EC2_SECRET_KEY", "EC2_URL"]:
                os.environ[key] = value
                continue

            if value is True:
                command.append(str("--%s" % key))
            elif value is False:
                pass
            else:
                if key == "ips_layout":
                    command.append("--ips_layout")
                    command.append(ips_layout)
                else:
                    command.append(str("--%s" % key))
                    command.append(str("%s" % value))

        # Finally, call AppScaleTools.run_instances
        options = ParseArgs(command, "appscale-run-instances").args
        AppScaleTools.run_instances(options)
    def testGetLogsWithKeyname(self):
        # calling 'appscale logs dir' with a keyname should produce
        # a command to exec with the --keyname flag
        appscale = AppScale()
        contents = {"keyname": "boo"}
        yaml_dumped_contents = yaml.dump(contents)
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        # mock out the actual call to appscale-gather-logs
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('run_instances')
        self.assertRaises(BadConfigurationException, appscale.logs, '/baz')
Example #39
0
  def testGetLogsWithNoKeyname(self):
    # calling 'appscale logs dir' with no keyname should produce
    # a command to exec without the --keyname flag
    appscale = AppScale()
    contents = {
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # mock out the actual call to appscale-gather-logs
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.logs('/baz')
Example #40
0
  def up(self):
    """Starts an AppScale deployment with the configuration options from the
    AppScalefile in the current directory.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current
      directory.
    """
    contents = self.read_appscalefile()

    # If running in a cluster environment, we first need to set up SSH keys
    contents_as_yaml = yaml.safe_load(contents)
    if "ips_layout" in contents_as_yaml:
      ips_layout = base64.b64encode(yaml.dump(contents_as_yaml["ips_layout"]))

    if not "infrastructure" in contents_as_yaml:
      # Only run add-keypair if there is no ssh key present,
      # or if it doesn't log into all the machines specified.
      if not self.valid_ssh_key(contents_as_yaml):
        add_keypair_command = []
        if "keyname" in contents_as_yaml:
          add_keypair_command.append("--keyname")
          add_keypair_command.append(str(contents_as_yaml["keyname"]))

        add_keypair_command.append("--ips_layout")
        add_keypair_command.append(ips_layout)
        options = ParseArgs(add_keypair_command, "appscale-add-keypair").args
        AppScaleTools.add_keypair(options)

    # Construct a run-instances command from the file's contents
    command = []
    for key, value in contents_as_yaml.items():
      if key in ["EC2_ACCESS_KEY", "EC2_SECRET_KEY", "EC2_URL"]:
        os.environ[key] = value
        continue

      if value is True:
        command.append(str("--%s" % key))
      elif value is False:
        pass
      else:
        if key == "ips_layout":
          command.append("--ips_layout")
          command.append(ips_layout)
        else:
          command.append(str("--%s" % key))
          command.append(str("%s" % value))

    # Finally, call AppScaleTools.run_instances
    options = ParseArgs(command, "appscale-run-instances").args
    AppScaleTools.run_instances(options)
  def testGetLogsWithKeyname(self):
    # calling 'appscale logs dir' with a keyname should produce
    # a command to exec with the --keyname flag
    appscale = AppScale()
    contents = {
      "keyname" : "boo"
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # mock out the actual call to appscale-gather-logs
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    self.assertRaises(BadConfigurationException, appscale.logs, '/baz')
  def test_appscale_in_one_node_virt_deployment_with_login_override(self):
    # let's say that appscale isn't already running
    self.local_state.should_receive('ensure_appscale_isnt_running').and_return()
    self.local_state.should_receive('make_appscale_directory').and_return()
    self.local_state.should_receive('update_local_metadata').and_return()
    self.local_state.should_receive('get_local_nodes_info').and_return(json.loads(
      json.dumps([{
        "public_ip" : "1.2.3.4",
        "private_ip" : "1.2.3.4",
        "jobs" : ["shadow", "login"]
      }])))
    self.local_state.should_receive('get_secret_key').and_return("fookey")


    flexmock(RemoteHelper)
    RemoteHelper.should_receive('start_head_node')\
        .and_return(('1.2.3.4','i-ABCDEFG'))
    RemoteHelper.should_receive('sleep_until_port_is_open').and_return()
    RemoteHelper.should_receive('copy_local_metadata').and_return()
    RemoteHelper.should_receive('create_user_accounts').and_return()
    RemoteHelper.should_receive('wait_for_machines_to_finish_loading')\
        .and_return()

    acc = flexmock(AppControllerClient)
    acc.should_receive('is_initialized').and_return(True)

    uac = flexmock(UserAppClient)
    uac.should_receive('does_user_exist').and_return(False)

    flexmock(UserAppClient).should_receive('set_admin_role').and_return()


    # don't use a 192.168.X.Y IP here, since sometimes we set our virtual
    # machines to boot with those addresses (and that can mess up our tests).
    ips_layout = yaml.safe_load("""
master : 1.2.3.4
database: 1.2.3.4
zookeeper: 1.2.3.4
appengine:  1.2.3.4
    """)

    argv = [
      "--ips_layout", base64.b64encode(yaml.dump(ips_layout)),
      "--keyname", self.keyname,
      "--test",
      "--login_host", "www.booscale.com"
    ]

    options = ParseArgs(argv, self.function).args
    AppScaleTools.run_instances(options)
Example #43
0
  def test_appscale_in_one_node_virt_deployment_with_login_override(self):
    # let's say that appscale isn't already running
    local_state = flexmock(LocalState)
    local_state.should_receive('ensure_appscale_isnt_running').and_return()
    local_state.should_receive('make_appscale_directory').and_return()
    local_state.should_receive('update_local_metadata').and_return()
    local_state.should_receive('get_local_nodes_info').and_return(json.loads(
      json.dumps([{
        "public_ip" : "1.2.3.4",
        "private_ip" : "1.2.3.4",
        "jobs" : ["shadow", "login"]
      }])))
    local_state.should_receive('get_secret_key').and_return("fookey")


    flexmock(RemoteHelper)
    RemoteHelper.should_receive('start_head_node')\
        .and_return(('1.2.3.4','i-ABCDEFG'))
    RemoteHelper.should_receive('sleep_until_port_is_open').and_return()
    RemoteHelper.should_receive('copy_local_metadata').and_return()
    RemoteHelper.should_receive('create_user_accounts').and_return()
    RemoteHelper.should_receive('wait_for_machines_to_finish_loading')\
        .and_return()

    acc = flexmock(AppControllerClient)
    acc.should_receive('get_uaserver_host').and_return('host')

    flexmock(UserAppClient).should_receive('set_admin_role').and_return()


    # don't use a 192.168.X.Y IP here, since sometimes we set our virtual
    # machines to boot with those addresses (and that can mess up our tests).
    ips_layout = yaml.safe_load("""
master : 1.2.3.4
database: 1.2.3.4
zookeeper: 1.2.3.4
appengine:  1.2.3.4
    """)

    argv = [
      "--ips_layout", base64.b64encode(yaml.dump(ips_layout)),
      "--keyname", self.keyname,
      "--test",
      "--login_host", "www.booscale.com"
    ]


    options = ParseArgs(argv, self.function).args
    AppScaleTools.run_instances(options)
    def appscale_down(self):
        """ Terminates a currently running deployment of AppScale. Calls on the 
    AppScale tools by building an argument list, which varies based on 
    the deployment type.
   
    Returns:
      True on success, False otherwise. 
    """
        logging.debug("Starting AppScale down.")
        self.state = self.TERMINATING_STATE

        # We capture the stdout and stderr of the tools and use it to calculate
        # the percentage towards completion.
        old_stdout = sys.stdout
        old_stderr = sys.stderr
        sys.stdout = self.std_out_capture
        sys.stderr = self.std_err_capture

        terminate_args = ['--keyname', self.keyname, "--verbose"]

        if self.deployment_type == CLOUD:
            terminate_args.extend([
                "--EC2_SECRET_KEY", self.ec2_secret, "--EC2_ACCESS_KEY",
                self.ec2_access, "--EC2_URL", self.ec2_url, "--test"
            ])
        try:
            logging.info("Starting terminate instances.")

            options = parse_args.ParseArgs(terminate_args,
                                           "appscale-terminate-instances").args
            AppScaleTools.terminate_instances(options)
            self.state = self.TERMINATED_STATE

            logging.info("AppScale terminate instances successfully ran!")
        except BadConfigurationException as bad_config:
            self.state = self.ERROR_STATE
            logging.exception(bad_config)
            self.err_message = "Bad configuration. Unable to terminate AppScale. " \
              "{0}".format(bad_config)
        except Exception as exception:
            self.state = self.ERROR_STATE
            logging.exception(exception)
            self.err_message = "Exception when terminating: {0}".format(
                exception)
        finally:
            sys.stdout = old_stdout
            sys.stderr = old_stderr

        return self.state == self.TERMINATED_STATE
  def appscale_down(self):
    """ Terminates a currently running deployment of AppScale. Calls on the 
    AppScale tools by building an argument list, which varies based on 
    the deployment type.
   
    Returns:
      True on success, False otherwise. 
    """
    logging.debug("Starting AppScale down.")
    self.state = self.TERMINATING_STATE

    # We capture the stdout and stderr of the tools and use it to calculate
    # the percentage towards completion.
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = self.std_out_capture
    sys.stderr = self.std_err_capture

    terminate_args = ['--keyname', self.keyname, "--verbose"]

    if self.deployment_type == CLOUD:
      terminate_args.extend(["--EC2_SECRET_KEY", self.ec2_secret,
      "--EC2_ACCESS_KEY", self.ec2_access,
      "--EC2_URL", self.ec2_url,
      "--test"])
    try: 
      logging.info("Starting terminate instances.")

      options = parse_args.ParseArgs(terminate_args, 
        "appscale-terminate-instances").args
      AppScaleTools.terminate_instances(options)
      self.state = self.TERMINATED_STATE

      logging.info("AppScale terminate instances successfully ran!")
    except BadConfigurationException as bad_config:
      self.state = self.ERROR_STATE
      logging.exception(bad_config)
      self.err_message = "Bad configuration. Unable to terminate AppScale. " \
        "{0}".format(bad_config)
    except Exception as exception:
      self.state = self.ERROR_STATE
      logging.exception(exception)
      self.err_message = "Exception when terminating: {0}".format(exception)
    finally:
      sys.stdout = old_stdout
      sys.stderr = old_stderr

    return self.state == self.TERMINATED_STATE
Example #46
0
    def get(self, property_regex):
        """ 'get' provides a cleaner experience for users than the
    appscale-get-property command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      property_regex: A regular expression indicating which AppController
        properties should be retrieved.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # construct the appscale-get-property command
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--property")
        command.append(property_regex)

        # and exec it
        options = ParseArgs(command, "appscale-get-property").args
        return AppScaleTools.get_property(options)
Example #47
0
  def get(self, property_regex):
    """ 'get' provides a cleaner experience for users than the
    appscale-get-property command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      property_regex: A regular expression indicating which AppController
        properties should be retrieved.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()
    contents_as_yaml = yaml.safe_load(contents)

    # construct the appscale-get-property command
    command = []
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml["keyname"])

    command.append("--property")
    command.append(property_regex)

    # and exec it
    options = ParseArgs(command, "appscale-get-property").args
    return AppScaleTools.get_property(options)
Example #48
0
  def testUpWithEC2EnvironmentVariables(self):
    # if the user wants us to use their EC2 credentials when running AppScale,
    # we should make sure they get set
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1,
      'EC2_ACCESS_KEY' : 'access key',
      'EC2_SECRET_KEY' : 'secret key',
      'zone' : 'my-zone-1b'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # finally, pretend that our ec2 zone/image to use exist
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_all_instances')

    fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
      .and_return('anything')

    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto.ec2)
    boto.ec2.should_receive('connect_to_region').with_args('my-zone-1',
      aws_access_key_id='access key',
      aws_secret_access_key='secret key').and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()

    self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
    self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
Example #49
0
  def testUpWithEC2EnvironmentVariables(self):
    # if the user wants us to use their EC2 credentials when running AppScale,
    # we should make sure they get set
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1,
      'EC2_ACCESS_KEY' : 'access key',
      'EC2_SECRET_KEY' : 'secret key',
      'zone' : 'my-zone-1b'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # finally, pretend that our ec2 zone/image to use exist
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_all_instances')

    fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
      .and_return('anything')

    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto.ec2)
    boto.ec2.should_receive('connect_to_region').with_args('my-zone-1',
      aws_access_key_id='access key',
      aws_secret_access_key='secret key').and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()

    self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
    self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
Example #50
0
  def testUpWithCloudAppScalefile(self):
    # calling 'appscale up' if there is an AppScalefile present
    # should call appscale-run-instances with the given config
    # params. here, we assume that the file is intended for use
    # on EC2
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min' : 1,
      'max' : 1,
      'zone' : 'my-zone-1b'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # throw in some mocks for the argument parsing
    for credential in EC2Agent.REQUIRED_CREDENTIALS:
      os.environ[credential] = "baz"

    # finally, pretend that our ec2 zone and image exists
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_all_instances')

    fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
      .and_return('anything')

    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto.ec2)
    boto.ec2.should_receive('connect_to_region').with_args('my-zone-1',
      aws_access_key_id='baz', aws_secret_access_key='baz').and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()
  def run_appscale(self):
    """ Exectutes the appscale tools once the configuration has been set. """
    self.status = RUNNING_STATE
    options = ParseArgs(self.args, "appscale-run-instances").args

    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = self.std_out_capture
    sys.stderr = self.std_err_capture

    try:
      AppScaleTools.run_instances(options)
    except Exception as e:
      self.status = ERROR_STATE
      self.err_message = str(e)
    finally:
      sys.stdout = old_stdout
      sys.stderr = old_stderr
    def run_appscale(self):
        """ Executes the appscale tools with deployment specific arguments.

    Returns:
      True on success, False otherwise.
    """
        logging.info("Tools arguments: {0}".format(str(self.args)))

        self.state = self.RUNNING_STATE
        old_stdout = sys.stdout
        old_stderr = sys.stderr

        try:
            options = parse_args.ParseArgs(self.args,
                                           "appscale-run-instances").args
            sys.stdout = self.std_out_capture
            sys.stderr = self.std_err_capture

            AppScaleTools.run_instances(options)
            logging.info("AppScale run instances was successful!")
            self.state = self.COMPLETE_STATE
            self.set_status_link()
        except BadConfigurationException as bad_config:
            self.state = self.ERROR_STATE
            logging.exception(bad_config)
            self.err_message = "Bad configuration. {0}".format(bad_config)
        except Exception as exception:
            self.state = self.ERROR_STATE
            logging.exception(exception)
            self.err_message = "Exception--{0}".format(exception)
        except SystemExit as sys_exit:
            self.state = self.ERROR_STATE
            logging.error(str(sys_exit))
            self.err_message = str(
                "Error with given arguments caused system exit.")
        finally:
            sys.stdout = old_stdout
            sys.stderr = old_stderr

        return self.state == self.COMPLETE_STATE
    def testUpWithClusterAppScalefile(self):
        # calling 'appscale up' if there is an AppScalefile present
        # should call appscale-run-instances with the given config
        # params. here, we assume that the file is intended for use
        # on a virtualized cluster
        appscale = AppScale()

        # Mock out the actual file reading itself, and slip in a YAML-dumped
        # file
        contents = {
            'ips_layout': {
                'master': 'ip1',
                'appengine': 'ip1',
                'database': 'ip2',
                'zookeeper': 'ip2'
            },
            'keyname': 'boobazblarg'
        }
        yaml_dumped_contents = yaml.dump(contents)
        base64_ips_layout = base64.b64encode(yaml.dump(contents["ips_layout"]))
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        # for this test, let's say that we don't have an SSH key already
        # set up for ip1 and ip2
        # TODO(cgb): Add in tests where we have a key for ip1 but not ip2,
        # and the case where we have a key but it doesn't work
        flexmock(os.path)
        key_path = os.path.expanduser('~/.appscale/boobazblarg.key')
        os.path.should_call('exists')
        os.path.should_receive('exists').with_args(key_path).and_return(
            False).once()

        # finally, mock out the actual appscale tools calls. since we're running
        # via a cluster, this means we call add-keypair to set up SSH keys, then
        # run-instances to start appscale
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('add_keypair')
        AppScaleTools.should_receive('run_instances')

        appscale.up()
    def testUpWithMalformedClusterAppScalefile(self):
        # if we try to use an IPs layout that isn't a dictionary, we should throw up
        # and die
        appscale = AppScale()

        # Mock out the actual file reading itself, and slip in a YAML-dumped
        # file, with an IPs layout that is a str
        contents = {
            'ips_layout': "'master' 'ip1' 'appengine' 'ip1'",
            'keyname': 'boobazblarg'
        }
        yaml_dumped_contents = yaml.dump(contents)
        base64_ips_layout = base64.b64encode(yaml.dump(contents["ips_layout"]))
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        # finally, mock out the actual appscale tools calls. since we're running
        # via a cluster, this means we call add-keypair to set up SSH keys, then
        # run-instances to start appscale
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('add_keypair')

        self.assertRaises(BadConfigurationException, appscale.up)
    def destroy(self):
        """'destroy' provides a nicer experience for users than the
    appscale-terminate-instances command, by using the configuration options
    present in the AppScalefile found in the current working directory.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()

        # Construct a terminate-instances command from the file's contents
        command = []
        contents_as_yaml = yaml.safe_load(contents)

        if "EC2_ACCESS_KEY" in contents_as_yaml:
            os.environ["EC2_ACCESS_KEY"] = contents_as_yaml["EC2_ACCESS_KEY"]

        if "EC2_SECRET_KEY" in contents_as_yaml:
            os.environ["EC2_SECRET_KEY"] = contents_as_yaml["EC2_SECRET_KEY"]

        if "EC2_URL" in contents_as_yaml:
            os.environ["EC2_URL"] = contents_as_yaml["EC2_URL"]

        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml['keyname'])

        if 'verbose' in contents_as_yaml and contents_as_yaml[
                'verbose'] == True:
            command.append("--verbose")

        if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
            command.append("--test")

        # Finally, exec the command. Don't worry about validating it -
        # appscale-terminate-instances will do that for us.
        options = ParseArgs(command, "appscale-terminate-instances").args
        AppScaleTools.terminate_instances(options)
Example #56
0
  def testUpWithMalformedClusterAppScalefile(self):
    # if we try to use an IPs layout that isn't a dictionary, we should throw up
    # and die
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file, with an IPs layout that is a str
    contents = {
      'ips_layout': "'master' 'ip1' 'appengine' 'ip1'",
      'keyname': 'boobazblarg'
    }
    yaml_dumped_contents = yaml.dump(contents)
    base64_ips_layout = base64.b64encode(yaml.dump(contents["ips_layout"]))
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale tools calls. since we're running
    # via a cluster, this means we call add-keypair to set up SSH keys, then
    # run-instances to start appscale
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('add_keypair')

    self.assertRaises(BadConfigurationException, appscale.up)
Example #57
0
  def status(self):
    """'status' is a more accessible way to query the state of the AppScale
    deployment than 'appscale-describe-instances', and calls it with the
    parameters in the user's AppScalefile.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current
      directory.
    """
    contents = self.read_appscalefile()

    # Construct a describe-instances command from the file's contents
    command = []
    contents_as_yaml = yaml.safe_load(contents)
    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml['keyname'])

    # Finally, exec the command. Don't worry about validating it -
    # appscale-describe-instances will do that for us.
    options = ParseArgs(command, "appscale-describe-instances").args
    AppScaleTools.describe_instances(options)
Example #58
0
    def status(self):
        """ 'status' is a more accessible way to query the state of the AppScale
    deployment than 'appscale-describe-instances', and calls it with the
    parameters in the user's AppScalefile.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current
      directory.
    """
        contents = self.read_appscalefile()

        # Construct a describe-instances command from the file's contents
        command = []
        contents_as_yaml = yaml.safe_load(contents)
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml['keyname'])

        # Finally, exec the command. Don't worry about validating it -
        # appscale-describe-instances will do that for us.
        options = ParseArgs(command, "appscale-describe-instances").args
        AppScaleTools.describe_instances(options)
Example #59
0
    def relocate(self, appid, http_port, https_port):
        """ 'relocate' provides a nicer experience for users than the
    appscale-terminate-instances command, by using the configuration options
    present in the AppScalefile found in the current working directory.

    Args:
      appid: A str indicating the name of the application to relocate.
      http_port: An int that indicates what port should serve HTTP traffic for
        this application.
      https_port: An int that indicates what port should serve HTTPS traffic for
        this application.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # Construct the appscale-relocate-app command from argv and the contents of
        # the AppScalefile.
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--appname")
        command.append(appid)

        command.append("--http_port")
        command.append(str(http_port))

        command.append("--https_port")
        command.append(str(https_port))

        # and exec it
        options = ParseArgs(command, "appscale-relocate-app").args
        AppScaleTools.relocate_app(options)
Example #60
0
  def testSetPropertyWithAppScalefile(self):
    # calling 'appscale set' with an AppScalefile in the local
    # directory should collect any parameters needed for the
    # 'appscale-get-property' command and then exec it
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'verbose' : True,
      'min' : 1,
      'max' : 1
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    # finally, mock out the actual appscale-set-property call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('set_property')
    appscale.set('key', 'value')