Example #1
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if not t_context.is_admin_context(context):
            pecan.abort(400, _('Admin role required to create bindings'))
            return

        if 'pod_binding' not in kw:
            pecan.abort(400, _('Request body not found'))
            return

        pod_b = kw['pod_binding']
        tenant_id = pod_b.get('tenant_id', '').strip()
        pod_id = pod_b.get('pod_id', '').strip()
        _uuid = uuidutils.generate_uuid()

        if tenant_id == '' or pod_id == '':
            return Response(_('Tenant_id and pod_id can not be empty'), 422)

        # the az_pod_map_id should be exist for in the pod map table
        try:
            with context.session.begin():
                pod = core.get_resource(context, models.Pod, pod_id)
                if pod.get('az_name') == '':
                    return Response(_('Top region can not be bound'), 422)
        except t_exc.ResourceNotFound:
            return Response(_('pod_id not found in pod'), 422)
        except Exception as e:
            LOG.exception(
                _LE('Failed to get_resource for pod_id: '
                    '%(pod_id)s ,'
                    '%(exception)s '), {
                        'pod_id': pod_id,
                        'exception': e
                    })
            pecan.abort(500, _('Failed to create pod binding'))
            return

        try:
            with context.session.begin():
                pod_binding = core.create_resource(context, models.PodBinding,
                                                   {
                                                       'id': _uuid,
                                                       'tenant_id': tenant_id,
                                                       'pod_id': pod_id
                                                   })
        except db_exc.DBDuplicateEntry:
            return Response(_('Pod binding already exists'), 409)
        except db_exc.DBConstraintError:
            return Response(_('pod_id not exists in pod'), 422)
        except db_exc.DBReferenceError:
            return Response(_('DB reference not exists in pod'), 422)
        except Exception as e:
            LOG.exception(_LE('Failed to create pod binding: %(exception)s '),
                          {'exception': e})
            pecan.abort(500, _('Failed to create pod binding'))
            return

        return {'pod_binding': pod_binding}
Example #2
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if not t_context.is_admin_context(context):
            pecan.abort(400, _('Admin role required to create bindings'))
            return

        if 'pod_binding' not in kw:
            pecan.abort(400, _('Request body not found'))
            return

        pod_b = kw['pod_binding']
        tenant_id = pod_b.get('tenant_id', '').strip()
        pod_id = pod_b.get('pod_id', '').strip()
        _uuid = uuidutils.generate_uuid()

        if tenant_id == '' or pod_id == '':
            return Response(
                _('Tenant_id and pod_id can not be empty'),
                422)

        # the az_pod_map_id should be exist for in the pod map table
        try:
            with context.session.begin():
                pod = core.get_resource(context, models.Pod,
                                        pod_id)
                if pod.get('az_name') == '':
                    return Response(_('Top region can not be bound'), 422)
        except t_exc.ResourceNotFound:
            return Response(_('pod_id not found in pod'), 422)
        except Exception as e:
            LOG.error(_LE('Fail to create pod binding: %(exception)s'),
                      {'exception': e})
            pecan.abort(500, _('Fail to create pod binding'))
            return

        try:
            with context.session.begin():
                pod_binding = core.create_resource(context, models.PodBinding,
                                                   {'id': _uuid,
                                                    'tenant_id': tenant_id,
                                                    'pod_id': pod_id})
        except db_exc.DBDuplicateEntry:
            return Response(_('Pod binding already exists'), 409)
        except db_exc.DBConstraintError:
            return Response(_('pod_id not exists in pod'), 422)
        except db_exc.DBReferenceError:
            return Response(_('DB reference not exists in pod'), 422)
        except Exception as e:
            LOG.error(_LE('Fail to create pod binding: %(exception)s'),
                      {'exception': e})
            pecan.abort(500, _('Fail to create pod binding'))
            return

        return {'pod_binding': pod_binding}
Example #3
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_BINDINGS_CREATE):
            pecan.abort(401, _('Unauthorized to create bindings'))
            return

        if 'pod_binding' not in kw:
            pecan.abort(400, _('Request body not found'))
            return

        pod_b = kw['pod_binding']
        tenant_id = pod_b.get('tenant_id', '').strip()
        pod_id = pod_b.get('pod_id', '').strip()

        if tenant_id == '' or pod_id == '':
            return Response(
                _('Tenant_id and pod_id can not be empty'),
                422)

        # the az_pod_map_id should be exist for in the pod map table
        try:
            with context.session.begin():
                pod = core.get_resource(context, models.Pod,
                                        pod_id)
                if pod.get('az_name') == '':
                    return Response(_('Top region can not be bound'), 422)
        except t_exc.ResourceNotFound:
            return Response(_('pod_id not found in pod'), 422)
        except Exception as e:
            LOG.exception(_LE('Failed to get_resource for pod_id: '
                              '%(pod_id)s ,'
                              '%(exception)s '),
                          {'pod_id': pod_id,
                          'exception': e})
            pecan.abort(500, _('Failed to create pod binding'))
            return

        try:
            pod_binding = db_api.create_pod_binding(
                context, tenant_id, pod_id)
        except db_exc.DBDuplicateEntry:
            return Response(_('Pod binding already exists'), 409)
        except db_exc.DBConstraintError:
            return Response(_('pod_id not exists in pod'), 422)
        except db_exc.DBReferenceError:
            return Response(_('DB reference not exists in pod'), 422)
        except Exception as e:
            LOG.exception(_LE('Failed to create pod binding: %(exception)s '),
                          {'exception': e})
            pecan.abort(500, _('Failed to create pod binding'))
            return

        return {'pod_binding': pod_binding}
Example #4
0
    def _check_bridge_network_type(self, bridge_network_type):
        if not bridge_network_type:
            return
        if bridge_network_type == 'local':
            LOG.error(_LE("Local is not a valid bridge network type. "
                          "Service terminated!"), bridge_network_type)
            raise SystemExit(1)

        type_set = set(self.tenant_network_types)
        if bridge_network_type not in type_set:
            LOG.error(_LE("Bridge network type %s is not registered. "
                          "Service terminated!"), bridge_network_type)
            raise SystemExit(1)
Example #5
0
    def _check_bridge_network_type(self, bridge_network_type):
        if not bridge_network_type:
            return
        if bridge_network_type == 'local':
            LOG.error(_LE("Local is not a valid bridge network type. "
                          "Service terminated!"), bridge_network_type)
            raise SystemExit(1)

        type_set = set(self.tenant_network_types)
        if bridge_network_type not in type_set:
            LOG.error(_LE("Bridge network type %s is not registered. "
                          "Service terminated!"), bridge_network_type)
            raise SystemExit(1)
Example #6
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_PODS_DELETE):
            pecan.abort(401, _('Unauthorized to delete pods'))
            return

        try:
            with context.session.begin():
                pod = core.get_resource(context, models.Pod, _id)
                if pod is not None:
                    ag_name = utils.get_ag_name(pod['pod_name'])
                    ag = az_ag.get_ag_by_name(context, ag_name)
                    if ag is not None:
                        az_ag.delete_ag(context, ag['id'])
                core.delete_resource(context, models.Pod, _id)
                pecan.response.status = 200
                return {}
        except t_exc.ResourceNotFound:
            return Response(_('Pod not found'), 404)
        except Exception as e:
            LOG.exception(_LE('Failed to delete pod: %(pod_id)s,'
                              '%(exception)s'),
                          {'pod_id': _id,
                           'exception': e})

            return Response(_('Failed to delete pod'), 500)
