示例#1
0
    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())
示例#2
0
    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)
示例#3
0
    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)
示例#4
0
    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))
示例#5
0
    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())
示例#6
0
    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)
示例#7
0
    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)
示例#8
0
 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'])}
示例#9
0
 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'])}
示例#10
0
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
示例#11
0
    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))
示例#12
0
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
示例#13
0
 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')
示例#14
0
    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
示例#15
0
    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
示例#16
0
 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