def assert_compute_node_has_enough_disk(self, context, instance_ref, dest): """Checks if destination host has enough disk for block migration. :param context: security context :param instance_ref: engine.db.sqlalchemy.models.Instance object :param dest: destination host """ # Getting total available memory and disk of host avail = self._get_compute_info(context, dest, 'local_gb') # Getting total used memory and disk of host # It should be sum of disks that are assigned as max value # because overcommiting is risky. used = 0 instance_refs = db.instance_get_all_by_host(context, dest) used_list = [i['local_gb'] for i in instance_refs] if used_list: used = reduce(lambda x, y: x + y, used_list) disk_inst = instance_ref['local_gb'] avail = avail - used if avail <= disk_inst: instance_id = ec2utils.id_to_ec2_id(instance_ref['id']) reason = _("Unable to migrate %(instance_id)s to %(dest)s: " "Lack of disk(host:%(avail)s " "<= instance:%(disk_inst)s)") raise exception.MigrationError(reason=reason % locals())
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: engine.db.sqlalchemy.models.Instance object """ # Checking instance is running. if instance_ref['power_state'] != power_state.RUNNING: instance_id = ec2utils.id_to_ec2_id(instance_ref['id']) raise exception.InstanceNotRunning(instance_id=instance_id) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref['volumes']) != 0: services = db.service_get_all_by_topic(context, 'volume') if len(services) < 1 or not self.service_is_up(services[0]): raise exception.VolumeServiceUnavailable() # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not self.service_is_up(services[0]): raise exception.ComputeServiceUnavailable(host=src)
def _live_migration_dest_check(self, context, instance_ref, dest, block_migration): """Live migration check routine (for destination host). :param context: security context :param instance_ref: engine.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not self.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: instance_id = ec2utils.id_to_ec2_id(instance_ref['id']) raise exception.UnableToMigrateToSelf(instance_id=instance_id, host=dest) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest, block_migration)
def test_vpn_dict_state_running(self): isonow = datetime.datetime.utcnow() vpn_instance = { 'id': 1, 'created_at': isonow, 'fixed_ip': { 'address': '127.0.0.1' } } project = type('Project', (object, ), { 'id': 'project', 'vpn_ip': '127.0.0.1', 'vpn_port': 1234 }) # Returns state running for 127.0.0.1 - look at class setup expected_vpn_dict = { 'project_id': 'project', 'public_ip': '127.0.0.1', 'public_port': 1234, 'internal_ip': '127.0.0.1', 'instance_id': ec2utils.id_to_ec2_id(1), 'created_at': utils.isotime(isonow), 'state': 'running' } self.assertEqual(expected_vpn_dict, admin.vpn_dict(project, vpn_instance))
def start_vpn(self, context, project): instance = self._vpn_for(context, project) if not instance: # NOTE(vish) import delayed because of __init__.py from engine.cloudpipe import pipelib pipe = pipelib.CloudPipe() proj = manager.AuthManager().get_project(project) user_id = proj.project_manager_id try: pipe.launch_vpn_instance(project, user_id) except db.NoMoreNetworks: raise exception.ApiError("Unable to claim IP for VPN instance" ", ensure it isn't running, and try " "again in a few minutes") instance = self._vpn_for(context, project) return {'instance_id': ec2utils.id_to_ec2_id(instance['id'])}
def vpn_dict(project, vpn_instance): rv = {'project_id': project.id, 'public_ip': project.vpn_ip, 'public_port': project.vpn_port} if vpn_instance: rv['instance_id'] = ec2utils.id_to_ec2_id(vpn_instance['id']) rv['created_at'] = utils.isotime(vpn_instance['created_at']) address = vpn_instance.get('fixed_ip', None) if address: rv['internal_ip'] = address['address'] if project.vpn_ip and project.vpn_port: if utils.vpn_ping(project.vpn_ip, project.vpn_port): rv['state'] = 'running' else: rv['state'] = 'down' else: rv['state'] = 'down - invalid project vpn config' else: rv['state'] = 'pending' return rv
def test_vpn_dict_state_running(self): isonow = datetime.datetime.utcnow() vpn_instance = {'id': 1, 'created_at': isonow, 'fixed_ip': {'address': '127.0.0.1'}} project = type('Project', (object,), {'id': 'project', 'vpn_ip': '127.0.0.1', 'vpn_port': 1234}) # Returns state running for 127.0.0.1 - look at class setup expected_vpn_dict = {'project_id': 'project', 'public_ip': '127.0.0.1', 'public_port': 1234, 'internal_ip': '127.0.0.1', 'instance_id': ec2utils.id_to_ec2_id(1), 'created_at': utils.isotime(isonow), 'state': 'running'} self.assertEqual(expected_vpn_dict, admin.vpn_dict(project, vpn_instance))
def vpn_dict(project, vpn_instance): rv = { 'project_id': project.id, 'public_ip': project.vpn_ip, 'public_port': project.vpn_port } if vpn_instance: rv['instance_id'] = ec2utils.id_to_ec2_id(vpn_instance['id']) rv['created_at'] = utils.isotime(vpn_instance['created_at']) address = vpn_instance.get('fixed_ip', None) if address: rv['internal_ip'] = address['address'] if project.vpn_ip and project.vpn_port: if utils.vpn_ping(project.vpn_ip, project.vpn_port): rv['state'] = 'running' else: rv['state'] = 'down' else: rv['state'] = 'down - invalid project vpn config' else: rv['state'] = 'pending' return rv
def test_id_to_ec2_id(self): self.assertEqual(ec2utils.id_to_ec2_id(30), 'i-0000001e') self.assertEqual(ec2utils.id_to_ec2_id(29, 'ami-%08x'), 'ami-0000001d') self.assertEqual(ec2utils.id_to_ec2_snap_id(28), 'snap-0000001c') self.assertEqual(ec2utils.id_to_ec2_vol_id(27), 'vol-0000001b')
def get_metadata(self, address): ctxt = context.get_admin_context() search_opts = {'fixed_ip': address, 'deleted': False} try: instance_ref = self.compute_api.get_all(ctxt, search_opts=search_opts) except exception.NotFound: instance_ref = None if not instance_ref: return None # This ensures that all attributes of the instance # are populated. instance_ref = db.instance_get(ctxt, instance_ref[0]['id']) mpi = self._get_mpi_data(ctxt, instance_ref['project_id']) hostname = "%s.%s" % (instance_ref['hostname'], FLAGS.dhcp_domain) host = instance_ref['host'] services = db.service_get_all_by_host(ctxt.elevated(), host) availability_zone = ec2utils.get_availability_zone_by_host( services, host) ip_info = ec2utils.get_ip_info_for_instance(ctxt, instance_ref) floating_ips = ip_info['floating_ips'] floating_ip = floating_ips and floating_ips[0] or '' ec2_id = ec2utils.id_to_ec2_id(instance_ref['id']) image_ec2_id = ec2utils.image_ec2_id(instance_ref['image_ref']) security_groups = db.security_group_get_by_instance( ctxt, instance_ref['id']) security_groups = [x['name'] for x in security_groups] mappings = self._format_instance_mapping(ctxt, instance_ref) data = { 'user-data': base64.b64decode(instance_ref['user_data']), 'meta-data': { 'ami-id': image_ec2_id, 'ami-launch-index': instance_ref['launch_index'], 'ami-manifest-path': 'FIXME', 'block-device-mapping': mappings, 'hostname': hostname, 'instance-action': 'none', 'instance-id': ec2_id, 'instance-type': instance_ref['instance_type']['name'], 'local-hostname': hostname, 'local-ipv4': address, 'placement': { 'availability-zone': availability_zone }, 'public-hostname': hostname, 'public-ipv4': floating_ip, 'reservation-id': instance_ref['reservation_id'], 'security-groups': security_groups, 'mpi': mpi } } # public-keys should be in meta-data only if user specified one if instance_ref['key_name']: data['meta-data']['public-keys'] = { '0': { '_name': instance_ref['key_name'], 'openssh-key': instance_ref['key_data'] } } for image_type in ['kernel', 'ramdisk']: if instance_ref.get('%s_id' % image_type): ec2_id = ec2utils.image_ec2_id( instance_ref['%s_id' % image_type], ec2utils.image_type(image_type)) data['meta-data']['%s-id' % image_type] = ec2_id if False: # TODO(vish): store ancestor ids data['ancestor-ami-ids'] = [] if False: # TODO(vish): store product codes data['product-codes'] = [] return data
def get_metadata(self, address): ctxt = context.get_admin_context() search_opts = {'fixed_ip': address, 'deleted': False} try: instance_ref = self.compute_api.get_all(ctxt, search_opts=search_opts) except exception.NotFound: instance_ref = None if not instance_ref: return None # This ensures that all attributes of the instance # are populated. instance_ref = db.instance_get(ctxt, instance_ref[0]['id']) mpi = self._get_mpi_data(ctxt, instance_ref['project_id']) hostname = "%s.%s" % (instance_ref['hostname'], FLAGS.dhcp_domain) host = instance_ref['host'] services = db.service_get_all_by_host(ctxt.elevated(), host) availability_zone = ec2utils.get_availability_zone_by_host(services, host) ip_info = ec2utils.get_ip_info_for_instance(ctxt, instance_ref) floating_ips = ip_info['floating_ips'] floating_ip = floating_ips and floating_ips[0] or '' ec2_id = ec2utils.id_to_ec2_id(instance_ref['id']) image_ec2_id = ec2utils.image_ec2_id(instance_ref['image_ref']) security_groups = db.security_group_get_by_instance(ctxt, instance_ref['id']) security_groups = [x['name'] for x in security_groups] mappings = self._format_instance_mapping(ctxt, instance_ref) data = { 'user-data': base64.b64decode(instance_ref['user_data']), 'meta-data': { 'ami-id': image_ec2_id, 'ami-launch-index': instance_ref['launch_index'], 'ami-manifest-path': 'FIXME', 'block-device-mapping': mappings, 'hostname': hostname, 'instance-action': 'none', 'instance-id': ec2_id, 'instance-type': instance_ref['instance_type']['name'], 'local-hostname': hostname, 'local-ipv4': address, 'placement': {'availability-zone': availability_zone}, 'public-hostname': hostname, 'public-ipv4': floating_ip, 'reservation-id': instance_ref['reservation_id'], 'security-groups': security_groups, 'mpi': mpi}} # public-keys should be in meta-data only if user specified one if instance_ref['key_name']: data['meta-data']['public-keys'] = { '0': {'_name': instance_ref['key_name'], 'openssh-key': instance_ref['key_data']}} for image_type in ['kernel', 'ramdisk']: if instance_ref.get('%s_id' % image_type): ec2_id = ec2utils.image_ec2_id( instance_ref['%s_id' % image_type], ec2utils.image_type(image_type)) data['meta-data']['%s-id' % image_type] = ec2_id if False: # TODO(vish): store ancestor ids data['ancestor-ami-ids'] = [] if False: # TODO(vish): store product codes data['product-codes'] = [] return data
def __call__(self, req): context = req.environ['engine.context'] api_request = req.environ['ec2.request'] result = None try: result = api_request.invoke(context) except exception.InstanceNotFound as ex: LOG.info(_('InstanceNotFound raised: %s'), unicode(ex), context=context) ec2_id = ec2utils.id_to_ec2_id(ex.kwargs['instance_id']) message = ex.message % {'instance_id': ec2_id} return self._error(req, context, type(ex).__name__, message) except exception.VolumeNotFound as ex: LOG.info(_('VolumeNotFound raised: %s'), unicode(ex), context=context) ec2_id = ec2utils.id_to_ec2_vol_id(ex.kwargs['volume_id']) message = ex.message % {'volume_id': ec2_id} return self._error(req, context, type(ex).__name__, message) except exception.SnapshotNotFound as ex: LOG.info(_('SnapshotNotFound raised: %s'), unicode(ex), context=context) ec2_id = ec2utils.id_to_ec2_snap_id(ex.kwargs['snapshot_id']) message = ex.message % {'snapshot_id': ec2_id} return self._error(req, context, type(ex).__name__, message) except exception.NotFound as ex: LOG.info(_('NotFound raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.ApiError as ex: LOG.exception(_('ApiError raised: %s'), unicode(ex), context=context) if ex.code: return self._error(req, context, ex.code, unicode(ex)) else: return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.KeyPairExists as ex: LOG.debug(_('KeyPairExists raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.InvalidParameterValue as ex: LOG.debug(_('InvalidParameterValue raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.InvalidPortRange as ex: LOG.debug(_('InvalidPortRange raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.NotAuthorized as ex: LOG.info(_('NotAuthorized raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.InvalidRequest as ex: LOG.debug(_('InvalidRequest raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) except Exception as ex: extra = {'environment': req.environ} LOG.exception(_('Unexpected error raised: %s'), unicode(ex), extra=extra, context=context) return self._error(req, context, 'UnknownError', _('An unknown error has occurred. ' 'Please try your request again.')) else: resp = webob.Response() resp.status = 200 resp.headers['Content-Type'] = 'text/xml' resp.body = str(result) return resp