def setUp(self): self.factory = InfrastructureAgentFactory() self.fake_ec2 = flexmock(name='self.fake_ec2') self.fake_ec2.should_receive('get_key_pair') self.fake_ec2.should_receive('create_key_pair').with_args('bookeyname') \ .and_return(KeyPair()) self.fake_ec2.should_receive('get_all_security_groups').and_return([]) self.fake_ec2.should_receive('create_security_group') \ .with_args('boogroup', 'AppScale security group') \ .and_return(SecurityGroup()) self.fake_ec2.should_receive('authorize_security_group') instance = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-id', state='running', key_name='bookeyname') self.fake_ec2.should_receive('terminate_instances').and_return( [instance]) self.fake_ec2.should_receive('run_instances') flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').and_return(self.fake_ec2)
def validate_machine_image(self): """Checks with the given cloud (if running in a cloud) to ensure that the user-specified ami/emi exists, aborting if it does not. Raises: BadConfigurationException: If the given machine image does not exist. """ if not self.args.infrastructure: return cloud_agent = InfrastructureAgentFactory.create_agent( self.args.infrastructure) params = cloud_agent.get_params_from_args(self.args) if not cloud_agent.does_image_exist(params): raise BadConfigurationException( "Couldn't find the given machine image.") if not cloud_agent.does_zone_exist(params): raise BadConfigurationException("Couldn't find the given zone.") # Make sure that if the user gives us an Elastic IP / static IP, that they # actually own it. if self.args.static_ip: if not cloud_agent.does_address_exist(params): raise BadConfigurationException( "Couldn't find the given static IP.") if not self.args.disks: return for disk in set(self.args.disks.values()): if not cloud_agent.does_disk_exist(params, disk): raise BadConfigurationException( "Couldn't find disk {0}".format(disk))
def validate_credentials(self): """If running over a cloud infrastructure, makes sure that all of the necessary credentials have been specified. """ if not self.args.infrastructure: return cloud_agent = InfrastructureAgentFactory.create_agent( self.args.infrastructure) params = cloud_agent.get_params_from_args(self.args) cloud_agent.assert_required_parameters(params, BaseAgent.OPERATION_RUN)
def setUp(self): self.factory = InfrastructureAgentFactory() (flexmock(EC2Connection).should_receive('get_key_pair').and_return( None)) (flexmock(EC2Connection).should_receive('create_key_pair').with_args( 'bookeyname').and_return(KeyPair())) (flexmock(EC2Connection).should_receive( 'get_all_security_groups').and_return([])) (flexmock( EC2Connection).should_receive('create_security_group').with_args( 'boogroup', 'AppScale security group').and_return(SecurityGroup())) (flexmock(EC2Connection).should_receive( 'authorize_security_group').and_return()) (flexmock(EC2Connection).should_receive('run_instances').and_return())
def make_app(secret, is_autoscaler): options.__dict__['_options'].clear() options.define('secret', secret) agent_factory = InfrastructureAgentFactory() if is_autoscaler: scaler_route = ('/instances', InstancesHandler, { 'agent_factory': agent_factory }) else: scaler_route = ( '/instances', Respond404Handler, dict(reason='This node was not started as an autoscaler.')) app = web.Application([ ('/instance', InstanceHandler, { 'agent_factory': agent_factory }), scaler_route, ]) return app
def setUp(self): self.factory = InfrastructureAgentFactory() self.fake_ec2 = flexmock(name='self.fake_ec2') flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').and_return(self.fake_ec2) reservation = Reservation() instance = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccee', state='running', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') new_instance = flexmock(name='new-instance', private_dns_name='new-private-ip', public_dns_name='new-public-ip', id='i-aabbccff', state='running', key_name='bookeyname', ip_address='new-public-ip', private_ip_address='new-private-ip') t_aabbccee = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccee', state='terminated', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') t_aabbccff = flexmock(name='new-instance', private_dns_name='new-private-ip', public_dns_name='new-public-ip', id='i-aabbccff', state='terminated', key_name='bookeyname', ip_address='new-public-ip', private_ip_address='new-private-ip') t_aabbccdd = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccdd', state='terminated', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') reservation.instances = [instance] new_reservation = Reservation() new_reservation.instances = [instance, new_instance] # For testing wait_for_status self.good_reservation = Reservation() self.good_reservation.instances = [instance, new_instance] self.good_reservations = [self.good_reservation] self.terminated_reservation = Reservation() # Used because we filter for 'terminated' and it should return no instances.. self.empty_reservation = Reservation() self.empty_reservation.instances = [] self.empty_reservations = [self.empty_reservation] self.terminated_reservation.instances = [t_aabbccee, t_aabbccff, t_aabbccdd] self.terminated_reservations = [self.terminated_reservation] self.instance_notfound_body = """ <Response xmlns=""><Errors> <Error> <Code>InvalidInstanceID.NotFound</Code> <Message>The instance ID '{}' does not exist</Message> </Error></Errors> <RequestID>23548a3a-d6c8-4de7-b846-4e072587c582</RequestID></Response> """ self.multiple_instance_notfound_body = """ <Response xmlns=""><Errors> <Error> <Code>InvalidInstanceID.NotFound</Code> <Message>The instance IDs '{}' do not exist</Message> </Error></Errors> <RequestID>23548a3a-d6c8-4de7-b846-4e072587c582</RequestID></Response> """ self.full_params = { 'credentials': { 'a': 'b', 'EC2_URL': 'http://testing.appscale.com:8773/foo/bar', 'EC2_ACCESS_KEY': 'access_key', 'EC2_SECRET_KEY': 'secret_key'}, 'group': 'boogroup', 'image_id': 'booid', 'infrastructure': 'ec2', 'instance_type': 'booinstance_type', 'keyname': 'bookeyname', 'num_vms': '1', 'use_spot_instances': False, 'region': 'my-zone-1', 'zone': 'my-zone-1b', 'autoscale_agent': True, }
class TestEC2AgentTerminateInstances(TestCase): def setUp(self): self.factory = InfrastructureAgentFactory() self.fake_ec2 = flexmock(name='self.fake_ec2') flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').and_return(self.fake_ec2) reservation = Reservation() instance = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccee', state='running', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') new_instance = flexmock(name='new-instance', private_dns_name='new-private-ip', public_dns_name='new-public-ip', id='i-aabbccff', state='running', key_name='bookeyname', ip_address='new-public-ip', private_ip_address='new-private-ip') t_aabbccee = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccee', state='terminated', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') t_aabbccff = flexmock(name='new-instance', private_dns_name='new-private-ip', public_dns_name='new-public-ip', id='i-aabbccff', state='terminated', key_name='bookeyname', ip_address='new-public-ip', private_ip_address='new-private-ip') t_aabbccdd = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccdd', state='terminated', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') reservation.instances = [instance] new_reservation = Reservation() new_reservation.instances = [instance, new_instance] # For testing wait_for_status self.good_reservation = Reservation() self.good_reservation.instances = [instance, new_instance] self.good_reservations = [self.good_reservation] self.terminated_reservation = Reservation() # Used because we filter for 'terminated' and it should return no instances.. self.empty_reservation = Reservation() self.empty_reservation.instances = [] self.empty_reservations = [self.empty_reservation] self.terminated_reservation.instances = [t_aabbccee, t_aabbccff, t_aabbccdd] self.terminated_reservations = [self.terminated_reservation] self.instance_notfound_body = """ <Response xmlns=""><Errors> <Error> <Code>InvalidInstanceID.NotFound</Code> <Message>The instance ID '{}' does not exist</Message> </Error></Errors> <RequestID>23548a3a-d6c8-4de7-b846-4e072587c582</RequestID></Response> """ self.multiple_instance_notfound_body = """ <Response xmlns=""><Errors> <Error> <Code>InvalidInstanceID.NotFound</Code> <Message>The instance IDs '{}' do not exist</Message> </Error></Errors> <RequestID>23548a3a-d6c8-4de7-b846-4e072587c582</RequestID></Response> """ self.full_params = { 'credentials': { 'a': 'b', 'EC2_URL': 'http://testing.appscale.com:8773/foo/bar', 'EC2_ACCESS_KEY': 'access_key', 'EC2_SECRET_KEY': 'secret_key'}, 'group': 'boogroup', 'image_id': 'booid', 'infrastructure': 'ec2', 'instance_type': 'booinstance_type', 'keyname': 'bookeyname', 'num_vms': '1', 'use_spot_instances': False, 'region': 'my-zone-1', 'zone': 'my-zone-1b', 'autoscale_agent': True, } def test_ec2_terminate_instances(self): """ Test out a successful terminate instances """ # Uncomment to get logging from the agent, helpful for debugging #logging.basicConfig(level=logging.DEBUG) #l = logging.getLogger('appscale.agents.ec_agent') #l.setLevel(logging.DEBUG) ec2 = self.factory.create_agent('ec2') (self.fake_ec2.should_receive('terminate_instances') .and_return(True)) self.full_params['instance_ids'] = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] (self.fake_ec2.should_receive('get_all_reservations') .and_return(self.terminated_reservations)) instance_ids = set(self.full_params[ec2.PARAM_INSTANCE_IDS]) status_filters = {"instance-state-name": 'terminated', "key-name": self.full_params[ec2.PARAM_KEYNAME]} conn = ec2.open_connection(self.full_params) result = ec2._EC2Agent__terminate_instances(instance_ids, conn, status_filters, max_attempts=1) self.assertTrue(result) def test_ec2_terminate_instances_invalid_id(self): """ Test out an invalid instance id """ ec2 = self.factory.create_agent('ec2') instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] self.full_params['instance_ids'] = instance_ids # First instance ID doesn't exist, second call will succeed (self.fake_ec2.should_receive('terminate_instances') .and_raise(EC2ResponseError(400, 'no reason', self.instance_notfound_body.format(instance_ids[0]))) .and_return(True)) # _wait_for_status should return true. (self.fake_ec2.should_receive('get_all_reservations') .and_return(self.terminated_reservations)) instance_ids = set(self.full_params[ec2.PARAM_INSTANCE_IDS]) status_filters = {"instance-state-name": 'terminated', "key-name": self.full_params[ec2.PARAM_KEYNAME]} conn = ec2.open_connection(self.full_params) result = ec2._EC2Agent__terminate_instances(instance_ids, conn, status_filters, max_attempts=1) self.assertTrue(result) def test_ec2_terminate_instances_multiple_invalid_id(self): """ Test out a multiple invalid instance ids. """ # Uncomment to get logging from the agent, helpful for debugging logging.basicConfig(level=logging.DEBUG) l = logging.getLogger('appscale.agents.ec_agent') l.setLevel(logging.DEBUG) ec2 = self.factory.create_agent('ec2') instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] self.full_params['instance_ids'] = instance_ids # First instance ID doesn't exist, second call will succeed (self.fake_ec2.should_receive('terminate_instances') .and_raise(EC2ResponseError(400, 'no reason', self.multiple_instance_notfound_body.format(instance_ids[0:2]))) .and_return(True)) # _wait_for_status should return true. (self.fake_ec2.should_receive('get_all_reservations') .and_return(self.terminated_reservations)) instance_ids = set(self.full_params[ec2.PARAM_INSTANCE_IDS]) status_filters = {"instance-state-name": 'terminated', "key-name": self.full_params[ec2.PARAM_KEYNAME]} conn = ec2.open_connection(self.full_params) result = ec2._EC2Agent__terminate_instances(instance_ids, conn, status_filters, max_attempts=1) self.assertTrue(result) def test_ec2_terminate_instances_all_not_found(self): """ Test out all not found, should return true """ # Uncomment to get logging from the agent, helpful for debugging logging.basicConfig(level=logging.DEBUG) l = logging.getLogger('appscale.agents.ec_agent') l.setLevel(logging.DEBUG) ec2 = self.factory.create_agent('ec2') instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] self.full_params['instance_ids'] = instance_ids # First instance ID doesn't exist, second call will succeed (self.fake_ec2.should_receive('terminate_instances') .and_raise(EC2ResponseError(400, 'no reason', self.multiple_instance_notfound_body.format(instance_ids[:]))) .and_return(True)) # _wait_for_status should return true. (self.fake_ec2.should_receive('get_all_reservations') .and_return(self.terminated_reservations)) instance_ids = set(self.full_params[ec2.PARAM_INSTANCE_IDS]) status_filters = {"instance-state-name": 'terminated', "key-name": self.full_params[ec2.PARAM_KEYNAME]} conn = ec2.open_connection(self.full_params) result = ec2._EC2Agent__terminate_instances(instance_ids, conn, status_filters, max_attempts=1) self.assertTrue(result) def test_ec2_terminate_instances_keeps_running(self): """ Test out case where all instances keep running. boto.terminate_instances throws InstanceIDInvalid.NotFound We recover and keep waiting for the other 2 instances, which keep running and do *not* terminate. Will take about 120 seconds to run (timeout) Should return False """ ec2 = self.factory.create_agent('ec2') instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] self.full_params['instance_ids'] = instance_ids # First instance ID doesn't exist, second call will succeed (self.fake_ec2.should_receive('terminate_instances') .and_raise(EC2ResponseError(400, 'no reason', self.instance_notfound_body.format(instance_ids[0]))) .and_return(True)) # _wait_for_status should return true. (self.fake_ec2.should_receive('get_all_reservations') .and_return(self.empty_reservations)) instance_ids = set(self.full_params[ec2.PARAM_INSTANCE_IDS]) status_filters = {"instance-state-name": 'terminated', "key-name": self.full_params[ec2.PARAM_KEYNAME]} conn = ec2.open_connection(self.full_params) result = ec2._EC2Agent__terminate_instances(instance_ids, conn, status_filters, max_attempts=1) self.assertFalse(result)
class TestEC2AgentStatusChange(TestCase): """ Test cases that test out the ec2agent.wait_for_status_change() method and how it handles the cases where an instance id is not found. """ def setUp(self): self.factory = InfrastructureAgentFactory() self.fake_ec2 = flexmock(name='self.fake_ec2') flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').and_return(self.fake_ec2) reservation = Reservation() instance = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccee', state='running', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') new_instance = flexmock(name='new-instance', private_dns_name='new-private-ip', public_dns_name='new-public-ip', id='i-aabbccff', state='running', key_name='bookeyname', ip_address='new-public-ip', private_ip_address='new-private-ip') t_aabbccee = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccee', state='terminated', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') t_aabbccff = flexmock(name='new-instance', private_dns_name='new-private-ip', public_dns_name='new-public-ip', id='i-aabbccff', state='terminated', key_name='bookeyname', ip_address='new-public-ip', private_ip_address='new-private-ip') t_aabbccdd = flexmock(name='instance', private_dns_name='private-ip', public_dns_name='public-ip', id='i-aabbccdd', state='terminated', key_name='bookeyname', ip_address='public-ip', private_ip_address='private-ip') reservation.instances = [instance] new_reservation = Reservation() new_reservation.instances = [instance, new_instance] # For testing wait_for_status self.good_reservation = Reservation() self.good_reservation.instances = [instance, new_instance] self.good_reservations = [self.good_reservation] self.terminated_reservation = Reservation() # Used because we filter for 'terminated' and it should return no instances.. self.empty_reservation = Reservation() self.empty_reservation.instances = [] self.empty_reservations = [self.empty_reservation] self.terminated_reservation.instances = [t_aabbccee, t_aabbccff, t_aabbccdd] self.terminated_reservations = [self.terminated_reservation] self.instance_notfound_body = """ <Response xmlns=""><Errors> <Error> <Code>InvalidInstanceID.NotFound</Code> <Message>The instance ID '{}' does not exist</Message> </Error></Errors> <RequestID>23548a3a-d6c8-4de7-b846-4e072587c582</RequestID></Response> """ self.multiple_instances_not_found = """ <Response xmlns=""><Errors> <Error> <Code>InvalidInstanceID.NotFound</Code> <Message>The instance IDs '{}' do not exist</Message> </Error></Errors> <RequestID>23548a3a-d6c8-4de7-b846-4e072587c582</RequestID></Response> """ self.full_params = { 'credentials': { 'a': 'b', 'EC2_URL': 'http://testing.appscale.com:8773/foo/bar', 'EC2_ACCESS_KEY': 'access_key', 'EC2_SECRET_KEY': 'secret_key'}, 'group': 'boogroup', 'image_id': 'booid', 'infrastructure': 'ec2', 'instance_type': 'booinstance_type', 'keyname': 'bookeyname', 'num_vms': '1', 'use_spot_instances': False, 'region': 'my-zone-1', 'zone': 'my-zone-1b', 'autoscale_agent': True } def test_ec2_wait_for_status_change_invalid_filters(self): """ Simple test case if an invalid filter is passed" """ ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) with self.assertRaisesRegexp(InvalidFilter, 'instance-state-name is missing from filter'): ec2.wait_for_status_change(['i-aabbccdd'], conn, filters={}) def test_ec2_wait_for_status_change_stopped_not_found(self): """ When waiting for the 'stopped' state, if an instance is not found it is considered to be an error and the method will throw an InstanceIDNotFound exception. """ filters = {'instance-state-name': 'stopped', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) # Throw an invalid id when stopping an instance. wait_for_status should raise an # exception. (self.fake_ec2.should_receive('get_all_reservations') .and_raise(EC2ResponseError(400, "no reason", self.instance_notfound_body.format('i-aabbccdd')))) with self.assertRaises(InstanceIDNotFound): ec2.wait_for_status_change(['i-aabbccdd'], conn, filters, 5, 1) def test_ec2_wait_for_status_change_already_terminated(self): """ Terminate an instance and the cloud returns InvalidInstanceID.NotFound This should be reported as a success """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) instance_ids = ['i-aabbccdd'] self.fake_ec2.should_receive('get_all_reservations').and_raise( EC2ResponseError(400, "no reason", self.instance_notfound_body.format(instance_ids[0]))) result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=10, poll_interval=1) self.assertTrue(result) def test_ec2_wait_for_status_change_one_not_found_terminated(self): """ The first instance id in the list is marked as not found. Note: self.terminated_reservations does return the instance id, which shouldn't have an impact """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] (self.fake_ec2.should_receive('get_all_reservations') .and_raise(EC2ResponseError(400, "no reason", self.instance_notfound_body.format(instance_ids[0]))) .and_return(self.terminated_reservations)) result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=10, poll_interval=1) self.assertTrue(result) def test_ec2_wait_for_status_change_all_not_found_terminated(self): """ Case where all instances are not found Should return True """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] # Raise an exception for each instance id in serial (self.fake_ec2.should_receive('get_all_reservations') .and_raise(EC2ResponseError(400, "no reason", self.instance_notfound_body.format(instance_ids[0]))) .and_raise(EC2ResponseError(400, "no reason", self.instance_notfound_body.format(instance_ids[1]))) .and_raise(EC2ResponseError(400, "no reason", self.instance_notfound_body.format(instance_ids[2])))) result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=5, poll_interval=1) self.assertTrue(result) def test_ec2_wait_for_status_change_multiple_not_found(self): """ Case where multiple instances are not found. Should return True """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] # Raise exception for the first two instance ids. missing_ids = ','.join(instance_ids[0:2]) (self.fake_ec2.should_receive('get_all_reservations') .and_raise(EC2ResponseError(400, "no reason", self.multiple_instances_not_found.format(missing_ids))) .and_return(self.terminated_reservations)) result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=5, poll_interval=1) self.assertTrue(result) def test_ec2_wait_for_status_change_multiple_not_found_different_order(self): """ Multiple instance ids not found, first one is found Should return True """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] # Raise exception for the first two instance ids. missing_ids = ','.join(instance_ids[1:]) (self.fake_ec2.should_receive('get_all_reservations') .and_raise(EC2ResponseError(400, "no reason", self.multiple_instances_not_found.format(missing_ids))) .and_return(self.terminated_reservations)) result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=5, poll_interval=1) self.assertTrue(result) def test_ec2_wait_for_status_change_keeps_on_running(self): """ Case where all instances keep running and never reach 'terminated' Should return False """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) # First element is missing instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] (self.fake_ec2.should_receive('get_all_reservations') .and_raise(EC2ResponseError(400, 'no reason', self.instance_notfound_body.format(instance_ids[1]))) .and_return(self.empty_reservations) .and_return(self.empty_reservations) .and_return(self.empty_reservations) .and_return(self.empty_reservations) ) # Last two won't reach terminated state result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=3, poll_interval=1) self.assertFalse(result) def test_ec2_wait_for_status_change_successfully_terminated(self): """ The first instance id in the list is marked as not found. Note: self.terminated_reservations does return the instance id, which shouldn't have an impact """ filters = {'instance-state-name': 'terminated', 'key-name': self.full_params['keyname']} ec2 = self.factory.create_agent('ec2') conn = ec2.open_connection(self.full_params) instance_ids = ['i-aabbccdd', 'i-aabbccee', 'i-aabbccff'] (self.fake_ec2.should_receive('get_all_reservations') .and_return(self.terminated_reservations)) result = ec2.wait_for_status_change(instance_ids, conn, filters, max_wait_time=10, poll_interval=1) self.assertTrue(result) def tearDown(self): pass
def test_gce_run_instances(self): # mock out interactions with GCE # first, mock out the oauth library calls fake_credentials = flexmock(name='fake_credentials', invalid=False) fake_storage = flexmock(name='fake_storage') fake_storage.should_receive('get').and_return(fake_credentials) flexmock(oauth2client.file) oauth2client.file.should_receive('Storage').with_args( GCEAgent.OAUTH2_STORAGE_LOCATION).and_return(fake_storage) # 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) # add some fake data in where no instances are initially running, then one # is (in response to our insert request) no_instance_info = {} instance_id = u'appscale-bazgroup-feb10b11-62bc-4536-ac25-9734f2267d6d' list_instance_info = { u'items': [{ 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': instance_id, 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-bazgroup-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'public-ip' }], u'networkIP': u'private-ip', u'network': u'https://www.googleapis.com/compute/v1beta14/projects/appscale.com:appscale/global/networks/bazgroup', u'name': u'nic0' }] }], 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(no_instance_info) \ .and_return(no_instance_info) \ .and_return(list_instance_info) fake_instances = flexmock(name='fake_instances') fake_gce = flexmock(name='fake_gce') fake_gce.should_receive('instances').and_return(fake_instances) \ .and_return(fake_instances).and_return(fake_instances) fake_instances.should_receive('list').with_args(project=self.project, filter="name eq boogroup-.*", zone='my-zone-1b') \ .and_return(fake_list_instance_request) \ .and_return(fake_list_instance_request) # we only need to create one node, so set up mocks for that add_instance = u'operation-1369248752891-4dd5311848461-afc55a20' add_instance_info = { u'status': u'PENDING', u'kind': u'compute#operation', u'name': add_instance, u'azone': unicode(GCEAgent.GCE_URL) + u'appscale.com:appscale/zones/my-zone-1b', u'startTime': u'2013-05-22T11:52:32.939-07:00', u'insertTime': u'2013-05-22T11:52:32.891-07:00', u'targetLink': unicode(GCEAgent.GCE_URL) + u'appscale.com:appscale/zones/my-zone-1b/instances/appscale-bazgroup-feb10b11-62bc-4536-ac25-9734f2267d6d', u'operationType': u'insert', u'progress': 0, u'id': u'6663616273628949255', u'selfLink': unicode(GCEAgent.GCE_URL) + u'appscale.com:appscale/zones/my-zone-1b/operations/operation-1369248752891-4dd5311848461-afc55a20', u'user': u'*****@*****.**' } fake_add_instance_request = flexmock(name='fake_add_instance_request') fake_add_instance_request.should_receive('execute').with_args( http=fake_authorized_http).and_return(add_instance_info) fake_instances.should_receive('insert').with_args( project=self.project, body=dict, zone=str).and_return(fake_add_instance_request) created_instance_info = {u'status': u'DONE'} fake_instance_checker = flexmock(name='fake_network_checker') fake_instance_checker.should_receive('execute').and_return( created_instance_info) fake_blocker = flexmock(name='fake_blocker') fake_gce.should_receive('globalOperations').and_return(fake_blocker) fake_blocker.should_receive('get').with_args( project=self.project, operation=add_instance).and_return(fake_instance_checker) # finally, inject our fake GCE connection flexmock(discovery) discovery.should_receive('build').with_args( 'compute', GCEAgent.API_VERSION).and_return(fake_gce) # next, presume that the persistent disk we want to use exists disk_name = 'my-persistent-disk-1' disk_info = {'status': 'DONE'} fake_disk_request = flexmock(name='fake_disk_request') fake_disk_request.should_receive('execute').with_args( http=fake_authorized_http).and_return(disk_info) fake_disks = flexmock(name='fake_disks') fake_disks.should_receive('get').with_args( project=self.project, disk=disk_name, zone=str).and_return(fake_disk_request) fake_disks.should_receive('insert').with_args( project=self.project, sourceImage=str, body=dict, zone=str).and_return(fake_disk_request) fake_gce.should_receive('disks').and_return(fake_disks) i = InfrastructureAgentFactory.create_agent('gce') # first, validate that the run_instances call goes through successfully # and gives the user an operation id agent_run_instances_result = ([ u'appscale-bazgroup-feb10b11-62bc-4536-ac25-9734f2267d6d' ], ['public-ip'], ['private-ip']) security_configured = i.configure_instance_security(self.params) self.assertTupleEqual( agent_run_instances_result, i.run_instances(int(self.params['num_vms']), self.params, security_configured, public_ip_needed=False))