Example #7
0
def enforce(context, rule=None, target=None, *args, **kwargs):
    """Check authorization of a rule against the target and credentials.

        :param dict context: As much information about the user performing the
                             action as possible.
        :param rule: The rule to evaluate.
        :param dict target: As much information about the object being operated
                            on as possible.
        :return: ``True`` if the policy allows the action.
                 ``False`` if the policy does not allow the action.
    """
    enforcer = init()
    credentials = context.to_dict()
    if target is None:
        target = {'project_id': context.project_id,
                  'user_id': context.user_id}

    exc = t_exec.PolicyNotAuthorized

    try:
        result = enforcer.enforce(rule, target, credentials,
                                  do_raise=True, exc=exc, *args, **kwargs)

    except t_exec.PolicyNotAuthorized as e:
        result = False
        LOG.exception(_LE("%(msg)s, %(rule)s, %(target)s"),
                      {'msg': str(e), 'rule': rule, 'target': target})
    return result
Example #8
0
def get_pod_by_az_tenant(context, az_name, tenant_id):
    pod_bindings = core.query_resource(context,
                                       models.PodBinding,
                                       [{'key': 'tenant_id',
                                         'comparator': 'eq',
                                         'value': tenant_id}],
                                       [])
    for pod_b in pod_bindings:
        pod = core.get_resource(context,
                                models.Pod,
                                pod_b['pod_id'])
        if pod['az_name'] == az_name:
            return pod, pod['pod_az_name']

    # TODO(joehuang): schedule one dynamically in the future
    filters = [{'key': 'az_name', 'comparator': 'eq', 'value': az_name}]
    pods = db_api.list_pods(context, filters=filters)
    for pod in pods:
        if pod['pod_name'] != '':
            try:
                with context.session.begin():
                    core.create_resource(
                        context, models.PodBinding,
                        {'id': uuidutils.generate_uuid(),
                         'tenant_id': tenant_id,
                         'pod_id': pod['pod_id']})
                    return pod, pod['pod_az_name']
            except Exception as e:
                LOG.error(_LE('Fail to create pod binding: %(exception)s'),
                          {'exception': e})
                return None, None

    return None, None
Example #9
0
def enforce(context, rule=None, target=None, *args, **kwargs):
    """Check authorization of a rule against the target and credentials.

        :param dict context: As much information about the user performing the
                             action as possible.
        :param rule: The rule to evaluate.
        :param dict target: As much information about the object being operated
                            on as possible.
        :return: ``True`` if the policy allows the action.
                 ``False`` if the policy does not allow the action.
    """
    enforcer = init()
    credentials = context.to_dict()
    if target is None:
        target = {'project_id': context.project_id,
                  'user_id': context.user_id}

    exc = t_exec.PolicyNotAuthorized

    try:
        result = enforcer.enforce(rule, target, credentials,
                                  do_raise=True, exc=exc, *args, **kwargs)

    except t_exec.PolicyNotAuthorized as e:
        result = False
        LOG.exception(_LE("%(msg)s, %(rule)s, %(target)s"),
                      {'msg': str(e), 'rule': rule, 'target': target})
    return result
Example #10
0
def get_pod_by_az_tenant(context, az_name, tenant_id):
    pod_bindings = core.query_resource(context, models.PodBinding,
                                       [{
                                           'key': 'tenant_id',
                                           'comparator': 'eq',
                                           'value': tenant_id
                                       }], [])
    for pod_b in pod_bindings:
        pod = core.get_resource(context, models.Pod, pod_b['pod_id'])
        if pod['az_name'] == az_name:
            return pod, pod['pod_az_name']

    # TODO(joehuang): schedule one dynamically in the future
    filters = [{'key': 'az_name', 'comparator': 'eq', 'value': az_name}]
    pods = db_api.list_pods(context, filters=filters)
    for pod in pods:
        if pod['pod_name'] != '':
            try:
                with context.session.begin():
                    core.create_resource(
                        context, models.PodBinding, {
                            'id': uuidutils.generate_uuid(),
                            'tenant_id': tenant_id,
                            'pod_id': pod['pod_id']
                        })
                    return pod, pod['pod_az_name']
            except Exception as e:
                LOG.error(_LE('Fail to create pod binding: %(exception)s'),
                          {'exception': e})
                return None, None

    return None, None
Example #11
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        if not t_context.is_admin_context(context):
            pecan.abort(400, _('Admin role required to delete pods'))
            return

        try:
            with context.session.begin():
                pod = core.get_resource(context, models.Pod, _id)
                if pod is not None:
                    ag_name = utils.get_ag_name(pod['pod_name'])
                    ag = az_ag.get_ag_by_name(context, ag_name)
                    if ag is not None:
                        az_ag.delete_ag(context, ag['id'])
                core.delete_resource(context, models.Pod, _id)
                pecan.response.status = 200
        except t_exc.ResourceNotFound:
            return Response(_('Pod not found'), 404)
        except Exception as e:
            LOG.exception(
                _LE('Failed to delete pod: %(pod_id)s,'
                    '%(exception)s'), {
                        'pod_id': _id,
                        'exception': e
                    })

            return Response(_('Failed to delete pod'), 500)
Example #12
0
    def _should_format(self):

        if self.kwargs['message'] is None and '%(message)' in self.message:
            LOG.error(_LE('\%(message)s in message '
                          'but init parameter is None'))

        return self.kwargs['message'] is None or '%(message)' in self.message
Example #13
0
    def delete(self, _id):
        """Marks volume types as deleted.

        :param _id: id of volume type to be deleted
        """
        context = t_context.extract_context_from_environ()

        if not context.is_admin:
            return utils.format_cinder_error(
                403,
                _("Policy doesn't allow volume_extension:types_manage "
                  "to be performed."))

        session = core.get_session()
        with session.begin():
            try:
                db_api.volume_type_get(context, _id, session)
            except exceptions.VolumeTypeNotFound as e:
                return utils.format_cinder_error(404, e.message)
            try:
                db_api.volume_type_delete(context, _id, session)
            except Exception as e:
                LOG.exception(
                    _LE('Fail to update volume type: %(id)s,'
                        '%(exception)s'), {
                            'id': _id,
                            'exception': e
                        })
                return utils.format_cinder_error(
                    500, _('Fail to delete volume type.'))

        pecan.response.status = 202
        return pecan.response
