Exemplo n.º 1
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))
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
  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
Exemplo n.º 4
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 "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)
Exemplo n.º 5
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 "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)
    def test_terminate_in_virtual_cluster_and_succeeds(self):
        # let's say that there is a locations.yaml file, which means appscale is
        # running, so we should terminate the services on each box
        flexmock(os.path)
        os.path.should_call('exists')  # set up the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return(True)

        # mock out reading the locations.yaml file, and pretend that we're on
        # a virtualized cluster
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')

        fake_yaml_file = flexmock(name='fake_file')
        fake_yaml_file.should_receive('read').and_return(
            yaml.dump({'infrastructure': 'xen'}))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_yaml_location(self.keyname), 'r') \
          .and_return(fake_yaml_file)

        # mock out reading the json file, and pretend that we're running in a
        # two node deployment
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_json_file = flexmock(name='fake_file')
        fake_json_file.should_receive('read').and_return(
            json.dumps([{
                'public_ip': 'public1',
                'jobs': ['shadow']
            }, {
                'public_ip': 'public2',
                'jobs': ['appengine']
            }]))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_json_file)

        # and slip in a fake secret file
        fake_secret_file = flexmock(name='fake_file')
        fake_secret_file.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(
          LocalState.get_secret_key_location(self.keyname), 'r') \
          .and_return(fake_secret_file)

        # mock out talking to the appcontroller, and assume that it tells us there
        # there are still two machines in this deployment
        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)

        # and mock out the ssh call to kill the remote appcontroller, assuming that
        # it fails the first time and passes the second
        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('controller stop'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.failed).and_return(self.success)

        # next, mock out our checks to see how the stopping process is going and
        # assume that it has stopped
        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('ps x'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        # finally, mock out removing the yaml file, json file, and secret key from
        # this machine
        flexmock(os)
        os.should_receive('remove').with_args(
            LocalState.get_locations_yaml_location(self.keyname)).and_return()
        os.should_receive('remove').with_args(
            LocalState.get_locations_json_location(self.keyname)).and_return()
        os.should_receive('remove').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return()

        # also mock out asking the user for confirmation on shutting down
        # their cloud
        builtins.should_receive('raw_input').and_return('yes')

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.terminate_instances(options)
    def test_terminate_in_gce_and_succeeds(self):
        # let's say that there is a locations.yaml file, which means appscale is
        # running, so we should terminate the services on each box
        flexmock(os.path)
        os.path.should_call('exists')  # set up the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_yaml_location(
                self.keyname)).and_return(True)
        os.path.should_receive('exists').with_args(
            LocalState.get_client_secrets_location(
                self.keyname)).and_return(True)
        os.path.should_receive('exists').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return(True)

        # mock out reading the locations.yaml file, and pretend that we're on
        # GCE
        project_id = "1234567890"
        zone = 'my-zone-1b'
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')

        fake_yaml_file = flexmock(name='fake_file')
        fake_yaml_file.should_receive('read').and_return(
            yaml.dump({
                'infrastructure': 'gce',
                'group': self.group,
                'project': project_id,
                'zone': zone
            }))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_yaml_location(self.keyname), 'r') \
          .and_return(fake_yaml_file)

        # mock out reading the json file, and pretend that we're running in a
        # two node deployment
        fake_json_file = flexmock(name='fake_file')
        fake_json_file.should_receive('read').and_return(
            json.dumps([{
                'public_ip': 'public1',
                'jobs': ['shadow']
            }, {
                'public_ip': 'public2',
                'jobs': ['appengine']
            }]))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_json_file)

        # and slip in a fake secret file
        fake_secret_file = flexmock(name='fake_file')
        fake_secret_file.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(
          LocalState.get_secret_key_location(self.keyname), 'r') \
          .and_return(fake_secret_file)

        # also add in a fake client-secrets file for GCE
        client_secrets = LocalState.get_client_secrets_location(self.keyname)

        # mock out talking to GCE
        # first, mock out the oauth library calls
        fake_flow = flexmock(name='fake_flow')
        flexmock(oauth2client.client)
        oauth2client.client.should_receive(
            'flow_from_clientsecrets').with_args(
                client_secrets, scope=str).and_return(fake_flow)

        fake_storage = flexmock(name='fake_storage')
        fake_storage.should_receive('get').and_return(None)

        fake_flags = oauth2client.tools.argparser.parse_args(args=[])

        flexmock(oauth2client.file)
        oauth2client.file.should_receive('Storage').with_args(str).and_return(
            fake_storage)

        fake_credentials = flexmock(name='fake_credentials')
        flexmock(oauth2client.tools)
        oauth2client.tools.should_receive('run_flow').with_args(
            fake_flow, fake_storage, fake_flags).and_return(fake_credentials)

        # next, mock out http calls to GCE
        fake_http = flexmock(name='fake_http')
        fake_authorized_http = flexmock(name='fake_authorized_http')

        flexmock(httplib2)
        httplib2.should_receive('Http').and_return(fake_http)
        fake_credentials.should_receive('authorize').with_args(fake_http) \
          .and_return(fake_authorized_http)

        fake_gce = flexmock(name='fake_gce')

        # let's say that two instances are running
        instance_one_info = {
            u'status':
            u'RUNNING',
            u'kind':
            u'compute#instance',
            u'machineType':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/machineTypes/n1-standard-1',
            u'name':
            u'appscale-bazboogroup-one',
            u'zone':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
            u'tags': {
                u'fingerprint': u'42WmSpB8rSM='
            },
            u'image':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/images/lucid64',
            u'disks': [{
                u'index': 0,
                u'kind': u'compute#attachedDisk',
                u'type': u'EPHEMERAL',
                u'mode': u'READ_WRITE'
            }],
            u'canIpForward':
            False,
            u'serviceAccounts': [{
                u'scopes': [GCEAgent.GCE_SCOPE],
                u'email':
                u'*****@*****.**'
            }],
            u'metadata': {
                u'kind': u'compute#metadata',
                u'fingerprint': u'42WmSpB8rSM='
            },
            u'creationTimestamp':
            u'2013-05-22T11:52:33.254-07:00',
            u'id':
            u'8684033495853907982',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazboogroup-feb10b11-62bc-4536-ac25-9734f2267d6d',
            u'networkInterfaces': [{
                u'accessConfigs': [{
                    u'kind': u'compute#accessConfig',
                    u'type': u'ONE_TO_ONE_NAT',
                    u'name': u'External NAT',
                    u'natIP': u'public1'
                }],
                u'networkIP':
                u'private1',
                u'network':
                u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazboogroup',
                u'name':
                u'nic0'
            }]
        }

        instance_two_info = {
            u'status':
            u'RUNNING',
            u'kind':
            u'compute#instance',
            u'machineType':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/machineTypes/n1-standard-1',
            u'name':
            u'appscale-bazboogroup-two',
            u'zone':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
            u'tags': {
                u'fingerprint': u'42WmSpB8rSM='
            },
            u'image':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/images/lucid64',
            u'disks': [{
                u'index': 0,
                u'kind': u'compute#attachedDisk',
                u'type': u'EPHEMERAL',
                u'mode': u'READ_WRITE'
            }],
            u'canIpForward':
            False,
            u'serviceAccounts': [{
                u'scopes': [GCEAgent.GCE_SCOPE],
                u'email':
                u'*****@*****.**'
            }],
            u'metadata': {
                u'kind': u'compute#metadata',
                u'fingerprint': u'42WmSpB8rSM='
            },
            u'creationTimestamp':
            u'2013-05-22T11:52:33.254-07:00',
            u'id':
            u'8684033495853907982',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazboogroup-feb10b11-62bc-4536-ac25-9734f2267d6d',
            u'networkInterfaces': [{
                u'accessConfigs': [{
                    u'kind': u'compute#accessConfig',
                    u'type': u'ONE_TO_ONE_NAT',
                    u'name': u'External NAT',
                    u'natIP': u'public1'
                }],
                u'networkIP':
                u'private1',
                u'network':
                u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazboogroup',
                u'name':
                u'nic0'
            }]
        }

        list_instance_info = {
            u'items': [instance_one_info, instance_two_info],
            u'kind':
            u'compute#instanceList',
            u'id':
            u'projects/appscale.com:appscale/zones/my-zone-1b/instances',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/961228229472/zones/my-zone-1b/instances'
        }

        fake_list_instance_request = flexmock(
            name='fake_list_instance_request')
        fake_list_instance_request.should_receive('execute').with_args(
            http=fake_authorized_http).and_return(list_instance_info)

        fake_instances = flexmock(name='fake_instances')
        fake_instances.should_receive('list').with_args(project=project_id,
          filter="name eq appscale-bazboogroup-.*", zone=zone) \
          .and_return(fake_list_instance_request)
        fake_gce.should_receive('instances').and_return(fake_instances)

        # And assume that we can kill both of our instances fine
        delete_instance = u'operation-1369676691806-4ddb6b4ab6f39-a095d3de'
        delete_instance_info_one = {
            u'status': u'PENDING',
            u'kind': u'compute#operation',
            u'name': delete_instance,
            u'zone':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
            u'startTime': u'2013-05-27T10:44:51.849-07:00',
            u'insertTime': u'2013-05-27T10:44:51.806-07:00',
            u'targetId': u'12912855597472179535',
            u'targetLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-appscalecgb20-0cf89267-5887-4048-b774-ca20de47a07f',
            u'operationType': u'delete',
            u'progress': 0,
            u'id': u'11114355109942058217',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/operations/operation-1369676691806-4ddb6b4ab6f39-a095d3de',
            u'user': u'*****@*****.**'
        }

        delete_instance_info_two = {
            u'status': u'PENDING',
            u'kind': u'compute#operation',
            u'name': delete_instance,
            u'zone':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
            u'startTime': u'2013-05-27T10:44:51.849-07:00',
            u'insertTime': u'2013-05-27T10:44:51.806-07:00',
            u'targetId': u'12912855597472179535',
            u'targetLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-appscalecgb20-0cf89267-5887-4048-b774-ca20de47a07f',
            u'operationType': u'delete',
            u'progress': 0,
            u'id': u'11114355109942058217',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/operations/operation-1369676691806-4ddb6b4ab6f39-a095d3de',
            u'user': u'*****@*****.**'
        }

        fake_delete_instance_request_one = flexmock(
            name='fake_delete_instance_request_one')
        fake_delete_instance_request_one.should_receive('execute').with_args(
            http=fake_authorized_http).and_return(delete_instance_info_one)
        fake_instances.should_receive('delete').with_args(
            project=project_id, zone=zone,
            instance='appscale-bazboogroup-one').and_return(
                fake_delete_instance_request_one)

        fake_delete_instance_request_two = flexmock(
            name='fake_delete_instance_request_two')
        fake_delete_instance_request_two.should_receive('execute').with_args(
            http=fake_authorized_http).and_return(delete_instance_info_two)
        fake_instances.should_receive('delete').with_args(
            project=project_id, zone=zone,
            instance='appscale-bazboogroup-two').and_return(
                fake_delete_instance_request_two)

        # mock out our waiting for the instances to be deleted
        all_done = {u'status': u'DONE'}

        fake_instance_checker = flexmock(name='fake_instance_checker')
        fake_instance_checker.should_receive('execute').and_return(all_done)

        fake_blocker = flexmock(name='fake_blocker')
        fake_blocker.should_receive('get').with_args(
            project=project_id, operation=delete_instance,
            zone=zone).and_return(fake_instance_checker)
        fake_gce.should_receive('zoneOperations').and_return(fake_blocker)

        # mock out the call to delete the firewall
        delete_firewall = u'operation-1369677695390-4ddb6f07cc611-5a8f1654'
        fake_delete_firewall_info = {
            u'status': u'PENDING',
            u'kind': u'compute#operation',
            u'name': delete_firewall,
            u'startTime': u'2013-05-27T11:01:35.482-07:00',
            u'insertTime': u'2013-05-27T11:01:35.390-07:00',
            u'targetId': u'11748720697396371259',
            u'targetLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/firewalls/appscalecgb20',
            u'operationType': u'delete',
            u'progress': 0,
            u'id': u'15574488986772298961',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/operations/operation-1369677695390-4ddb6f07cc611-5a8f1654',
            u'user': u'*****@*****.**'
        }
        fake_delete_firewall_request = flexmock(
            name='fake_delete_firewall_request')
        fake_delete_firewall_request.should_receive('execute').and_return(
            fake_delete_firewall_info)

        fake_firewalls = flexmock(name='fake_firewalls')
        fake_firewalls.should_receive('delete').with_args(
            project=project_id,
            firewall=self.group).and_return(fake_delete_firewall_request)
        fake_gce.should_receive('firewalls').and_return(fake_firewalls)

        # mock out the call to make sure the firewall was deleted
        fake_firewall_checker = flexmock(name='fake_firewall_checker')
        fake_firewall_checker.should_receive('execute').and_return(all_done)

        fake_blocker.should_receive('get').with_args(
            project=project_id,
            operation=delete_firewall).and_return(fake_firewall_checker)
        fake_gce.should_receive('globalOperations').and_return(fake_blocker)

        # and the call to delete the network
        delete_network = u'operation-1369677749954-4ddb6f3bd1849-056cf8ca'
        fake_delete_network_info = {
            u'status': u'PENDING',
            u'kind': u'compute#operation',
            u'name': delete_network,
            u'startTime': u'2013-05-27T11:02:30.012-07:00',
            u'insertTime': u'2013-05-27T11:02:29.954-07:00',
            u'targetId': u'17688075350400527692',
            u'targetLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/appscalecgb20',
            u'operationType': u'delete',
            u'progress': 0,
            u'id': u'12623697331874594836',
            u'selfLink':
            u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/operations/operation-1369677749954-4ddb6f3bd1849-056cf8ca',
            u'user': u'*****@*****.**'
        }
        fake_delete_network_request = flexmock(
            name='fake_delete_network_request')
        fake_delete_network_request.should_receive('execute').and_return(
            fake_delete_network_info)

        fake_networks = flexmock(name='fake_networks')
        fake_networks.should_receive('delete').with_args(
            project=project_id,
            network=self.group).and_return(fake_delete_network_request)
        fake_gce.should_receive('networks').and_return(fake_networks)

        # mock out the call to make sure the network was deleted
        fake_network_checker = flexmock(name='fake_network_checker')
        fake_network_checker.should_receive('execute').and_return(all_done)

        fake_blocker.should_receive('get').with_args(
            project=project_id,
            operation=delete_network).and_return(fake_network_checker)

        # finally, inject our fake GCE connection
        flexmock(apiclient.discovery)
        apiclient.discovery.should_receive('build').with_args(
            'compute', GCEAgent.API_VERSION).and_return(fake_gce)

        # finally, mock out removing the yaml file, json file, and secret key from
        # this machine
        flexmock(os)
        os.should_receive('remove').with_args(
            LocalState.get_locations_yaml_location(self.keyname)).and_return()
        os.should_receive('remove').with_args(
            LocalState.get_locations_json_location(self.keyname)).and_return()
        os.should_receive('remove').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return()

        argv = ["--keyname", self.keyname, "--test"]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.terminate_instances(options)
    def test_terminate_in_cloud_and_succeeds(self):
        # let's say that there is a locations.yaml file, which means appscale is
        # running, so we should terminate the services on each box
        flexmock(os.path)
        os.path.should_call('exists')  # set up the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return(True)

        # mock out reading the locations.yaml file, and pretend that we're on
        # a virtualized cluster
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')

        fake_yaml_file = flexmock(name='fake_file')
        fake_yaml_file.should_receive('read').and_return(
            yaml.dump({
                'infrastructure': 'ec2',
                'group': self.group,
            }))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_yaml_location(self.keyname), 'r') \
          .and_return(fake_yaml_file)

        # mock out reading the json file, and pretend that we're running in a
        # two node deployment
        fake_json_file = flexmock(name='fake_file')
        fake_json_file.should_receive('read').and_return(
            json.dumps([{
                'public_ip': 'public1',
                'jobs': ['shadow']
            }, {
                'public_ip': 'public2',
                'jobs': ['appengine']
            }]))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_json_file)

        # and slip in a fake secret file
        fake_secret_file = flexmock(name='fake_file')
        fake_secret_file.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(
          LocalState.get_secret_key_location(self.keyname), 'r') \
          .and_return(fake_secret_file)

        # mock out talking to EC2
        fake_ec2 = flexmock(name='fake_ec2')

        # let's say that three instances are running, and that two of them are in
        # our deployment
        fake_one_running = flexmock(name='fake_one',
                                    key_name=self.keyname,
                                    state='running',
                                    id='i-ONE',
                                    public_dns_name='public1',
                                    private_dns_name='private1')
        fake_two_running = flexmock(name='fake_two',
                                    key_name=self.keyname,
                                    state='running',
                                    id='i-TWO',
                                    public_dns_name='public2',
                                    private_dns_name='private2')
        fake_three_running = flexmock(name='fake_three',
                                      key_name='abcdefg',
                                      state='running',
                                      id='i-THREE',
                                      public_dns_name='public3',
                                      private_dns_name='private3')
        fake_reservation_running = flexmock(
            name='fake_reservation',
            instances=[fake_one_running, fake_two_running, fake_three_running])

        fake_one_terminated = flexmock(name='fake_one',
                                       key_name=self.keyname,
                                       state='terminated',
                                       id='i-ONE',
                                       public_dns_name='public1',
                                       private_dns_name='private1')
        fake_two_terminated = flexmock(name='fake_two',
                                       key_name=self.keyname,
                                       state='terminated',
                                       id='i-TWO',
                                       public_dns_name='public2',
                                       private_dns_name='private2')
        fake_three_terminated = flexmock(name='fake_three',
                                         key_name='abcdefg',
                                         state='terminated',
                                         id='i-THREE',
                                         public_dns_name='public3',
                                         private_dns_name='private3')
        fake_reservation_terminated = flexmock(name='fake_reservation',
                                               instances=[
                                                   fake_one_terminated,
                                                   fake_two_terminated,
                                                   fake_three_terminated
                                               ])

        fake_ec2.should_receive('get_all_instances').and_return(fake_reservation_running) \
          .and_return(fake_reservation_terminated)

        flexmock(boto.ec2)
        boto.ec2.should_receive('connect_to_region').and_return(fake_ec2)

        # and mock out the call to kill the instances
        fake_ec2.should_receive('terminate_instances').with_args(
            ['i-ONE',
             'i-TWO']).and_return([fake_one_terminated, fake_two_terminated])

        # mock out the call to delete the keypair
        fake_ec2.should_receive('delete_key_pair').and_return()

        # and the call to delete the security group - let's say that we can't
        # delete the group the first time, and can the second
        fake_ec2.should_receive('delete_security_group').and_return(False) \
          .and_return(True)

        # finally, mock out removing the yaml file, json file, and secret key from
        # this machine
        flexmock(os)
        os.should_receive('remove').with_args(
            LocalState.get_locations_yaml_location(self.keyname)).and_return()
        os.should_receive('remove').with_args(
            LocalState.get_locations_json_location(self.keyname)).and_return()
        os.should_receive('remove').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return()

        # also mock out asking the user for confirmation on shutting down
        # their cloud
        builtins.should_receive('raw_input').and_return('yes')

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.terminate_instances(options)
  def test_terminate_in_virtual_cluster_and_succeeds(self):
    # let's say that there is a locations.yaml file, which means appscale is
    # running, so we should terminate the services on each box
    flexmock(os.path)
    os.path.should_call('exists')  # set up the fall-through
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_yaml_location(self.keyname)).and_return(True)

    # mock out reading the locations.yaml file, and pretend that we're on
    # a virtualized cluster
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')

    fake_yaml_file = flexmock(name='fake_file')
    fake_yaml_file.should_receive('read').and_return(yaml.dump({
      'infrastructure' : 'xen'
    }))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_yaml_location(self.keyname), 'r') \
      .and_return(fake_yaml_file)

    # mock out reading the json file, and pretend that we're running in a
    # two node deployment
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return(True)

    fake_json_file = flexmock(name='fake_file')
    fake_json_file.should_receive('read').and_return(json.dumps([
      {
        'public_ip' : 'public1',
        'jobs' : ['shadow']
      },
      {
        'public_ip' : 'public2',
        'jobs' : ['appengine']
      }
    ]))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_json_file)

    # and slip in a fake secret file
    fake_secret_file = flexmock(name='fake_file')
    fake_secret_file.should_receive('read').and_return('the secret')
    builtins.should_receive('open').with_args(
      LocalState.get_secret_key_location(self.keyname), 'r') \
      .and_return(fake_secret_file)

    # mock out talking to the appcontroller, and assume that it tells us there
    # there are still two machines in this deployment
    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)

    # and mock out the ssh call to kill the remote appcontroller, assuming that
    # it fails the first time and passes the second
    flexmock(subprocess)
    subprocess.should_receive('Popen').with_args(re.compile('controller stop'),
      shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
      .and_return(self.failed).and_return(self.success)

    # next, mock out our checks to see how the stopping process is going and
    # assume that it has stopped
    flexmock(subprocess)
    subprocess.should_receive('Popen').with_args(re.compile('ps x'),
      shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
      .and_return(self.success)

    # finally, mock out removing the yaml file, json file, and secret key from
    # this machine
    flexmock(os)
    os.should_receive('remove').with_args(
      LocalState.get_locations_yaml_location(self.keyname)).and_return()
    os.should_receive('remove').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return()
    os.should_receive('remove').with_args(
      LocalState.get_secret_key_location(self.keyname)).and_return()

    argv = [
      "--keyname", self.keyname
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.terminate_instances(options)
  def test_terminate_in_cloud_and_succeeds(self):
    # let's say that there is a locations.yaml file, which means appscale is
    # running, so we should terminate the services on each box
    flexmock(os.path)
    os.path.should_call('exists')  # set up the fall-through
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_yaml_location(self.keyname)).and_return(True)

    # mock out reading the locations.yaml file, and pretend that we're on
    # a virtualized cluster
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')

    fake_yaml_file = flexmock(name='fake_file')
    fake_yaml_file.should_receive('read').and_return(yaml.dump({
      'infrastructure' : 'ec2',
      'group' : 'bazboogroup'
    }))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_yaml_location(self.keyname), 'r') \
      .and_return(fake_yaml_file)

    # mock out reading the json file, and pretend that we're running in a
    # two node deployment
    fake_json_file = flexmock(name='fake_file')
    fake_json_file.should_receive('read').and_return(json.dumps([
      {
        'public_ip' : 'public1',
        'jobs' : ['shadow']
      },
      {
        'public_ip' : 'public2',
        'jobs' : ['appengine']
      }
    ]))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_json_file)

    # and slip in a fake secret file
    fake_secret_file = flexmock(name='fake_file')
    fake_secret_file.should_receive('read').and_return('the secret')
    builtins.should_receive('open').with_args(
      LocalState.get_secret_key_location(self.keyname), 'r') \
      .and_return(fake_secret_file)

    # mock out talking to EC2
    fake_ec2 = flexmock(name='fake_ec2')

    # let's say that three instances are running, and that two of them are in
    # our deployment
    fake_one = flexmock(name='fake_one', key_name=self.keyname, state='running',
      id='i-ONE', public_dns_name='public1', private_dns_name='private1')
    fake_two = flexmock(name='fake_two', key_name=self.keyname, state='running',
      id='i-TWO', public_dns_name='public2', private_dns_name='private2')
    fake_three = flexmock(name='fake_three', key_name='abcdefg',
      state='running', id='i-THREE', public_dns_name='public3',
      private_dns_name='private3')

    fake_reservation = flexmock(name='fake_reservation', instances=[fake_one,
      fake_two, fake_three])
    fake_ec2.should_receive('get_all_instances').and_return(fake_reservation)

    flexmock(boto)
    boto.should_receive('connect_ec2').with_args('baz', 'baz') \
      .and_return(fake_ec2)

    # and mock out the call to kill the instances
    fake_ec2.should_receive('terminate_instances').with_args(['i-ONE',
      'i-TWO']).and_return([fake_one, fake_two])

    # mock out the call to delete the keypair
    fake_ec2.should_receive('delete_key_pair').and_return()

    # and the call to delete the security group - let's say that we can't
    # delete the group the first time, and can the second
    fake_ec2.should_receive('delete_security_group').and_return(False) \
      .and_return(True)

    # finally, mock out removing the yaml file, json file, and secret key from
    # this machine
    flexmock(os)
    os.should_receive('remove').with_args(
      LocalState.get_locations_yaml_location(self.keyname)).and_return()
    os.should_receive('remove').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return()
    os.should_receive('remove').with_args(
      LocalState.get_secret_key_location(self.keyname)).and_return()

    argv = [
      "--keyname", self.keyname
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.terminate_instances(options)
Exemplo n.º 11
0
    def down(self, clean=False, terminate=False):
        """ 'down' 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:
      clean: A boolean to indicate if the deployment data and metadata
        needs to be clean. This will clear the datastore.
      terminate: A boolean to indicate if instances needs to be terminated
        (valid only if we spawn instances at start).

    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 'verbose' in contents_as_yaml and contents_as_yaml[
                'verbose'] == True:
            is_verbose = contents_as_yaml['verbose']
            command.append("--verbose")
        else:
            is_verbose = False

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

        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 clean:
            if 'test' not in contents_as_yaml or contents_as_yaml[
                    'test'] != True:
                LocalState.confirm_or_abort(
                    "Clean will delete every data in the deployment.")
            all_ips = LocalState.get_all_public_ips(keyname)
            for ip in all_ips:
                RemoteHelper.ssh(ip, keyname, self.TERMINATE, is_verbose)
            AppScaleLogger.success(
                "Successfully cleaned your AppScale deployment.")

        if terminate:
            infrastructure = LocalState.get_infrastructure(keyname)
            if infrastructure != "xen" and not LocalState.are_disks_used(
                    keyname) and 'test' not in contents_as_yaml:
                LocalState.confirm_or_abort(
                    "Terminate will delete instances and the data on them.")
            command.append("--terminate")

        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)

        LocalState.cleanup_appscale_files(keyname, terminate)
        AppScaleLogger.success(
            "Successfully shut down your AppScale deployment.")
  def test_terminate_in_gce_and_succeeds(self):
    # let's say that there is a locations.yaml file, which means appscale is
    # running, so we should terminate the services on each box
    flexmock(os.path)
    os.path.should_call('exists')  # set up the fall-through
    os.path.should_receive('exists').with_args(
      LocalState.get_locations_yaml_location(self.keyname)).and_return(True)
    os.path.should_receive('exists').with_args(
      LocalState.get_client_secrets_location(self.keyname)).and_return(True)
    os.path.should_receive('exists').with_args(
      LocalState.get_secret_key_location(self.keyname)).and_return(True)

    # mock out reading the locations.yaml file, and pretend that we're on
    # GCE
    project_id = "1234567890"
    zone = 'my-zone-1b'
    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')

    fake_yaml_file = flexmock(name='fake_file')
    fake_yaml_file.should_receive('read').and_return(yaml.dump({
      'infrastructure' : 'gce',
      'group' : self.group,
      'project' : project_id,
      'zone' : zone
    }))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_yaml_location(self.keyname), 'r') \
      .and_return(fake_yaml_file)

    # mock out reading the json file, and pretend that we're running in a
    # two node deployment
    fake_json_file = flexmock(name='fake_file')
    fake_json_file.should_receive('read').and_return(json.dumps([
      {
        'public_ip' : 'public1',
        'jobs' : ['shadow']
      },
      {
        'public_ip' : 'public2',
        'jobs' : ['appengine']
      }
    ]))
    builtins.should_receive('open').with_args(
      LocalState.get_locations_json_location(self.keyname), 'r') \
      .and_return(fake_json_file)

    # and slip in a fake secret file
    fake_secret_file = flexmock(name='fake_file')
    fake_secret_file.should_receive('read').and_return('the secret')
    builtins.should_receive('open').with_args(
      LocalState.get_secret_key_location(self.keyname), 'r') \
      .and_return(fake_secret_file)

    # also add in a fake client-secrets file for GCE
    client_secrets = LocalState.get_client_secrets_location(self.keyname)

    # mock out talking to GCE
    # first, mock out the oauth library calls
    fake_flow = flexmock(name='fake_flow')
    flexmock(oauth2client.client)
    oauth2client.client.should_receive('flow_from_clientsecrets').with_args(
      client_secrets, scope=str).and_return(fake_flow)

    fake_storage = flexmock(name='fake_storage')
    fake_storage.should_receive('get').and_return(None)

    flexmock(oauth2client.file)
    oauth2client.file.should_receive('Storage').with_args(str).and_return(
      fake_storage)

    fake_credentials = flexmock(name='fake_credentials')
    flexmock(oauth2client.tools)
    oauth2client.tools.should_receive('run').with_args(fake_flow,
      fake_storage).and_return(fake_credentials)

    # next, mock out http calls to GCE
    fake_http = flexmock(name='fake_http')
    fake_authorized_http = flexmock(name='fake_authorized_http')

    flexmock(httplib2)
    httplib2.should_receive('Http').and_return(fake_http)
    fake_credentials.should_receive('authorize').with_args(fake_http) \
      .and_return(fake_authorized_http)

    fake_gce = flexmock(name='fake_gce')

    # let's say that two instances are running
    instance_one_info = {
      u'status': u'RUNNING',
      u'kind': u'compute#instance',
      u'machineType': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/machineTypes/n1-standard-1',
      u'name': u'appscale-bazboogroup-one',
      u'zone': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
      u'tags': {u'fingerprint': u'42WmSpB8rSM='},
      u'image': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/images/lucid64',
      u'disks': [{
        u'index': 0,
        u'kind': u'compute#attachedDisk',
        u'type': u'EPHEMERAL',
        u'mode': u'READ_WRITE'
      }],
      u'canIpForward': False,
      u'serviceAccounts': [{
        u'scopes': [GCEAgent.GCE_SCOPE],
        u'email': u'*****@*****.**'
      }],
      u'metadata': {
        u'kind': u'compute#metadata',
        u'fingerprint': u'42WmSpB8rSM='
      },
      u'creationTimestamp': u'2013-05-22T11:52:33.254-07:00',
      u'id': u'8684033495853907982',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazboogroup-feb10b11-62bc-4536-ac25-9734f2267d6d',
      u'networkInterfaces': [{
        u'accessConfigs': [{
          u'kind': u'compute#accessConfig',
          u'type': u'ONE_TO_ONE_NAT',
          u'name': u'External NAT',
          u'natIP': u'public1'
        }],
        u'networkIP': u'private1',
        u'network': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazboogroup',
        u'name': u'nic0'
      }]
    }

    instance_two_info = {
      u'status': u'RUNNING',
      u'kind': u'compute#instance',
      u'machineType': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/machineTypes/n1-standard-1',
      u'name': u'appscale-bazboogroup-two',
      u'zone': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
      u'tags': {u'fingerprint': u'42WmSpB8rSM='},
      u'image': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/images/lucid64',
      u'disks': [{
        u'index': 0,
        u'kind': u'compute#attachedDisk',
        u'type': u'EPHEMERAL',
        u'mode': u'READ_WRITE'
      }],
      u'canIpForward': False,
      u'serviceAccounts': [{
        u'scopes': [GCEAgent.GCE_SCOPE],
        u'email': u'*****@*****.**'
      }],
      u'metadata': {
        u'kind': u'compute#metadata',
        u'fingerprint': u'42WmSpB8rSM='
      },
      u'creationTimestamp': u'2013-05-22T11:52:33.254-07:00',
      u'id': u'8684033495853907982',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazboogroup-feb10b11-62bc-4536-ac25-9734f2267d6d',
      u'networkInterfaces': [{
        u'accessConfigs': [{
          u'kind': u'compute#accessConfig',
          u'type': u'ONE_TO_ONE_NAT',
          u'name': u'External NAT',
          u'natIP': u'public1'
        }],
        u'networkIP': u'private1',
        u'network': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazboogroup',
        u'name': u'nic0'
      }]
    }

    list_instance_info = {
      u'items': [instance_one_info, instance_two_info],
      u'kind': u'compute#instanceList',
      u'id': u'projects/appscale.com:appscale/zones/my-zone-1b/instances',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/961228229472/zones/my-zone-1b/instances'
    }

    fake_list_instance_request = flexmock(name='fake_list_instance_request')
    fake_list_instance_request.should_receive('execute').with_args(
      http=fake_authorized_http).and_return(list_instance_info)

    fake_instances = flexmock(name='fake_instances')
    fake_instances.should_receive('list').with_args(project=project_id,
      filter="name eq appscale-bazboogroup-.*", zone=zone) \
      .and_return(fake_list_instance_request)
    fake_gce.should_receive('instances').and_return(fake_instances)

    # And assume that we can kill both of our instances fine
    delete_instance = u'operation-1369676691806-4ddb6b4ab6f39-a095d3de'
    delete_instance_info_one = {
      u'status': u'PENDING',
      u'kind': u'compute#operation',
      u'name': delete_instance,
      u'zone': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
      u'startTime': u'2013-05-27T10:44:51.849-07:00',
      u'insertTime': u'2013-05-27T10:44:51.806-07:00',
      u'targetId': u'12912855597472179535',
      u'targetLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-appscalecgb20-0cf89267-5887-4048-b774-ca20de47a07f',
      u'operationType': u'delete',
      u'progress': 0,
      u'id': u'11114355109942058217',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/operations/operation-1369676691806-4ddb6b4ab6f39-a095d3de',
      u'user': u'*****@*****.**'
    }

    delete_instance_info_two = {
      u'status': u'PENDING',
      u'kind': u'compute#operation',
      u'name': delete_instance,
      u'zone': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b',
      u'startTime': u'2013-05-27T10:44:51.849-07:00',
      u'insertTime': u'2013-05-27T10:44:51.806-07:00',
      u'targetId': u'12912855597472179535',
      u'targetLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-appscalecgb20-0cf89267-5887-4048-b774-ca20de47a07f',
      u'operationType': u'delete',
      u'progress': 0,
      u'id': u'11114355109942058217',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/operations/operation-1369676691806-4ddb6b4ab6f39-a095d3de',
      u'user': u'*****@*****.**'
    }

    fake_delete_instance_request_one = flexmock(name='fake_delete_instance_request_one')
    fake_delete_instance_request_one.should_receive('execute').with_args(
      http=fake_authorized_http).and_return(delete_instance_info_one)
    fake_instances.should_receive('delete').with_args(project=project_id,
      zone=zone, instance='appscale-bazboogroup-one').and_return(
      fake_delete_instance_request_one)

    fake_delete_instance_request_two = flexmock(name='fake_delete_instance_request_two')
    fake_delete_instance_request_two.should_receive('execute').with_args(
      http=fake_authorized_http).and_return(delete_instance_info_two)
    fake_instances.should_receive('delete').with_args(project=project_id,
      zone=zone, instance='appscale-bazboogroup-two').and_return(
      fake_delete_instance_request_two)

    # mock out our waiting for the instances to be deleted
    all_done = {
      u'status' : u'DONE'
    }

    fake_instance_checker = flexmock(name='fake_instance_checker')
    fake_instance_checker.should_receive('execute').and_return(all_done)

    fake_blocker = flexmock(name='fake_blocker')
    fake_blocker.should_receive('get').with_args(project=project_id,
      operation=delete_instance, zone=zone).and_return(
      fake_instance_checker)
    fake_gce.should_receive('zoneOperations').and_return(fake_blocker)

    # mock out the call to delete the firewall
    delete_firewall = u'operation-1369677695390-4ddb6f07cc611-5a8f1654'
    fake_delete_firewall_info = {
      u'status': u'PENDING',
      u'kind': u'compute#operation',
      u'name': delete_firewall,
      u'startTime': u'2013-05-27T11:01:35.482-07:00',
      u'insertTime': u'2013-05-27T11:01:35.390-07:00',
      u'targetId': u'11748720697396371259',
      u'targetLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/firewalls/appscalecgb20',
      u'operationType': u'delete',
      u'progress': 0,
      u'id': u'15574488986772298961',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/operations/operation-1369677695390-4ddb6f07cc611-5a8f1654',
      u'user': u'*****@*****.**'
    }
    fake_delete_firewall_request = flexmock(name='fake_delete_firewall_request')
    fake_delete_firewall_request.should_receive('execute').and_return(fake_delete_firewall_info)

    fake_firewalls = flexmock(name='fake_firewalls')
    fake_firewalls.should_receive('delete').with_args(project=project_id,
      firewall=self.group).and_return(fake_delete_firewall_request)
    fake_gce.should_receive('firewalls').and_return(fake_firewalls)

    # mock out the call to make sure the firewall was deleted
    fake_firewall_checker = flexmock(name='fake_firewall_checker')
    fake_firewall_checker.should_receive('execute').and_return(all_done)

    fake_blocker.should_receive('get').with_args(project=project_id,
      operation=delete_firewall).and_return(fake_firewall_checker)
    fake_gce.should_receive('globalOperations').and_return(fake_blocker)

    # and the call to delete the network
    delete_network = u'operation-1369677749954-4ddb6f3bd1849-056cf8ca'
    fake_delete_network_info = {
      u'status': u'PENDING',
      u'kind': u'compute#operation',
      u'name': delete_network,
      u'startTime': u'2013-05-27T11:02:30.012-07:00',
      u'insertTime': u'2013-05-27T11:02:29.954-07:00',
      u'targetId': u'17688075350400527692',
      u'targetLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/appscalecgb20',
      u'operationType': u'delete',
      u'progress': 0,
      u'id': u'12623697331874594836',
      u'selfLink': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/operations/operation-1369677749954-4ddb6f3bd1849-056cf8ca',
      u'user': u'*****@*****.**'
    }
    fake_delete_network_request = flexmock(name='fake_delete_network_request')
    fake_delete_network_request.should_receive('execute').and_return(fake_delete_network_info)

    fake_networks = flexmock(name='fake_networks')
    fake_networks.should_receive('delete').with_args(project=project_id,
      network=self.group).and_return(fake_delete_network_request)
    fake_gce.should_receive('networks').and_return(fake_networks)

    # mock out the call to make sure the network was deleted
    fake_network_checker = flexmock(name='fake_network_checker')
    fake_network_checker.should_receive('execute').and_return(all_done)

    fake_blocker.should_receive('get').with_args(project=project_id,
      operation=delete_network).and_return(fake_network_checker)

    # finally, inject our fake GCE connection
    flexmock(apiclient.discovery)
    apiclient.discovery.should_receive('build').with_args('compute',
      GCEAgent.API_VERSION).and_return(fake_gce)

    # finally, mock out removing the yaml file, json file, and secret key from
    # this machine
    flexmock(os)
    os.should_receive('remove').with_args(
      LocalState.get_locations_yaml_location(self.keyname)).and_return()
    os.should_receive('remove').with_args(
      LocalState.get_locations_json_location(self.keyname)).and_return()
    os.should_receive('remove').with_args(
      LocalState.get_secret_key_location(self.keyname)).and_return()

    argv = [
      "--keyname", self.keyname,
      "--test"
    ]
    options = ParseArgs(argv, self.function).args
    AppScaleTools.terminate_instances(options)
    def test_terminate_in_virtual_cluster_and_succeeds(self):
        # let's say that there is a locations.yaml file, which means appscale is
        # running, so we should terminate the services on each box
        flexmock(os.path)
        os.path.should_call("exists")  # set up the fall-through
        os.path.should_receive("exists").with_args(LocalState.get_secret_key_location(self.keyname)).and_return(True)

        # mock out reading the locations.yaml file, and pretend that we're on
        # a virtualized cluster
        builtins = flexmock(sys.modules["__builtin__"])
        builtins.should_call("open")

        fake_yaml_file = flexmock(name="fake_file")
        fake_yaml_file.should_receive("read").and_return(yaml.dump({"infrastructure": "xen"}))
        builtins.should_receive("open").with_args(LocalState.get_locations_yaml_location(self.keyname), "r").and_return(
            fake_yaml_file
        )

        # mock out reading the json file, and pretend that we're running in a
        # two node deployment
        os.path.should_receive("exists").with_args(LocalState.get_locations_json_location(self.keyname)).and_return(
            True
        )

        fake_json_file = flexmock(name="fake_file")
        fake_json_file.should_receive("read").and_return(
            json.dumps([{"public_ip": "public1", "jobs": ["shadow"]}, {"public_ip": "public2", "jobs": ["appengine"]}])
        )
        builtins.should_receive("open").with_args(LocalState.get_locations_json_location(self.keyname), "r").and_return(
            fake_json_file
        )

        # and slip in a fake secret file
        fake_secret_file = flexmock(name="fake_file")
        fake_secret_file.should_receive("read").and_return("the secret")
        builtins.should_receive("open").with_args(LocalState.get_secret_key_location(self.keyname), "r").and_return(
            fake_secret_file
        )

        # mock out talking to the appcontroller, and assume that it tells us there
        # there are still two machines in this deployment
        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)

        # and mock out the ssh call to kill the remote appcontroller, assuming that
        # it fails the first time and passes the second
        flexmock(subprocess)
        subprocess.should_receive("Popen").with_args(
            re.compile("controller stop"), shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT
        ).and_return(self.failed).and_return(self.success)

        # next, mock out our checks to see how the stopping process is going and
        # assume that it has stopped
        flexmock(subprocess)
        subprocess.should_receive("Popen").with_args(
            re.compile("ps x"), shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT
        ).and_return(self.success)

        # finally, mock out removing the yaml file, json file, and secret key from
        # this machine
        flexmock(os)
        os.should_receive("remove").with_args(LocalState.get_locations_yaml_location(self.keyname)).and_return()
        os.should_receive("remove").with_args(LocalState.get_locations_json_location(self.keyname)).and_return()
        os.should_receive("remove").with_args(LocalState.get_secret_key_location(self.keyname)).and_return()

        # also mock out asking the user for confirmation on shutting down
        # their cloud
        builtins.should_receive("raw_input").and_return("yes")

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.terminate_instances(options)
    def test_terminate_in_gce_and_succeeds(self):
        # let's say that there is a locations.yaml file, which means appscale is
        # running, so we should terminate the services on each box
        flexmock(os.path)
        os.path.should_call("exists")  # set up the fall-through
        os.path.should_receive("exists").with_args(LocalState.get_secret_key_location(self.keyname)).and_return(True)
        os.path.should_receive("exists").with_args(LocalState.get_locations_yaml_location(self.keyname)).and_return(
            True
        )
        os.path.should_receive("exists").with_args(LocalState.get_client_secrets_location(self.keyname)).and_return(
            True
        )

        # mock out reading the locations.yaml file, and pretend that we're on
        # GCE
        project_id = "1234567890"
        zone = "my-zone-1b"
        builtins = flexmock(sys.modules["__builtin__"])
        builtins.should_call("open")

        fake_yaml_file = flexmock(name="fake_file")
        fake_yaml_file.should_receive("read").and_return(
            yaml.dump({"infrastructure": "gce", "group": self.group, "project": project_id, "zone": zone})
        )
        builtins.should_receive("open").with_args(LocalState.get_locations_yaml_location(self.keyname), "r").and_return(
            fake_yaml_file
        )

        # mock out reading the json file, and pretend that we're running in a
        # two node deployment
        fake_json_file = flexmock(name="fake_file")
        fake_json_file.should_receive("read").and_return(
            json.dumps([{"public_ip": "public1", "jobs": ["shadow"]}, {"public_ip": "public2", "jobs": ["appengine"]}])
        )
        builtins.should_receive("open").with_args(LocalState.get_locations_json_location(self.keyname), "r").and_return(
            fake_json_file
        )

        # and slip in a fake secret file
        fake_secret_file = flexmock(name="fake_file")
        fake_secret_file.should_receive("read").and_return("the secret")
        builtins.should_receive("open").with_args(LocalState.get_secret_key_location(self.keyname), "r").and_return(
            fake_secret_file
        )

        # also add in a fake client-secrets file for GCE
        client_secrets = LocalState.get_client_secrets_location(self.keyname)

        # mock out talking to GCE
        # first, mock out the oauth library calls
        fake_flow = flexmock(name="fake_flow")
        flexmock(oauth2client.client)
        oauth2client.client.should_receive("flow_from_clientsecrets").with_args(client_secrets, scope=str).and_return(
            fake_flow
        )

        fake_storage = flexmock(name="fake_storage")
        fake_storage.should_receive("get").and_return(None)

        flexmock(oauth2client.file)
        oauth2client.file.should_receive("Storage").with_args(str).and_return(fake_storage)

        fake_credentials = flexmock(name="fake_credentials")
        flexmock(oauth2client.tools)
        oauth2client.tools.should_receive("run").with_args(fake_flow, fake_storage).and_return(fake_credentials)

        # next, mock out http calls to GCE
        fake_http = flexmock(name="fake_http")
        fake_authorized_http = flexmock(name="fake_authorized_http")

        flexmock(httplib2)
        httplib2.should_receive("Http").and_return(fake_http)
        fake_credentials.should_receive("authorize").with_args(fake_http).and_return(fake_authorized_http)

        fake_gce = flexmock(name="fake_gce")

        # let's say that two instances are running
        instance_one_info = {
            u"status": u"RUNNING",
            u"kind": u"compute#instance",
            u"machineType": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/machineTypes/n1-standard-1",
            u"name": u"appscale-bazboogroup-one",
            u"zone": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b",
            u"tags": {u"fingerprint": u"42WmSpB8rSM="},
            u"image": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/images/lucid64",
            u"disks": [{u"index": 0, u"kind": u"compute#attachedDisk", u"type": u"EPHEMERAL", u"mode": u"READ_WRITE"}],
            u"canIpForward": False,
            u"serviceAccounts": [
                {u"scopes": [GCEAgent.GCE_SCOPE], u"email": u"*****@*****.**"}
            ],
            u"metadata": {u"kind": u"compute#metadata", u"fingerprint": u"42WmSpB8rSM="},
            u"creationTimestamp": u"2013-05-22T11:52:33.254-07:00",
            u"id": u"8684033495853907982",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazboogroup-feb10b11-62bc-4536-ac25-9734f2267d6d",
            u"networkInterfaces": [
                {
                    u"accessConfigs": [
                        {
                            u"kind": u"compute#accessConfig",
                            u"type": u"ONE_TO_ONE_NAT",
                            u"name": u"External NAT",
                            u"natIP": u"public1",
                        }
                    ],
                    u"networkIP": u"private1",
                    u"network": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazboogroup",
                    u"name": u"nic0",
                }
            ],
        }

        instance_two_info = {
            u"status": u"RUNNING",
            u"kind": u"compute#instance",
            u"machineType": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/machineTypes/n1-standard-1",
            u"name": u"appscale-bazboogroup-two",
            u"zone": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b",
            u"tags": {u"fingerprint": u"42WmSpB8rSM="},
            u"image": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/images/lucid64",
            u"disks": [{u"index": 0, u"kind": u"compute#attachedDisk", u"type": u"EPHEMERAL", u"mode": u"READ_WRITE"}],
            u"canIpForward": False,
            u"serviceAccounts": [
                {u"scopes": [GCEAgent.GCE_SCOPE], u"email": u"*****@*****.**"}
            ],
            u"metadata": {u"kind": u"compute#metadata", u"fingerprint": u"42WmSpB8rSM="},
            u"creationTimestamp": u"2013-05-22T11:52:33.254-07:00",
            u"id": u"8684033495853907982",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazboogroup-feb10b11-62bc-4536-ac25-9734f2267d6d",
            u"networkInterfaces": [
                {
                    u"accessConfigs": [
                        {
                            u"kind": u"compute#accessConfig",
                            u"type": u"ONE_TO_ONE_NAT",
                            u"name": u"External NAT",
                            u"natIP": u"public1",
                        }
                    ],
                    u"networkIP": u"private1",
                    u"network": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazboogroup",
                    u"name": u"nic0",
                }
            ],
        }

        list_instance_info = {
            u"items": [instance_one_info, instance_two_info],
            u"kind": u"compute#instanceList",
            u"id": u"projects/appscale.com:appscale/zones/my-zone-1b/instances",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/961228229472/zones/my-zone-1b/instances",
        }

        fake_list_instance_request = flexmock(name="fake_list_instance_request")
        fake_list_instance_request.should_receive("execute").with_args(http=fake_authorized_http).and_return(
            list_instance_info
        )

        fake_instances = flexmock(name="fake_instances")
        fake_instances.should_receive("list").with_args(
            project=project_id, filter="name eq appscale-bazboogroup-.*", zone=zone
        ).and_return(fake_list_instance_request)
        fake_gce.should_receive("instances").and_return(fake_instances)

        # And assume that we can kill both of our instances fine
        delete_instance = u"operation-1369676691806-4ddb6b4ab6f39-a095d3de"
        delete_instance_info_one = {
            u"status": u"PENDING",
            u"kind": u"compute#operation",
            u"name": delete_instance,
            u"zone": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b",
            u"startTime": u"2013-05-27T10:44:51.849-07:00",
            u"insertTime": u"2013-05-27T10:44:51.806-07:00",
            u"targetId": u"12912855597472179535",
            u"targetLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-appscalecgb20-0cf89267-5887-4048-b774-ca20de47a07f",
            u"operationType": u"delete",
            u"progress": 0,
            u"id": u"11114355109942058217",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/operations/operation-1369676691806-4ddb6b4ab6f39-a095d3de",
            u"user": u"*****@*****.**",
        }

        delete_instance_info_two = {
            u"status": u"PENDING",
            u"kind": u"compute#operation",
            u"name": delete_instance,
            u"zone": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b",
            u"startTime": u"2013-05-27T10:44:51.849-07:00",
            u"insertTime": u"2013-05-27T10:44:51.806-07:00",
            u"targetId": u"12912855597472179535",
            u"targetLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/instances/appscale-appscalecgb20-0cf89267-5887-4048-b774-ca20de47a07f",
            u"operationType": u"delete",
            u"progress": 0,
            u"id": u"11114355109942058217",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/zones/my-zone-1b/operations/operation-1369676691806-4ddb6b4ab6f39-a095d3de",
            u"user": u"*****@*****.**",
        }

        fake_delete_instance_request_one = flexmock(name="fake_delete_instance_request_one")
        fake_delete_instance_request_one.should_receive("execute").with_args(http=fake_authorized_http).and_return(
            delete_instance_info_one
        )
        fake_instances.should_receive("delete").with_args(
            project=project_id, zone=zone, instance="appscale-bazboogroup-one"
        ).and_return(fake_delete_instance_request_one)

        fake_delete_instance_request_two = flexmock(name="fake_delete_instance_request_two")
        fake_delete_instance_request_two.should_receive("execute").with_args(http=fake_authorized_http).and_return(
            delete_instance_info_two
        )
        fake_instances.should_receive("delete").with_args(
            project=project_id, zone=zone, instance="appscale-bazboogroup-two"
        ).and_return(fake_delete_instance_request_two)

        # mock out our waiting for the instances to be deleted
        all_done = {u"status": u"DONE"}

        fake_instance_checker = flexmock(name="fake_instance_checker")
        fake_instance_checker.should_receive("execute").and_return(all_done)

        fake_blocker = flexmock(name="fake_blocker")
        fake_blocker.should_receive("get").with_args(
            project=project_id, operation=delete_instance, zone=zone
        ).and_return(fake_instance_checker)
        fake_gce.should_receive("zoneOperations").and_return(fake_blocker)

        # mock out the call to delete the firewall
        delete_firewall = u"operation-1369677695390-4ddb6f07cc611-5a8f1654"
        fake_delete_firewall_info = {
            u"status": u"PENDING",
            u"kind": u"compute#operation",
            u"name": delete_firewall,
            u"startTime": u"2013-05-27T11:01:35.482-07:00",
            u"insertTime": u"2013-05-27T11:01:35.390-07:00",
            u"targetId": u"11748720697396371259",
            u"targetLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/firewalls/appscalecgb20",
            u"operationType": u"delete",
            u"progress": 0,
            u"id": u"15574488986772298961",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/operations/operation-1369677695390-4ddb6f07cc611-5a8f1654",
            u"user": u"*****@*****.**",
        }
        fake_delete_firewall_request = flexmock(name="fake_delete_firewall_request")
        fake_delete_firewall_request.should_receive("execute").and_return(fake_delete_firewall_info)

        fake_firewalls = flexmock(name="fake_firewalls")
        fake_firewalls.should_receive("delete").with_args(project=project_id, firewall=self.group).and_return(
            fake_delete_firewall_request
        )
        fake_gce.should_receive("firewalls").and_return(fake_firewalls)

        # mock out the call to make sure the firewall was deleted
        fake_firewall_checker = flexmock(name="fake_firewall_checker")
        fake_firewall_checker.should_receive("execute").and_return(all_done)

        fake_blocker.should_receive("get").with_args(project=project_id, operation=delete_firewall).and_return(
            fake_firewall_checker
        )
        fake_gce.should_receive("globalOperations").and_return(fake_blocker)

        # and the call to delete the network
        delete_network = u"operation-1369677749954-4ddb6f3bd1849-056cf8ca"
        fake_delete_network_info = {
            u"status": u"PENDING",
            u"kind": u"compute#operation",
            u"name": delete_network,
            u"startTime": u"2013-05-27T11:02:30.012-07:00",
            u"insertTime": u"2013-05-27T11:02:29.954-07:00",
            u"targetId": u"17688075350400527692",
            u"targetLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/appscalecgb20",
            u"operationType": u"delete",
            u"progress": 0,
            u"id": u"12623697331874594836",
            u"selfLink": u"https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/operations/operation-1369677749954-4ddb6f3bd1849-056cf8ca",
            u"user": u"*****@*****.**",
        }
        fake_delete_network_request = flexmock(name="fake_delete_network_request")
        fake_delete_network_request.should_receive("execute").and_return(fake_delete_network_info)

        fake_networks = flexmock(name="fake_networks")
        fake_networks.should_receive("delete").with_args(project=project_id, network=self.group).and_return(
            fake_delete_network_request
        )
        fake_gce.should_receive("networks").and_return(fake_networks)

        # mock out the call to make sure the network was deleted
        fake_network_checker = flexmock(name="fake_network_checker")
        fake_network_checker.should_receive("execute").and_return(all_done)

        fake_blocker.should_receive("get").with_args(project=project_id, operation=delete_network).and_return(
            fake_network_checker
        )

        # finally, inject our fake GCE connection
        flexmock(apiclient.discovery)
        apiclient.discovery.should_receive("build").with_args("compute", GCEAgent.API_VERSION).and_return(fake_gce)

        # finally, mock out removing the yaml file, json file, and secret key from
        # this machine
        flexmock(os)
        os.should_receive("remove").with_args(LocalState.get_locations_yaml_location(self.keyname)).and_return()
        os.should_receive("remove").with_args(LocalState.get_locations_json_location(self.keyname)).and_return()
        os.should_receive("remove").with_args(LocalState.get_secret_key_location(self.keyname)).and_return()

        argv = ["--keyname", self.keyname, "--test"]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.terminate_instances(options)
    def test_terminate_in_cloud_and_succeeds(self):
        # let's say that there is a locations.yaml file, which means appscale is
        # running, so we should terminate the services on each box
        flexmock(os.path)
        os.path.should_call("exists")  # set up the fall-through
        os.path.should_receive("exists").with_args(LocalState.get_secret_key_location(self.keyname)).and_return(True)

        # mock out reading the locations.yaml file, and pretend that we're on
        # a virtualized cluster
        builtins = flexmock(sys.modules["__builtin__"])
        builtins.should_call("open")

        fake_yaml_file = flexmock(name="fake_file")
        fake_yaml_file.should_receive("read").and_return(yaml.dump({"infrastructure": "ec2", "group": self.group}))
        builtins.should_receive("open").with_args(LocalState.get_locations_yaml_location(self.keyname), "r").and_return(
            fake_yaml_file
        )

        # mock out reading the json file, and pretend that we're running in a
        # two node deployment
        fake_json_file = flexmock(name="fake_file")
        fake_json_file.should_receive("read").and_return(
            json.dumps([{"public_ip": "public1", "jobs": ["shadow"]}, {"public_ip": "public2", "jobs": ["appengine"]}])
        )
        builtins.should_receive("open").with_args(LocalState.get_locations_json_location(self.keyname), "r").and_return(
            fake_json_file
        )

        # and slip in a fake secret file
        fake_secret_file = flexmock(name="fake_file")
        fake_secret_file.should_receive("read").and_return("the secret")
        builtins.should_receive("open").with_args(LocalState.get_secret_key_location(self.keyname), "r").and_return(
            fake_secret_file
        )

        # mock out talking to EC2
        fake_ec2 = flexmock(name="fake_ec2")

        # let's say that three instances are running, and that two of them are in
        # our deployment
        fake_one_running = flexmock(
            name="fake_one",
            key_name=self.keyname,
            state="running",
            id="i-ONE",
            public_dns_name="public1",
            private_dns_name="private1",
        )
        fake_two_running = flexmock(
            name="fake_two",
            key_name=self.keyname,
            state="running",
            id="i-TWO",
            public_dns_name="public2",
            private_dns_name="private2",
        )
        fake_three_running = flexmock(
            name="fake_three",
            key_name="abcdefg",
            state="running",
            id="i-THREE",
            public_dns_name="public3",
            private_dns_name="private3",
        )
        fake_reservation_running = flexmock(
            name="fake_reservation", instances=[fake_one_running, fake_two_running, fake_three_running]
        )

        fake_one_terminated = flexmock(
            name="fake_one",
            key_name=self.keyname,
            state="terminated",
            id="i-ONE",
            public_dns_name="public1",
            private_dns_name="private1",
        )
        fake_two_terminated = flexmock(
            name="fake_two",
            key_name=self.keyname,
            state="terminated",
            id="i-TWO",
            public_dns_name="public2",
            private_dns_name="private2",
        )
        fake_three_terminated = flexmock(
            name="fake_three",
            key_name="abcdefg",
            state="terminated",
            id="i-THREE",
            public_dns_name="public3",
            private_dns_name="private3",
        )
        fake_reservation_terminated = flexmock(
            name="fake_reservation", instances=[fake_one_terminated, fake_two_terminated, fake_three_terminated]
        )

        fake_ec2.should_receive("get_all_instances").and_return(fake_reservation_running).and_return(
            fake_reservation_terminated
        )

        flexmock(boto.ec2)
        boto.ec2.should_receive("connect_to_region").and_return(fake_ec2)

        # and mock out the call to kill the instances
        fake_ec2.should_receive("terminate_instances").with_args(["i-ONE", "i-TWO"]).and_return(
            [fake_one_terminated, fake_two_terminated]
        )

        # mock out the call to delete the keypair
        fake_ec2.should_receive("delete_key_pair").and_return()

        # and the call to delete the security group - let's say that we can't
        # delete the group the first time, and can the second
        fake_ec2.should_receive("delete_security_group").and_return(False).and_return(True)

        # finally, mock out removing the yaml file, json file, and secret key from
        # this machine
        flexmock(os)
        os.should_receive("remove").with_args(LocalState.get_locations_yaml_location(self.keyname)).and_return()
        os.should_receive("remove").with_args(LocalState.get_locations_json_location(self.keyname)).and_return()
        os.should_receive("remove").with_args(LocalState.get_secret_key_location(self.keyname)).and_return()

        # also mock out asking the user for confirmation on shutting down
        # their cloud
        builtins.should_receive("raw_input").and_return("yes")

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.terminate_instances(options)
Exemplo n.º 16
0
  def down(self, clean=False, terminate=False):
    """ 'down' 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:
      clean: A boolean to indicate if the deployment data and metadata
        needs to be clean. This will clear the datastore.
      terminate: A boolean to indicate if instances needs to be terminated
        (valid only if we spawn instances at start).

    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 'verbose' in contents_as_yaml and contents_as_yaml['verbose'] == True:
      is_verbose = contents_as_yaml['verbose']
      command.append("--verbose")
    else:
      is_verbose = False

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

    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 clean:
      if 'test' not in contents_as_yaml or contents_as_yaml['test'] != True:
        LocalState.confirm_or_abort("Clean will delete every data in the deployment.")
      all_ips = LocalState.get_all_public_ips(keyname)
      for ip in all_ips:
        RemoteHelper.ssh(ip, keyname, self.TERMINATE, is_verbose)
      AppScaleLogger.success("Successfully cleaned your AppScale deployment.")

    if terminate:
      infrastructure = LocalState.get_infrastructure(keyname)
      if infrastructure != "xen" and not LocalState.are_disks_used(
        keyname) and 'test' not in contents_as_yaml:
        LocalState.confirm_or_abort("Terminate will delete instances and the data on them.")
      command.append("--terminate")

    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)

    LocalState.cleanup_appscale_files(keyname, terminate)
    AppScaleLogger.success("Successfully shut down your AppScale deployment.")