def get_info(self, instance): """Retrieve information from aws for a specific instance name.""" LOG.debug('Get info of server: %s' % instance.uuid) context = req_context.RequestContext(is_admin=True, project_id=instance.project_id) state = power_state.NOSTATE aws_instance_id = self._get_provider_instance_id( context, instance.uuid) if not aws_instance_id: LOG.error('Cannot get the aws_instance_id of % s' % instance.uuid) raise exception.InstanceNotFound(instance_id=instance.uuid) try: LOG.debug('Get info the instance %s on aws', aws_instance_id) kwargs = {'InstanceIds': [aws_instance_id]} instances = self.aws_client.get_aws_client(context)\ .describe_instances(**kwargs) if not instances: LOG.error('Instance %s not found on aws' % instance.uuid) raise exception.InstanceNotFound(instance_id=instance.uuid) instance = instances[0] state = AWS_POWER_STATE.get(instance.get('State').get('Code')) except botocore.exceptions.ClientError as e: reason = e.response.get('Error', {}).get('Message', 'Unkown') with excutils.save_and_reraise_exception(): LOG.error('Get instance failed on aws, the error is: %s' % reason) except KeyError: state = power_state.NOSTATE return hardware.InstanceInfo(state=state, max_mem_kb=0, mem_kb=0, num_cpu=1)
def reboot(self, context, instance, network_info, reboot_type, block_device_info=None, bad_volumes_callback=None): """Reboot the specified instance.""" LOG.debug('Start to reboot server: %s' % instance.uuid) try: aws_instance_id = self._get_provider_instance_id( context, instance.uuid) if aws_instance_id: LOG.debug('Reboot the instance %s on aws', aws_instance_id) instance_ids = [aws_instance_id] self.aws_client.get_aws_client(context)\ .reboot_instances(InstanceIds=instance_ids) LOG.debug('Reboot server: %s success' % instance.uuid) else: LOG.error('Cannot get the aws_instance_id of % s' % instance.uuid) raise exception.InstanceNotFound(instance_id=instance.uuid) except botocore.exceptions.ClientError as e: reason = e.response.get('Error', {}).get('Message', 'Unkown') LOG.error('Power on instance failed, the error is: %s' % reason) error_code = e.response.get('Error', {}).get('Code', 'Unkown') if error_code == 'InvalidInstanceID.NotFound': raise exception.InstanceNotFound(instance_id=instance.uuid) else: raise exception.InstanceRebootFailure(reason=reason) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error(_LE('Error from power on instance. ' 'Error=%(e)s'), {'e': e}, instance=instance)
def get_info(self, instance): if instance.uuid not in self.instances: raise exception.InstanceNotFound(instance_id=instance.uuid) i = self.instances[instance.uuid] return hardware.InstanceInfo(state=i.state, max_mem_kb=0, mem_kb=0, num_cpu=2, cpu_time_ns=0)
def power_off(self, instance, timeout=0, retry_interval=0): """Power off the specified instance.""" LOG.debug('Start to stop server: %s' % instance.uuid) try: project_id = instance.project_id context = req_context.RequestContext(is_admin=True, project_id=project_id) aws_instance_id = self._get_provider_instance_id( context, instance.uuid) if aws_instance_id: LOG.debug('Power off the instance %s on aws', aws_instance_id) instance_ids = [aws_instance_id] self.aws_client.get_aws_client(context)\ .stop_instances(InstanceIds=instance_ids) LOG.debug('Stop server: %s success' % instance.uuid) else: LOG.error('Cannot get the aws_instance_id of % s' % instance.uuid) raise exception.InstanceNotFound(instance_id=instance.uuid) except botocore.exceptions.ClientError as e: reason = e.response.get('Error', {}).get('Message', 'Unkown') LOG.error('Power off instance failed, the error is: %s' % reason) error_code = e.response.get('Error', {}).get('Code', 'Unkown') if error_code == 'InvalidInstanceID.NotFound': raise exception.InstanceNotFound(instance_id=instance.uuid) else: raise exception.InstancePowerOffFailure(reason=reason) except botocore.exceptions.WaiterError as e: reason = e.message LOG.warn('Cannot power_off instance,operation time out') raise exception.InstancePowerOffFailure(reason=reason) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error(_LE('Error from power off instance. ' 'Error=%(e)s'), {'e': e}, instance=instance)
def attach_volume(self, context, connection_info, instance, mountpoint=None, disk_bus=None, device_type=None, encryption=None): """Attach the disk to the instance at mountpoint using info.""" LOG.debug('Start to attach volume %s to instance %s' % (instance.uuid, connection_info['data']['volume_id'])) try: caa_volume_id = connection_info['data']['volume_id'] aws_instance_id = self._get_provider_instance_id( context, instance.uuid) aws_volume_id = self._get_provider_volume_id( context, caa_volume_id) if not aws_instance_id: raise exception.InstanceNotFound(instance_id=instance.uuid) if not aws_volume_id: raise exception.VolumeNotFound(volume_id=caa_volume_id) if mountpoint: device_name = self._trans_device_name(mountpoint) else: device_name = self._get_device_name(context, aws_instance_id) LOG.debug('Attach volume %s to instance %s on aws' % (aws_volume_id, aws_instance_id)) self.aws_client.get_aws_client(context)\ .attach_volume(VolumeId=aws_volume_id, InstanceId=aws_instance_id, Device=device_name) LOG.debug('Attach volume %s to instance %s success' % (instance.uuid, connection_info['data']['volume_id'])) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error(_LE('Error from attach volume. ' 'Error=%(e)s'), {'e': e}, instance=instance)
def detach_volume(self, connection_info, instance, mountpoint, encryption=None): """Detach the disk attached to the instance.""" LOG.debug('Start to detach volume %s from instance %s' % (instance.uuid, connection_info['data']['volume_id'])) project_id = instance.project_id context = req_context.RequestContext(is_admin=True, project_id=project_id) try: caa_volume_id = connection_info['data']['volume_id'] aws_instance_id = self._get_provider_instance_id( context, instance.uuid) aws_volume_id = self._get_provider_volume_id( context, caa_volume_id) if not aws_instance_id: aws_instances = self._get_provider_instance( context, instance.uuid) if not aws_instances: LOG.error('The instances %s not found' % instance.uuid) raise exception.InstanceNotFound(instance_id=instance.uuid) elif len(aws_instances) > 1: raise exception_ex.MultiInstanceConfusion else: aws_instance_id = aws_instances[0].get('InstanceId') if not aws_volume_id: aws_volumes = self._get_provider_volume(context, caa_volume_id) if not aws_volumes: LOG.error('The volume %s not found' % caa_volume_id) return elif len(aws_volumes) > 1: raise exception_ex.MultiVolumeConfusion else: aws_volume_id = aws_volumes[0].get('VolumeId') LOG.debug('Detach volume %s from instance %s on aws' % (aws_volume_id, aws_instance_id)) self.aws_client.get_aws_client(context)\ .detach_volume(VolumeId=aws_volume_id, InstanceId=aws_instance_id) LOG.debug('Detach volume %s from instance %s success' % (instance.uuid, connection_info['data']['volume_id'])) except botocore.exceptions.ClientError as e: reason = e.response.get('Error', {}).get('Message', 'Unkown') LOG.error('Detach volume failed, the error is: %s' % reason) error_code = e.response.get('Error', {}).get('Code', 'Unkown') if error_code == 'InvalidVolume.NotFound': LOG.warn('The volume %s not found on aws' % caa_volume_id) elif error_code == 'InvalidInstanceID.NotFound': LOG.error('Detach volume failed, the error is: %s' % reason) raise exception.InstanceNotFound(instance_id=instance.uuid) elif error_code == 'IncorrectState': kwargs = {'VolumeIds': [aws_volume_id]} volumes = self.aws_client.get_aws_client(context)\ .describe_volumes(**kwargs) volume_state = volumes[0].get('State') if volume_state == 'available': LOG.warn('The volume %s is available on aws' % caa_volume_id) else: with excutils.save_and_reraise_exception(): pass else: with excutils.save_and_reraise_exception(): pass except botocore.exceptions.WaiterError as e: reason = e.message LOG.warn('Cannot detach volume,operation time out') with excutils.save_and_reraise_exception(): LOG.error(_LE('Error from detach volume. ' 'Error=%(e)s'), {'e': e}, instance=instance) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error(_LE('Error from detach volume ' 'Error=%(e)s'), {'e': e}, instance=instance)
class InterfaceAttachTestsV21(test.NoDBTestCase): controller_cls = attach_interfaces_v21.InterfaceAttachmentController validate_exc = exception.ValidationError in_use_exc = exc.HTTPConflict not_found_exc = exc.HTTPNotFound not_usable_exc = exc.HTTPBadRequest def setUp(self): super(InterfaceAttachTestsV21, self).setUp() self.flags(timeout=30, group='neutron') self.stubs.Set(network_api.API, 'show_port', fake_show_port) self.stubs.Set(network_api.API, 'list_ports', fake_list_ports) self.stubs.Set(compute_api.API, 'get', fake_get_instance) self.expected_show = { 'interfaceAttachment': { 'net_id': FAKE_NET_ID1, 'port_id': FAKE_PORT_ID1, 'mac_addr': port_data1['mac_address'], 'port_state': port_data1['status'], 'fixed_ips': port_data1['fixed_ips'], } } self.attachments = self.controller_cls() self.req = fakes.HTTPRequest.blank('') @mock.patch.object(compute_api.API, 'get', side_effect=exception.InstanceNotFound(instance_id='')) def _test_instance_not_found(self, func, args, mock_get, kwargs=None): if not kwargs: kwargs = {} self.assertRaises(exc.HTTPNotFound, func, self.req, *args, **kwargs) def test_show_instance_not_found(self): self._test_instance_not_found(self.attachments.show, ('fake', 'fake')) def test_index_instance_not_found(self): self._test_instance_not_found(self.attachments.index, ('fake', )) def test_detach_interface_instance_not_found(self): self._test_instance_not_found(self.attachments.delete, ('fake', 'fake')) def test_attach_interface_instance_not_found(self): self._test_instance_not_found( self.attachments.create, ('fake', ), kwargs={'body': { 'interfaceAttachment': {} }}) def test_show(self): result = self.attachments.show(self.req, FAKE_UUID1, FAKE_PORT_ID1) self.assertEqual(self.expected_show, result) def test_show_with_port_not_found(self): self.assertRaises(exc.HTTPNotFound, self.attachments.show, self.req, FAKE_UUID2, FAKE_PORT_ID1) @mock.patch.object(network_api.API, 'show_port', side_effect=exception.Forbidden) def test_show_forbidden(self, show_port_mock): self.assertRaises(exc.HTTPForbidden, self.attachments.show, self.req, FAKE_UUID1, FAKE_PORT_ID1) def test_delete(self): self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface) result = self.attachments.delete(self.req, FAKE_UUID1, FAKE_PORT_ID1) # NOTE: on v2.1, http status code is set as wsgi_code of API # method instead of status_int in a response object. if isinstance(self.attachments, attach_interfaces_v21.InterfaceAttachmentController): status_int = self.attachments.delete.wsgi_code else: status_int = result.status_int self.assertEqual(202, status_int) def test_detach_interface_instance_locked(self): def fake_detach_interface_from_locked_server(self, context, instance, port_id): raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1) self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface_from_locked_server) self.assertRaises(exc.HTTPConflict, self.attachments.delete, self.req, FAKE_UUID1, FAKE_PORT_ID1) def test_delete_interface_not_found(self): self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface) self.assertRaises(exc.HTTPNotFound, self.attachments.delete, self.req, FAKE_UUID1, 'invaid-port-id') def test_attach_interface_instance_locked(self): def fake_attach_interface_to_locked_server(self, context, instance, network_id, port_id, requested_ip): raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1) self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface_to_locked_server) body = {} self.assertRaises(exc.HTTPConflict, self.attachments.create, self.req, FAKE_UUID1, body=body) def test_attach_interface_without_network_id(self): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) body = {} result = self.attachments.create(self.req, FAKE_UUID1, body=body) self.assertEqual(result['interfaceAttachment']['net_id'], FAKE_NET_ID1) def test_attach_interface_with_network_id(self): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) body = {'interfaceAttachment': {'net_id': FAKE_NET_ID2}} result = self.attachments.create(self.req, FAKE_UUID1, body=body) self.assertEqual(result['interfaceAttachment']['net_id'], FAKE_NET_ID2) def _attach_interface_bad_request_case(self, body): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) self.assertRaises(exc.HTTPBadRequest, self.attachments.create, self.req, FAKE_UUID1, body=body) def _attach_interface_not_found_case(self, body): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) self.assertRaises(self.not_found_exc, self.attachments.create, self.req, FAKE_UUID1, body=body) def test_attach_interface_with_port_and_network_id(self): body = { 'interfaceAttachment': { 'port_id': FAKE_PORT_ID1, 'net_id': FAKE_NET_ID2 } } self._attach_interface_bad_request_case(body) def test_attach_interface_with_not_found_network_id(self): body = {'interfaceAttachment': {'net_id': FAKE_BAD_NET_ID}} self._attach_interface_not_found_case(body) def test_attach_interface_with_not_found_port_id(self): body = {'interfaceAttachment': {'port_id': FAKE_NOT_FOUND_PORT_ID}} self._attach_interface_not_found_case(body) def test_attach_interface_with_invalid_state(self): def fake_attach_interface_invalid_state(*args, **kwargs): raise exception.InstanceInvalidState(instance_uuid='', attr='', state='', method='attach_interface') self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface_invalid_state) body = {'interfaceAttachment': {'net_id': FAKE_NET_ID1}} self.assertRaises(exc.HTTPConflict, self.attachments.create, self.req, FAKE_UUID1, body=body) @mock.patch.object(compute_api.API, 'attach_interface', side_effect=NotImplementedError()) def test_attach_interface_with_not_implemented(self, _mock): body = {'interfaceAttachment': {'net_id': FAKE_NET_ID1}} self.assertRaises(exc.HTTPNotImplemented, self.attachments.create, self.req, FAKE_UUID1, body=body) def test_detach_interface_with_invalid_state(self): def fake_detach_interface_invalid_state(*args, **kwargs): raise exception.InstanceInvalidState(instance_uuid='', attr='', state='', method='detach_interface') self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface_invalid_state) self.assertRaises(exc.HTTPConflict, self.attachments.delete, self.req, FAKE_UUID1, FAKE_NET_ID1) @mock.patch.object(compute_api.API, 'detach_interface', side_effect=NotImplementedError()) def test_detach_interface_with_not_implemented(self, _mock): self.assertRaises(exc.HTTPNotImplemented, self.attachments.delete, self.req, FAKE_UUID1, FAKE_NET_ID1) def test_attach_interface_invalid_fixed_ip(self): body = { 'interfaceAttachment': { 'net_id': FAKE_NET_ID1, 'fixed_ips': [{ 'ip_address': 'invalid_ip' }] } } self.assertRaises(self.validate_exc, self.attachments.create, self.req, FAKE_UUID1, body=body) @mock.patch.object(compute_api.API, 'get') @mock.patch.object(compute_api.API, 'attach_interface') def test_attach_interface_fixed_ip_already_in_use(self, attach_mock, get_mock): fake_instance = compute.Instance(uuid=FAKE_UUID1) get_mock.return_value = fake_instance attach_mock.side_effect = exception.FixedIpAlreadyInUse( address='10.0.2.2', instance_uuid=FAKE_UUID1) body = {} self.assertRaises(self.in_use_exc, self.attachments.create, self.req, FAKE_UUID1, body=body) ctxt = self.req.environ['compute.context'] attach_mock.assert_called_once_with(ctxt, fake_instance, None, None, None) get_mock.assert_called_once_with(ctxt, FAKE_UUID1, want_objects=True, expected_attrs=None) @mock.patch.object(compute_api.API, 'get') @mock.patch.object(compute_api.API, 'attach_interface') def test_attach_interface_port_in_use(self, attach_mock, get_mock): fake_instance = compute.Instance(uuid=FAKE_UUID1) get_mock.return_value = fake_instance attach_mock.side_effect = exception.PortInUse(port_id=FAKE_PORT_ID1) body = {} self.assertRaises(self.in_use_exc, self.attachments.create, self.req, FAKE_UUID1, body=body) ctxt = self.req.environ['compute.context'] attach_mock.assert_called_once_with(ctxt, fake_instance, None, None, None) get_mock.assert_called_once_with(ctxt, FAKE_UUID1, want_objects=True, expected_attrs=None) @mock.patch.object(compute_api.API, 'get') @mock.patch.object(compute_api.API, 'attach_interface') def test_attach_interface_port_not_usable(self, attach_mock, get_mock): fake_instance = compute.Instance(uuid=FAKE_UUID1) get_mock.return_value = fake_instance attach_mock.side_effect = exception.PortNotUsable( port_id=FAKE_PORT_ID1, instance=fake_instance.uuid) body = {} self.assertRaises(self.not_usable_exc, self.attachments.create, self.req, FAKE_UUID1, body=body) ctxt = self.req.environ['compute.context'] attach_mock.assert_called_once_with(ctxt, fake_instance, None, None, None) get_mock.assert_called_once_with(ctxt, FAKE_UUID1, want_objects=True, expected_attrs=None) @mock.patch.object(compute_api.API, 'get') @mock.patch.object(compute_api.API, 'attach_interface') def test_attach_interface_failed_no_network(self, attach_mock, get_mock): fake_instance = compute.Instance(uuid=FAKE_UUID1, project_id=FAKE_UUID2) get_mock.return_value = fake_instance attach_mock.side_effect = (exception.InterfaceAttachFailedNoNetwork( project_id=FAKE_UUID2)) self.assertRaises(exc.HTTPBadRequest, self.attachments.create, self.req, FAKE_UUID1, body={}) ctxt = self.req.environ['compute.context'] attach_mock.assert_called_once_with(ctxt, fake_instance, None, None, None) get_mock.assert_called_once_with(ctxt, FAKE_UUID1, want_objects=True, expected_attrs=None) @mock.patch.object(compute_api.API, 'get') @mock.patch.object(compute_api.API, 'attach_interface') def test_attach_interface_no_more_fixed_ips(self, attach_mock, get_mock): fake_instance = compute.Instance(uuid=FAKE_UUID1) get_mock.return_value = fake_instance attach_mock.side_effect = exception.NoMoreFixedIps(net=FAKE_NET_ID1) body = {} self.assertRaises(exc.HTTPBadRequest, self.attachments.create, self.req, FAKE_UUID1, body=body) ctxt = self.req.environ['compute.context'] attach_mock.assert_called_once_with(ctxt, fake_instance, None, None, None) get_mock.assert_called_once_with(ctxt, FAKE_UUID1, want_objects=True, expected_attrs=None) def _test_attach_interface_with_invalid_parameter(self, param): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) body = {'interface_attachment': param} self.assertRaises(exception.ValidationError, self.attachments.create, self.req, FAKE_UUID1, body=body) def test_attach_interface_instance_with_non_uuid_net_id(self): param = {'net_id': 'non_uuid'} self._test_attach_interface_with_invalid_parameter(param) def test_attach_interface_instance_with_non_uuid_port_id(self): param = {'port_id': 'non_uuid'} self._test_attach_interface_with_invalid_parameter(param) def test_attach_interface_instance_with_non_array_fixed_ips(self): param = {'fixed_ips': 'non_array'} self._test_attach_interface_with_invalid_parameter(param)