Example #14
0
    def update_subnet(self, ctx, payload):
        """update bottom subnet

        if bottom pod id equal to POD_NOT_SPECIFIED, dispatch jobs for every
        mapped bottom pod via RPC, otherwise update subnet in the specified
        pod.

        :param ctx: tricircle context
        :param payload: dict whose key is JT_SUBNET_UPDATE and value
        is "top_subnet_id#bottom_pod_id"
        :return: None
        """
        (b_pod_id, t_subnet_id) = payload[
            constants.JT_SUBNET_UPDATE].split('#')
        if b_pod_id == constants.POD_NOT_SPECIFIED:
            mappings = db_api.get_bottom_mappings_by_top_id(
                ctx, t_subnet_id, constants.RT_SUBNET)
            b_pods = [mapping[0] for mapping in mappings]
            for b_pod in b_pods:
                self.xjob_handler.update_subnet(ctx, t_subnet_id,
                                                b_pod['pod_id'])
            return

        t_client = self._get_client()
        t_subnet = t_client.get_subnets(ctx, t_subnet_id)
        if not t_subnet:
            return
        b_pod = db_api.get_pod(ctx, b_pod_id)
        b_region_name = b_pod['region_name']
        b_subnet_id = db_api.get_bottom_id_by_top_id_region_name(
            ctx, t_subnet_id, b_region_name, constants.RT_SUBNET)
        b_client = self._get_client(region_name=b_region_name)
        b_subnet = b_client.get_subnets(ctx, b_subnet_id)
        b_gateway_ip = b_subnet['gateway_ip']

        # we need to remove the bottom subnet gateway ip from the top subnet
        # allaction pools
        b_allocation_pools = helper.NetworkHelper.get_bottom_subnet_pools(
            t_subnet, b_gateway_ip)

        # bottom gateway_ip doesn't need to be updated, because it is reserved
        # by top pod.
        # name is not allowed to be updated, because it is used by
        # lock_handle to retrieve bottom/local resources that have been
        # created but not registered in the resource routing table
        body = {
            'subnet':
                {'description': t_subnet['description'],
                 'enable_dhcp': t_subnet['enable_dhcp'],
                 'allocation_pools': b_allocation_pools,
                 'host_routes': t_subnet['host_routes'],
                 'dns_nameservers': t_subnet['dns_nameservers']}
        }
        try:
            b_client.update_subnets(ctx, b_subnet_id, body)
        except q_cli_exceptions.NotFound:
            LOG.error(_LE('subnet: %(subnet_id)s not found, '
                          'pod name: %(name)s'),
                      {'subnet_id': b_subnet_id, 'name': b_region_name})
Example #15
0
    def _should_format(self):

        if self.kwargs['message'] is None and '%(message)' in self.message:
            LOG.error(
                _LE('\%(message)s in message '
                    'but init parameter is None'))

        return self.kwargs['message'] is None or '%(message)' in self.message
Example #16
0
 def _process_metadata_quota(self, context, t_server_dict):
     try:
         ctx = context.elevated()
         metadata = t_server_dict.get('metadata', None)
         self._check_metadata_properties_quota(ctx, metadata)
     except t_exceptions.InvalidMetadata as e1:
         LOG.exception(_LE('Invalid metadata %(exception)s'),
                       {'exception': str(e1)})
         pecan.abort(400, _('Invalid metadata'))
     except t_exceptions.InvalidMetadataSize as e2:
         LOG.exception(_LE('Invalid metadata size %(exception)s'),
                       {'exception': str(e2)})
         pecan.abort(400, _('Invalid metadata size'))
     except t_exceptions.MetadataLimitExceeded as e3:
         LOG.exception(_LE('Quota exceeded %(exception)s'),
                       {'exception': str(e3)})
         pecan.abort(400, _('Quota exceeded in metadata'))
Example #17
0
 def _parse_network_vlan_ranges(self):
     try:
         self.network_vlan_ranges = plugin_utils.parse_network_vlan_ranges(
             cfg.CONF.tricircle.network_vlan_ranges)
     except Exception:
         LOG.exception(_LE('Failed to parse network_vlan_ranges. '
                           'Service terminated!'))
         sys.exit(1)
     LOG.info(_LI('Network VLAN ranges: %s'), self.network_vlan_ranges)
Example #18
0
    def _get_all(self, context):

        # TODO(joehuang): query optimization for pagination, sort, etc
        ret = []
        pods = az_ag.list_pods_by_tenant(context, self.tenant_id)
        for pod in pods:
            if pod['pod_name'] == '':
                continue

            query = urlparse.urlsplit(request.url).query
            query_filters = urlparse.parse_qsl(query)
            skip_pod = False
            for k, v in query_filters:
                if k == 'availability_zone' and v != pod['az_name']:
                    skip_pod = True
                    break
            if skip_pod:
                continue

            s_ctx = hclient.get_pod_service_ctx(
                context,
                request.url,
                pod['pod_name'],
                s_type=cons.ST_CINDER)
            if s_ctx['b_url'] == '':
                LOG.error(_LE("bottom pod endpoint incorrect %s")
                          % pod['pod_name'])
                continue

            # TODO(joehuang): convert header and body content
            resp = hclient.forward_req(context, 'GET',
                                       request.headers,
                                       s_ctx['b_url'],
                                       request.body)

            if resp.status_code == 200:

                routings = db_api.get_bottom_mappings_by_tenant_pod(
                    context, self.tenant_id,
                    pod['pod_id'], cons.RT_VOLUME
                )

                b_ret_body = jsonutils.loads(resp.content)
                if b_ret_body.get('volumes'):
                    for vol in b_ret_body['volumes']:

                        if not routings.get(vol['id']):
                            b_ret_body['volumes'].remove(vol)
                            continue

                        vol['availability_zone'] = pod['az_name']

                    ret.extend(b_ret_body['volumes'])
        return ret
Example #19
0
    def _get_all(self, context):

        # TODO(joehuang): query optimization for pagination, sort, etc
        ret = []
        pods = az_ag.list_pods_by_tenant(context, self.tenant_id)
        for pod in pods:
            if pod['pod_name'] == '':
                continue

            query = urlparse.urlsplit(request.url).query
            query_filters = urlparse.parse_qsl(query)
            skip_pod = False
            for k, v in query_filters:
                if k == 'availability_zone' and v != pod['az_name']:
                    skip_pod = True
                    break
            if skip_pod:
                continue

            s_ctx = hclient.get_pod_service_ctx(context,
                                                request.url,
                                                pod['pod_name'],
                                                s_type=cons.ST_CINDER)
            if s_ctx['b_url'] == '':
                LOG.error(
                    _LE("bottom pod endpoint incorrect %s") % pod['pod_name'])
                continue

            # TODO(joehuang): get the release of top and bottom
            t_release = cons.R_MITAKA
            b_release = cons.R_MITAKA
            b_headers = hclient.convert_header(t_release, b_release,
                                               request.headers)

            resp = hclient.forward_req(context, 'GET', b_headers,
                                       s_ctx['b_url'], request.body)

            if resp.status_code == 200:

                routings = db_api.get_bottom_mappings_by_tenant_pod(
                    context, self.tenant_id, pod['pod_id'], cons.RT_VOLUME)

                b_ret_body = jsonutils.loads(resp.content)
                if b_ret_body.get('volumes'):
                    for vol in b_ret_body['volumes']:

                        if not routings.get(vol['id']):
                            b_ret_body['volumes'].remove(vol)
                            continue

                        vol['availability_zone'] = pod['az_name']

                    ret.extend(b_ret_body['volumes'])
        return ret
