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}
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}
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}
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)
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)
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
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
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
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)
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
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
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})
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
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'))
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)
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
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
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)
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()
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
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()}
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
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})
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
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
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
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
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
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}
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}
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
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'))
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'))
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
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'))
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'))
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}
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
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)
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
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)
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'))
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')
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)
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}
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}
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'))