Example #20
0
 def _process_injected_file_quota(self, context, t_server_dict):
     try:
         ctx = context.elevated()
         injected_files = t_server_dict.get('injected_files', None)
         self._check_injected_file_quota(ctx, injected_files)
     except (t_exceptions.OnsetFileLimitExceeded,
             t_exceptions.OnsetFilePathLimitExceeded,
             t_exceptions.OnsetFileContentLimitExceeded) as e:
         msg = str(e)
         LOG.exception(_LE('Quota exceeded %(msg)s'),
                       {'msg': msg})
         pecan.abort(400, _('Quota exceeded %s') % msg)
Example #21
0
    def stop(self):
        try:
            self.rpc_server.stop()
        except Exception:
            pass

        try:
            self.manager.cleanup_host()
        except Exception:
            LOG.exception(_LE('Service error occurred during cleanup_host'))
            pass

        super(XService, self).stop()
Example #22
0
    def stop(self):
        try:
            self.rpc_server.stop()
        except Exception:
            pass

        try:
            self.manager.cleanup_host()
        except Exception:
            LOG.exception(_LE('Service error occurred during cleanup_host'))
            pass

        super(XService, self).stop()
Example #23
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if 'volumeAttachment' not in kw:
            return utils.format_nova_error(
                400, _('volumeAttachment is not set'))
        body = kw['volumeAttachment']
        if 'volumeId' not in body:
            return utils.format_nova_error(
                400, _('Invalid input for field/attribute volumeAttachment'))

        server_mappings = db_api.get_bottom_mappings_by_top_id(
            context, self.server_id, constants.RT_SERVER)
        if not server_mappings:
            return utils.format_nova_error(404, _('Instance %s could not be '
                                                  'found.') % self.server_id)
        volume_mappings = db_api.get_bottom_mappings_by_top_id(
            context, body['volumeId'], constants.RT_VOLUME)
        if not volume_mappings:
            return utils.format_nova_error(
                404, _('Volume %s could not be found') % body['volumeId'])

        server_pod_name = server_mappings[0][0]['pod_name']
        volume_pod_name = volume_mappings[0][0]['pod_name']
        if server_pod_name != volume_pod_name:
            LOG.error(_LE('Server %(server)s is in pod %(server_pod)s and '
                          'volume %(volume)s is in pod %(volume_pod)s, which '
                          'are not the same.'),
                      {'server': self.server_id,
                       'server_pod': server_pod_name,
                       'volume': body['volumeId'],
                       'volume_pod': volume_pod_name})
            return utils.format_nova_error(
                400, _('Server and volume not in the same pod'))

        device = None
        if 'device' in body:
            device = body['device']
            # this regular expression is copied from nova/block_device.py
            match = re.match('(^/dev/x{0,1}[a-z]{0,1}d{0,1})([a-z]+)[0-9]*$',
                             device)
            if not match:
                return utils.format_nova_error(
                    400, _('The supplied device path (%s) is '
                           'invalid.') % device)

        client = self._get_client(server_pod_name)
        volume = client.action_server_volumes(
            context, 'create_server_volume',
            server_mappings[0][1], volume_mappings[0][1], device)
        return {'volumeAttachment': volume.to_dict()}
    def _prep_block_device(self, context, instance, bdms,
                           do_check_attach=True):
        """Set up the block device for an instance with error logging."""
        try:
            block_device_info = {
                'root_device_name': instance['root_device_name'],
                'swap': driver_block_device.convert_swap(bdms),
                'ephemerals': driver_block_device.convert_ephemerals(bdms),
                'block_device_mapping': (
                    driver_block_device.attach_block_devices(
                        driver_block_device.convert_volumes(bdms),
                        context, instance, self.volume_api,
                        self.driver, do_check_attach=do_check_attach) +
                    driver_block_device.attach_block_devices(
                        driver_block_device.convert_snapshots(bdms),
                        context, instance, self.volume_api,
                        self.driver, self._await_block_device_map_created,
                        do_check_attach=do_check_attach) +
                    driver_block_device.attach_block_devices(
                        driver_block_device.convert_images(bdms),
                        context, instance, self.volume_api,
                        self.driver, self._await_block_device_map_created,
                        do_check_attach=do_check_attach) +
                    driver_block_device.attach_block_devices(
                        driver_block_device.convert_blanks(bdms),
                        context, instance, self.volume_api,
                        self.driver, self._await_block_device_map_created,
                        do_check_attach=do_check_attach))
            }

            if self.use_legacy_block_device_info:
                for bdm_type in ('swap', 'ephemerals', 'block_device_mapping'):
                    block_device_info[bdm_type] = \
                        driver_block_device.legacy_block_devices(
                            block_device_info[bdm_type])

            # Get swap out of the list
            block_device_info['swap'] = driver_block_device.get_swap(
                block_device_info['swap'])
            return block_device_info

        except exception.OverQuota:
            msg = _LW('Failed to create block device for instance due to '
                      'being over volume resource quota')
            LOG.warn(msg, instance=instance)
            raise exception.InvalidBDM()

        except Exception:
            LOG.exception(_LE('Instance failed block device setup'),
                          instance=instance)
            raise exception.InvalidBDM()
    def _cleanup_allocated_networks(self, context, instance,
                                    requested_networks):
        try:
            self._deallocate_network(context, instance, requested_networks)
        except Exception:
            msg = _LE('Failed to deallocate networks')
            LOG.exception(msg, instance=instance)
            return

        instance.system_metadata['network_allocated'] = 'False'
        try:
            instance.save()
        except exception.InstanceNotFound:
            pass
Example #26
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if 'volumeAttachment' not in kw:
            pecan.abort(400, 'Request body not found')
            return
        body = kw['volumeAttachment']
        if 'volumeId' not in body:
            pecan.abort(400, 'Volume not set')
            return

        server_mappings = db_api.get_bottom_mappings_by_top_id(
            context, self.server_id, constants.RT_SERVER)
        if not server_mappings:
            pecan.abort(404, 'Server not found')
            return
        volume_mappings = db_api.get_bottom_mappings_by_top_id(
            context, body['volumeId'], constants.RT_VOLUME)
        if not volume_mappings:
            pecan.abort(404, 'Volume not found')
            return

        server_pod_name = server_mappings[0][0]['pod_name']
        volume_pod_name = volume_mappings[0][0]['pod_name']
        if server_pod_name != volume_pod_name:
            LOG.error(_LE('Server %(server)s is in pod %(server_pod)s and '
                          'volume %(volume)s is in pod %(volume_pod)s, which '
                          'are not the same.'),
                      {'server': self.server_id,
                       'server_pod': server_pod_name,
                       'volume': body['volumeId'],
                       'volume_pod': volume_pod_name})
            pecan.abort(400, 'Server and volume not in the same pod')
            return

        device = None
        if 'device' in body:
            device = body['device']
            # this regular expression is copied from nova/block_device.py
            match = re.match('(^/dev/x{0,1}[a-z]{0,1}d{0,1})([a-z]+)[0-9]*$',
                             device)
            if not match:
                pecan.abort(400, 'Invalid device path')
                return

        client = self._get_client(server_pod_name)
        volume = client.action_server_volumes(
            context, 'create_server_volume',
            server_mappings[0][1], volume_mappings[0][1], device)
        return {'volumeAttachment': volume.to_dict()}
Example #27
0
    def get_all(self):
        context = t_context.extract_context_from_environ()

        if not t_context.is_admin_context(context):
            pecan.abort(400, _('Admin role required to list pods'))
            return

        try:
            return {'pods': db_api.list_pods(context)}
        except Exception as e:
            LOG.error(_LE('Fail to list pod: %(exception)s'),
                      {'exception': e})
            pecan.abort(500, _('Fail to list pod'))
            return
Example #28
0
    def update_network(self, ctx, payload):
        """update bottom network

        if bottom pod id equal to POD_NOT_SPECIFIED, dispatch jobs for every
        mapped bottom pod via RPC, otherwise update network in the specified
        pod.

        :param ctx: tricircle context
        :param payload: dict whose key is JT_NETWORK_UPDATE and value
        is "top_network_id#bottom_pod_id"
        :return: None
        """
        (b_pod_id, t_network_id) = payload[
            constants.JT_NETWORK_UPDATE].split('#')
        if b_pod_id == constants.POD_NOT_SPECIFIED:
            mappings = db_api.get_bottom_mappings_by_top_id(
                ctx, t_network_id, constants.RT_NETWORK)
            b_pods = [mapping[0] for mapping in mappings]
            for b_pod in b_pods:
                self.xjob_handler.update_network(ctx, t_network_id,
                                                 b_pod['pod_id'])
            return

        t_client = self._get_client()
        t_network = t_client.get_networks(ctx, t_network_id)
        if not t_network:
            return
        b_pod = db_api.get_pod(ctx, b_pod_id)
        b_region_name = b_pod['region_name']
        b_client = self._get_client(region_name=b_region_name)
        b_network_id = db_api.get_bottom_id_by_top_id_region_name(
            ctx, t_network_id, b_region_name, constants.RT_NETWORK)
        # name is not allowed to be updated, because it is used by
        # lock_handle to retrieve bottom/local resources that have been
        # created but not registered in the resource routing table
        body = {
            'network': {
                'description': t_network['description'],
                'admin_state_up': t_network['admin_state_up'],
                'shared': t_network['shared']
            }
        }

        try:
            b_client.update_networks(ctx, b_network_id, body)
        except q_cli_exceptions.NotFound:
            LOG.error(_LE('network: %(net_id)s not found,'
                          'pod name: %(name)s'),
                      {'net_id': b_network_id, 'name': b_region_name})
Example #29
0
    def get_all(self):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_PODS_LIST):
            pecan.abort(401, _('Unauthorized to list pods'))
            return

        try:
            return {'pods': db_api.list_pods(context)}
        except Exception as e:
            LOG.exception(_LE('Failed to list all pods: %(exception)s '),
                          {'exception': e})

            pecan.abort(500, _('Failed to list pods'))
            return
Example #30
0
    def get_all(self):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_PODS_LIST):
            pecan.abort(401, _('Unauthorized to list pods'))
            return

        try:
            return {'pods': db_api.list_pods(context)}
        except Exception as e:
            LOG.exception(_LE('Failed to list all pods: %(exception)s '),
                          {'exception': e})

            pecan.abort(500, _('Failed to list pods'))
            return
Example #31
0
    def _get_top_region(self, ctx):
        top_region_name = ''
        try:
            with ctx.session.begin():
                pods = core.query_resource(ctx, models.Pod, [], [])
                for pod in pods:
                    if pod['az_name'] == '' and pod['pod_name'] != '':
                        return pod['pod_name']
        except Exception as e:
            LOG.exception(_LE('Failed to get top region: %(exception)s '),
                          {'exception': e})

            return top_region_name

        return top_region_name
Example #32
0
    def get_all(self):
        context = t_context.extract_context_from_environ()

        if not t_context.is_admin_context(context):
            pecan.abort(400, _('Admin role required to list pods'))
            return

        try:
            return {'pods': db_api.list_pods(context)}
        except Exception as e:
            LOG.exception(_LE('Failed to list all pods: %(exception)s '),
                          {'exception': e})

            pecan.abort(500, _('Failed to list pods'))
            return
Example #33
0
    def _get_top_region(self, ctx):
        top_region_name = ''
        try:
            with ctx.session.begin():
                pods = core.query_resource(ctx,
                                           models.Pod, [], [])
                for pod in pods:
                    if pod['az_name'] == '' and pod['pod_name'] != '':
                        return pod['pod_name']
        except Exception as e:
            LOG.exception(_LE('Failed to get top region: %(exception)s '),
                          {'exception': e})

            return top_region_name

        return top_region_name
Example #34
0
def get_pod_by_az_tenant(context, az_name, tenant_id):
    pod_bindings = core.query_resource(context,
                                       models.PodBinding,
                                       [{'key': 'tenant_id',
                                         'comparator': 'eq',
                                         'value': tenant_id}],
                                       [])
    for pod_b in pod_bindings:
        pod = core.get_resource(context,
                                models.Pod,
                                pod_b['pod_id'])
        if az_name and pod['az_name'] == az_name:
            return pod, pod['pod_az_name']
        elif az_name == '' and pod['az_name'] != '':
            # if the az_name is not specified, a defult bottom
            # pod will be selected
            return pod, pod['pod_az_name']
        else:
            pass

    # TODO(joehuang): schedule one dynamically in the future
    if az_name != '':
        filters = [{'key': 'az_name', 'comparator': 'eq', 'value': az_name}]
    else:
        filters = None

    # if az_name is valid, select a pod under this az_name
    # if az_name is '', select the first valid bottom pod.
    # change to dynamic schedluing in the future
    pods = db_api.list_pods(context, filters=filters)
    for pod in pods:
        if pod['pod_name'] != '' and pod['az_name'] != '':
            try:
                with context.session.begin():
                    core.create_resource(
                        context, models.PodBinding,
                        {'id': uuidutils.generate_uuid(),
                         'tenant_id': tenant_id,
                         'pod_id': pod['pod_id'],
                         'is_binding': True})
                    return pod, pod['pod_az_name']
            except Exception as e:
                LOG.error(_LE('Fail to create pod binding: %(exception)s'),
                          {'exception': e})
                return None, None

    return None, None
Example #35
0
    def get_one(self):
        """Get all metadata associated with a volume."""
        context = t_context.extract_context_from_environ()

        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        try:
            s_ctx = hclient.get_res_routing_ref(context, self.volume_id,
                                                request.url, cons.ST_CINDER)
            if not s_ctx:
                return utils.format_cinder_error(500,
                                                 _('Fail to find resource'))
        except Exception as e:
            LOG.exception(
                _LE('Fail to get metadata for a volume:'
                    '%(volume_id)s'
                    '%(exception)s'), {
                        'volume_id': self.volume_id,
                        'exception': e
                    })
            return utils.format_cinder_error(500, _('Fail to get metadata'))

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                500, _('Bottom pod endpoint incorrect'))

        resp = hclient.forward_req(context, 'GET', b_headers, s_ctx['b_url'],
                                   request.body)

        b_body_ret = jsonutils.loads(resp.content)

        b_status = resp.status_code
        response.status = b_status
        if b_status == 200:
            if b_body_ret.get('metadata') is not None:
                b_metadata_ret = b_body_ret['metadata']
                vol_ret = hclient.convert_object(b_release,
                                                 t_release,
                                                 b_metadata_ret,
                                                 res_type=cons.RT_VOl_METADATA)
                return {'metadata': vol_ret}

        return b_body_ret
    def _allocate_network_async(self, context, instance, requested_networks,
                                macs, security_groups, is_vpn, dhcp_options):
        """Method used to allocate networks in the background.

        Broken out for testing.
        """
        LOG.debug("Allocating IP information in the background.",
                  instance=instance)
        retries = CONF.network_allocate_retries
        if retries < 0:
            LOG.warn(_("Treating negative config value (%(retries)s) for "
                       "'network_allocate_retries' as 0."),
                     {'retries': retries})
        attempts = retries > 1 and retries + 1 or 1
        retry_time = 1
        for attempt in range(1, attempts + 1):
            try:
                nwinfo = self.network_api.allocate_for_instance(
                    context, instance, vpn=is_vpn,
                    requested_networks=requested_networks,
                    macs=macs, security_groups=security_groups,
                    dhcp_options=dhcp_options)
                LOG.debug('Instance network_info: |%s|', nwinfo,
                          instance=instance)
                instance.system_metadata['network_allocated'] = 'True'
                # NOTE(JoshNang) do not save the instance here, as it can cause
                # races. The caller shares a reference to instance and waits
                # for this async greenthread to finish before calling
                # instance.save().
                return nwinfo
            except Exception:
                exc_info = sys.exc_info()
                log_info = {'attempt': attempt,
                            'attempts': attempts}
                if attempt == attempts:
                    LOG.exception(_LE('Instance failed network setup '
                                      'after %(attempts)d attempt(s)'),
                                  log_info)
                    raise exc_info[0], exc_info[1], exc_info[2]
                LOG.warn(_('Instance failed network setup '
                           '(attempt %(attempt)d of %(attempts)d)'),
                         log_info, instance=instance)
                time.sleep(retry_time)
                retry_time *= 2
                if retry_time > 30:
                    retry_time = 30
Example #37
0
    def get_all(self):
        """Get all non-deleted volume_types."""
        filters = {}
        context = t_context.extract_context_from_environ()
        if not context.is_admin:
            # Only admin has query access to all volume types
            filters['is_public'] = True
        try:
            list_result = db_api.volume_type_get_all(context,
                                                     list_result=True,
                                                     filters=filters)
        except Exception as e:
            LOG.exception(_LE('Fail to retrieve volume types: %(exception)s'),
                          {'exception': e})
            return utils.format_cinder_error(500, e)

        return {'volume_types': list_result}
Example #38
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_CREATE):
            return utils.format_api_error(
                403, _("Unauthorized to create resource routing"))

        if 'routing' not in kw:
            return utils.format_api_error(400, _("Request body not found"))

        routing = kw['routing']

        for field in ('top_id', 'bottom_id', 'pod_id', 'project_id',
                      'resource_type'):
            value = routing.get(field)
            if value is None or len(value.strip()) == 0:
                return utils.format_api_error(
                    400,
                    _("Field %(field)s can not be empty") % {'field': field})

        # the resource type should be properly provisioned.
        resource_type = routing.get('resource_type').strip()
        if not constants.is_valid_resource_type(resource_type):
            return utils.format_api_error(400,
                                          _('There is no such resource type'))

        try:
            top_id = routing.get('top_id').strip()
            bottom_id = routing.get('bottom_id').strip()
            pod_id = routing.get('pod_id').strip()
            project_id = routing.get('project_id').strip()

            routing = db_api.create_resource_mapping(context, top_id,
                                                     bottom_id, pod_id,
                                                     project_id, resource_type)
            if not routing:
                return utils.format_api_error(
                    409, _('Resource routing already exists'))
        except Exception as e:
            LOG.exception(
                _LE('Failed to create resource routing: '
                    '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to create resource routing'))

        return {'routing': routing}
Example #39
0
    def _get_res_routing_ref(self, context, _id, t_url):

        pod = self._get_pod_by_top_id(context, _id)

        if not pod:
            return None

        pod_name = pod['pod_name']

        s_ctx = hclient.get_pod_service_ctx(context,
                                            t_url,
                                            pod_name,
                                            s_type=cons.ST_CINDER)

        if s_ctx['b_url'] == '':
            LOG.error(_LE("bottom pod endpoint incorrect %s") % pod_name)

        return s_ctx
Example #40
0
    def put(self, _id, **kw):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_PUT):
            return utils.format_api_error(
                403, _('Unauthorized to update resource routing'))

        try:
            db_api.get_resource_routing(context, _id)
        except t_exc.ResourceNotFound:
            return utils.format_api_error(404, _('Resource routing not found'))

        if 'routing' not in kw:
            return utils.format_api_error(400, _('Request body not found'))

        update_dict = kw['routing']

        # values to be updated should not be empty
        for field in update_dict:
            value = update_dict.get(field)
            if value is None or len(value.strip()) == 0:
                return utils.format_api_error(
                    400,
                    _("Field %(field)s can not be empty") % {'field': field})

        # the resource type should be properly provisioned.
        if 'resource_type' in update_dict:
            if not constants.is_valid_resource_type(
                    update_dict['resource_type']):
                return utils.format_api_error(
                    400, _('There is no such resource type'))

        try:
            routing_updated = db_api.update_resource_routing(
                context, _id, update_dict)
            return {'routing': routing_updated}
        except Exception as e:
            LOG.exception(
                _LE('Failed to update resource routing: '
                    '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to update resource routing'))
Example #41
0
    def get_all(self, **kwargs):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_LIST):
            return utils.format_api_error(
                403, _('Unauthorized to to show all resource routings'))

        filters = self._get_filters(kwargs)
        filters = [{'key': key,
                    'comparator': 'eq',
                    'value': value} for key, value in filters.iteritems()]

        try:
            return {'routings': db_api.list_resource_routings(context,
                                                              filters)}
        except Exception as e:
            LOG.exception(_LE('Failed to show all resource routings: '
                              '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to show all resource routings'))
Example #42
0
    def _get_res_routing_ref(self, context, _id, t_url):

        pod = self._get_pod_by_top_id(context, _id)

        if not pod:
            return None

        pod_name = pod['pod_name']

        s_ctx = hclient.get_pod_service_ctx(
            context,
            t_url,
            pod_name,
            s_type=cons.ST_CINDER)

        if s_ctx['b_url'] == '':
            LOG.error(_LE("bottom pod endpoint incorrect %s") %
                      pod_name)

        return s_ctx
Example #43
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_DELETE):
            return utils.format_api_error(
                403, _('Unauthorized to delete the resource routing'))

        try:
            db_api.get_resource_routing(context, _id)
        except t_exc.ResourceNotFound:
            return utils.format_api_error(404, _('Resource routing not found'))
        try:
            db_api.delete_resource_routing(context, _id)
            pecan.response.status = 200
            return pecan.response
        except Exception as e:
            LOG.exception(
                _LE('Failed to delete the resource routing: '
                    '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to delete the resource routing'))
Example #44
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_DELETE):
            return utils.format_api_error(
                403, _('Unauthorized to delete the resource routing'))

        try:
            db_api.get_resource_routing(context, _id)
        except t_exc.ResourceNotFound:
            return utils.format_api_error(404,
                                          _('Resource routing not found'))
        try:
            db_api.delete_resource_routing(context, _id)
            pecan.response.status = 200
            return pecan.response
        except Exception as e:
            LOG.exception(_LE('Failed to delete the resource routing: '
                              '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to delete the resource routing'))
Example #45
0
    def get_one(self, _id):
        """Retrieves single volume type by id.

        :param _id: id of volume type to be retrieved
        :returns: retrieved volume type
        """
        context = t_context.extract_context_from_environ()
        try:
            result = db_api.volume_type_get(context, _id)
        except exceptions.VolumeTypeNotFound as e:
            return utils.format_cinder_error(404, e.message)
        except Exception as e:
            LOG.exception(
                _LE('Volume type not found: %(id)s,'
                    '%(exception)s'), {
                        'id': _id,
                        'exception': e
                    })
            return utils.format_cinder_error(
                404,
                _("Volume type %(id)s could not be found.") % {'id': _id})
        return {'volume_type': result}
Example #46
0
    def delete(self, key):
        """Delete the given metadata item from a volume."""
        context = t_context.extract_context_from_environ()

        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        try:
            s_ctx = hclient.get_res_routing_ref(context, self.volume_id,
                                                request.url, cons.ST_CINDER)
            if not s_ctx:
                return utils.format_cinder_error(404,
                                                 _('Fail to find resource'))
        except Exception as e:
            LOG.exception(
                _LE('Fail to delete metadata from a volume: '
                    '%(volume_id)s'
                    '%(exception)s'), {
                        'volume_id': self.volume_id,
                        'exception': e
                    })
            return utils.format_cinder_error(500, _('Fail to delete metadata'))

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                500, _('Bottom pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        resp = hclient.forward_req(context, 'DELETE', b_headers,
                                   s_ctx['b_url'], request.body)

        response.status = resp.status_code

        # don't remove the resource routing for delete is async. operation
        # remove the routing when query is executed but not found
        # No content in the resp actually
        return response
Example #47
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        if not t_context.is_admin_context(context):
            pecan.abort(400, _('Admin role required to delete pods'))
            return

        try:
            with context.session.begin():
                pod = core.get_resource(context, models.Pod, _id)
                if pod is not None:
                    ag_name = utils.get_ag_name(pod['pod_name'])
                    ag = az_ag.get_ag_by_name(context, ag_name)
                    if ag is not None:
                        az_ag.delete_ag(context, ag['id'])
                core.delete_resource(context, models.Pod, _id)
                pecan.response.status = 200
        except t_exc.ResourceNotFound:
            return Response(_('Pod not found'), 404)
        except Exception as e:
            LOG.error(_LE('Fail to delete pod: %(exception)s'),
                      {'exception': e})
            return Response(_('Fail to delete pod'), 500)
Example #48
0
def get_res_routing_ref(context, _id, t_url, s_type):
    """Get the service context according to resource routing.

    :param _id: the top id of resource
    :param t_url: request url
    :param s_type: service type
    :returns: service context
    """
    pod = utils.get_pod_by_top_id(context, _id)

    if not pod:
        return None

    pod_name = pod['pod_name']

    s_ctx = get_pod_service_ctx(context, t_url, pod_name,
                                s_type=s_type)

    if s_ctx['b_url'] == '':
        LOG.error(_LE("bottom pod endpoint incorrect %s") %
                  pod_name)

    return s_ctx
Example #49
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_PODS_DELETE):
            pecan.abort(401, _('Unauthorized to delete pods'))
            return

        try:
            with context.session.begin():
                core.delete_resource(context, models.Pod, _id)
                pecan.response.status = 200
                return {}
        except t_exc.ResourceNotFound:
            return Response(_('Pod not found'), 404)
        except Exception as e:
            LOG.exception(
                _LE('Failed to delete pod: %(pod_id)s,'
                    '%(exception)s'), {
                        'pod_id': _id,
                        'exception': e
                    })

            return Response(_('Failed to delete pod'), 500)
Example #50
0
    def get_all(self, **kwargs):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_LIST):
            return utils.format_api_error(
                403, _('Unauthorized to show all resource routings'))

        filters = self._get_filters(kwargs)
        filters = [{
            'key': key,
            'comparator': 'eq',
            'value': value
        } for key, value in six.iteritems(filters)]

        try:
            return {
                'routings': db_api.list_resource_routings(context, filters)
            }
        except Exception as e:
            LOG.exception(
                _LE('Failed to show all resource routings: '
                    '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to show all resource routings'))
Example #51
0
 def __call__(self, *args, **kwargs):
     stacktrace = "".join(traceback.format_stack())
     LOG = logging.getLogger('nova.compute')
     LOG.error(_LE('No db access allowed in nova-compute: %s'),
               stacktrace)
     raise nova_exception.DBNotAllowed('nova-compute')
Example #52
0
        def handle_args(*args, **kwargs):
            if IN_TEST:
                # NOTE(zhiyuan) job mechanism will cause some unpredictable
                # result in unit test so we would like to bypass it. However
                # we have problem mocking a decorator which decorates member
                # functions, that's why we use this label, not an elegant
                # way though.
                func(*args, **kwargs)
                return
            ctx = args[1]
            payload = kwargs['payload']

            resource_id = payload[job_type]
            db_api.new_job(ctx, job_type, resource_id)
            start_time = datetime.datetime.now()

            while True:
                current_time = datetime.datetime.now()
                delta = current_time - start_time
                if delta.seconds >= CONF.worker_handle_timeout:
                    # quit when this handle is running for a long time
                    break
                time_new = db_api.get_latest_timestamp(ctx, constants.JS_New,
                                                       job_type, resource_id)
                time_success = db_api.get_latest_timestamp(
                    ctx, constants.JS_Success, job_type, resource_id)
                if time_success and time_success >= time_new:
                    break
                job = db_api.register_job(ctx, job_type, resource_id)
                if not job:
                    # fail to obtain the lock, let other worker handle the job
                    running_job = db_api.get_running_job(ctx, job_type,
                                                         resource_id)
                    if not running_job:
                        # there are two reasons that running_job is None. one
                        # is that the running job has just been finished, the
                        # other is that all workers fail to register the job
                        # due to deadlock exception. so we sleep and try again
                        eventlet.sleep(CONF.worker_sleep_time)
                        continue
                    job_time = running_job['timestamp']
                    current_time = datetime.datetime.now()
                    delta = current_time - job_time
                    if delta.seconds > CONF.job_run_expire:
                        # previous running job expires, we set its status to
                        # fail and try again to obtain the lock
                        db_api.finish_job(ctx, running_job['id'], False,
                                          time_new)
                        LOG.warning(_LW('Job %(job)s of type %(job_type)s for '
                                        'resource %(resource)s expires, set '
                                        'its state to Fail'),
                                    {'job': running_job['id'],
                                     'job_type': job_type,
                                     'resource': resource_id})
                        eventlet.sleep(CONF.worker_sleep_time)
                        continue
                    else:
                        # previous running job is still valid, we just leave
                        # the job to the worker who holds the lock
                        break
                # successfully obtain the lock, start to execute handler
                try:
                    func(*args, **kwargs)
                except Exception:
                    db_api.finish_job(ctx, job['id'], False, time_new)
                    LOG.error(_LE('Job %(job)s of type %(job_type)s for '
                                  'resource %(resource)s fails'),
                              {'job': job['id'],
                               'job_type': job_type,
                               'resource': resource_id})
                    break
                db_api.finish_job(ctx, job['id'], True, time_new)
                eventlet.sleep(CONF.worker_sleep_time)
Example #53
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if 'volume' not in kw:
            pecan.abort(400, _('Volume not found in request body'))
            return

        if 'availability_zone' not in kw['volume']:
            pecan.abort(400, _('Availability zone not set in request'))
            return

        pod, pod_az = az_ag.get_pod_by_az_tenant(
            context,
            az_name=kw['volume']['availability_zone'],
            tenant_id=self.tenant_id)
        if not pod:
            pecan.abort(500, _('Pod not configured or scheduling failure'))
            LOG.error(_LE("Pod not configured or scheduling failure"))
            return

        t_pod = db_api.get_top_pod(context)
        if not t_pod:
            pecan.abort(500, _('Top Pod not configured'))
            LOG.error(_LE("Top Po not configured"))
            return

        # TODO(joehuang): get release from pod configuration,
        # to convert the content
        # b_release = pod['release']
        # t_release = t_pod['release']
        t_release = 'Mitaka'
        b_release = 'Mitaka'

        s_ctx = hclient.get_pod_service_ctx(
            context,
            request.url,
            pod['pod_name'],
            s_type=cons.ST_CINDER)

        if s_ctx['b_url'] == '':
            pecan.abort(500, _('bottom pod endpoint incorrect'))
            LOG.error(_LE("bottom pod endpoint incorrect %s") %
                      pod['pod_name'])
            return

        b_headers = self._convert_header(t_release,
                                         b_release,
                                         request.headers)

        t_vol = kw['volume']

        # add or remove key-value in the request for diff. version
        b_vol_req = self._convert_object(t_release, b_release, t_vol,
                                         res_type=cons.RT_VOLUME)

        # convert az to the configured one
        # remove the AZ parameter to bottom request for default one
        b_vol_req['availability_zone'] = pod['pod_az_name']
        if b_vol_req['availability_zone'] == '':
            b_vol_req.pop("availability_zone", None)

        b_body = jsonutils.dumps({'volume': b_vol_req})

        resp = hclient.forward_req(
            context,
            'POST',
            b_headers,
            s_ctx['b_url'],
            b_body)
        b_status = resp.status_code
        b_ret_body = jsonutils.loads(resp.content)

        # build routing and convert response from the bottom pod
        # for different version.
        response.status = b_status
        if b_status == 202:
            if b_ret_body.get('volume') is not None:
                b_vol_ret = b_ret_body['volume']

                try:
                    with context.session.begin():
                        core.create_resource(
                            context, models.ResourceRouting,
                            {'top_id': b_vol_ret['id'],
                             'bottom_id': b_vol_ret['id'],
                             'pod_id': pod['pod_id'],
                             'project_id': self.tenant_id,
                             'resource_type': cons.RT_VOLUME})
                except Exception as e:
                    LOG.error(_LE('Fail to create volume: %(exception)s'),
                              {'exception': e})
                    return Response(_('Failed to create volume'), 500)

                ret_vol = self._convert_object(b_release, t_release,
                                               b_vol_ret,
                                               res_type=cons.RT_VOLUME)

                ret_vol['availability_zone'] = pod['az_name']

                return {'volume': ret_vol}

        return {'error': b_ret_body}
Example #54
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_CREATE):
            return utils.format_api_error(
                403, _("Unauthorized to create resource routing"))

        if 'routing' not in kw:
            return utils.format_api_error(
                400, _("Request body not found"))

        routing = kw['routing']

        for field in ('top_id', 'bottom_id', 'pod_id',
                      'project_id', 'resource_type'):
            value = routing.get(field)
            if value is None or len(value.strip()) == 0:
                return utils.format_api_error(
                    400, _("Field %(field)s can not be empty") % {
                        'field': field})

        # verify the integrity: the pod_id and the project_id should be bound
        pod_id = routing.get('pod_id').strip()
        project_id = routing.get('project_id').strip()
        bindings = db_api.list_pod_bindings(context,
                                            [{'key': 'pod_id',
                                              'comparator': 'eq',
                                              'value': pod_id
                                              },
                                             {'key': 'tenant_id',
                                              'comparator': 'eq',
                                              'value': project_id}
                                             ], [])
        if len(bindings) == 0:
            return utils.format_api_error(
                400, _('The pod_id and project_id have not been bound'))

        # the resource type should be properly provisioned.
        resource_type = routing.get('resource_type').strip()
        if not constants.is_valid_resource_type(resource_type):
            return utils.format_api_error(
                400, _('There is no such resource type'))

        try:
            top_id = routing.get('top_id').strip()
            bottom_id = routing.get('bottom_id').strip()

            routing = db_api.create_resource_mapping(context, top_id,
                                                     bottom_id, pod_id,
                                                     project_id,
                                                     resource_type)
            if not routing:
                return utils.format_api_error(
                    409, _('Resource routing already exists'))
        except Exception as e:
            LOG.exception(_LE('Failed to create resource routing: '
                              '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to create resource routing'))

        return {'routing': routing}
Example #55
0
    def put(self, _id, **kw):
        context = t_context.extract_context_from_environ()

        if not policy.enforce(context, policy.ADMIN_API_ROUTINGS_PUT):
            return utils.format_api_error(
                403, _('Unauthorized to update resource routing'))

        try:
            routing = db_api.get_resource_routing(context, _id)
        except t_exc.ResourceNotFound:
            return utils.format_api_error(404,
                                          _('Resource routing not found'))

        if 'routing' not in kw:
            return utils.format_api_error(
                400, _('Request body not found'))

        update_dict = kw['routing']

        # values to be updated should not be empty
        for field in update_dict:
            value = update_dict.get(field)
            if value is None or len(value.strip()) == 0:
                return utils.format_api_error(
                    400, _("Field %(field)s can not be empty") % {
                        'field': field})

        # the resource type should be properly provisioned.
        if 'resource_type' in update_dict:
            if not constants.is_valid_resource_type(
                    update_dict['resource_type']):
                return utils.format_api_error(
                    400, _('There is no such resource type'))

        # verify the integrity: the pod_id and project_id should be bound
        if 'pod_id' in update_dict or 'project_id' in update_dict:
            if 'pod_id' in update_dict:
                pod_id = update_dict['pod_id']
            else:
                pod_id = routing['pod_id']

            if 'project_id' in update_dict:
                project_id = update_dict['project_id']
            else:
                project_id = routing['project_id']

            bindings = db_api.list_pod_bindings(context,
                                                [{'key': 'pod_id',
                                                  'comparator': 'eq',
                                                  'value': pod_id
                                                  },
                                                 {'key': 'tenant_id',
                                                  'comparator': 'eq',
                                                  'value': project_id}
                                                 ], [])
            if len(bindings) == 0:
                return utils.format_api_error(
                    400, _('The pod_id and project_id have not been '
                           'bound'))

        try:
            routing_updated = db_api.update_resource_routing(
                context, _id, update_dict)
            return {'routing': routing_updated}
        except Exception as e:
            LOG.exception(_LE('Failed to update resource routing: '
                              '%(exception)s '), {'exception': e})
            return utils.format_api_error(
                500, _('Failed to update resource routing'))