def __init__(self, user_id, project_id, is_admin=None, read_deleted="no", roles=None, remote_address=None, timestamp=None, request_id=None, auth_token=None, overwrite=True, quota_class=None, user_name=None, project_name=None, service_catalog=None, instance_lock_checked=False, user_auth_plugin=None, **kwargs): """:param read_deleted: 'no' indicates deleted records are hidden, 'yes' indicates deleted records are visible, 'only' indicates that *only* deleted records are visible. :param overwrite: Set to False to ensure that the greenthread local copy of the index is not overwritten. :param user_auth_plugin: The auth plugin for the current request's authentication data. :param kwargs: Extra arguments that might be present, but we ignore because they possibly came in from older rpc messages. """ if kwargs: LOG.warning(_LW('Arguments dropped when creating context: %s') % str(kwargs)) self.user_id = user_id self.project_id = project_id self.roles = roles or [] self.read_deleted = read_deleted self.remote_address = remote_address if not timestamp: timestamp = timeutils.utcnow() if isinstance(timestamp, six.string_types): timestamp = timeutils.parse_strtime(timestamp) self.timestamp = timestamp if not request_id: request_id = context.generate_request_id() self.request_id = request_id self.auth_token = auth_token if service_catalog: # Only include required parts of service_catalog self.service_catalog = [s for s in service_catalog if s.get('type') in ('volume', 'volumev2', 'key-manager')] else: # if list is empty or none self.service_catalog = [] self.instance_lock_checked = instance_lock_checked # NOTE(markmc): this attribute is currently only used by the # rs_limits turnstile pre-processor. # See https://lists.launchpad.net/openstack/msg12200.html self.quota_class = quota_class self.user_name = user_name self.project_name = project_name self.is_admin = is_admin self.user_auth_plugin = user_auth_plugin if self.is_admin is None: self.is_admin = policy.check_is_admin(self) if overwrite or not hasattr(local.store, 'context'): self.update_store()
def __init__(self, user_id, project_id, is_admin=None, read_deleted="no", roles=None, remote_address=None, timestamp=None, request_id=None, auth_token=None, overwrite=True, quota_class=None, service_catalog=None, **kwargs): """Initialize RequestContext. :param read_deleted: 'no' indicates deleted records are hidden, 'yes' indicates deleted records are visible, 'only' indicates that *only* deleted records are visible. :param overwrite: Set to False to ensure that the greenthread local copy of the index is not overwritten. :param kwargs: Extra arguments that might be present, but we ignore because they possibly came in from older rpc messages. """ if kwargs: LOG.warn(_LW('Arguments dropped when creating context: %s'), str(kwargs)) self.user_id = user_id self.project_id = project_id self.roles = roles or [] self.is_admin = is_admin if self.is_admin is None: self.is_admin = policy.check_is_admin(self.roles) elif self.is_admin and 'admin' not in self.roles: self.roles.append('admin') self.read_deleted = read_deleted self.remote_address = remote_address if not timestamp: timestamp = timeutils.utcnow() if isinstance(timestamp, six.string_types): timestamp = timeutils.parse_strtime(timestamp) self.timestamp = timestamp if service_catalog: self.service_catalog = [ s for s in service_catalog if s.get('type') in ('compute', 'volume') ] else: self.service_catalog = [] if not request_id: request_id = common_context.generate_request_id() self.request_id = request_id self.auth_token = auth_token self.quota_class = quota_class if overwrite or not common_context.get_current(): self.update_store()
def __call__(self, req): req_id = context.generate_request_id() req.environ[ENV_REQUEST_ID] = req_id response = req.get_response(self.application) if HTTP_RESP_HEADER_REQUEST_ID not in response.headers: response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id) return response
def notify(action, alarm_id, alarm_name, previous, current, reason, reason_data, headers=None): headers = headers or {} if not headers.get('x-openstack-request-id'): headers['x-openstack-request-id'] = context.generate_request_id() LOG.info( _("Notifying alarm %(alarm_name)s %(alarm_id)s from " "%(previous)s to %(current)s with action %(action)s because " "%(reason)s. request-id: %(request_id)s ") % ({ 'alarm_name': alarm_name, 'alarm_id': alarm_id, 'previous': previous, 'current': current, 'action': action, 'reason': reason, 'request_id': headers['x-openstack-request-id'] })) body = { 'alarm_name': alarm_name, 'alarm_id': alarm_id, 'previous': previous, 'current': current, 'reason': reason, 'reason_data': reason_data } headers['content-type'] = 'application/json' kwargs = {'data': jsonutils.dumps(body), 'headers': headers} if action.scheme == 'https': default_verify = int(cfg.CONF.alarm.rest_notifier_ssl_verify) options = urlparse.parse_qs(action.query) verify = bool( int( options.get('ceilometer-alarm-ssl-verify', [default_verify])[-1])) kwargs['verify'] = verify cert = cfg.CONF.alarm.rest_notifier_certificate_file key = cfg.CONF.alarm.rest_notifier_certificate_key if cert: kwargs['cert'] = (cert, key) if key else cert # FIXME(rhonjo): Retries are automatically done by urllib3 in requests # library. However, there's no interval between retries in urllib3 # implementation. It will be better to put some interval between # retries (future work). max_retries = cfg.CONF.alarm.rest_notifier_max_retries session = requests.Session() session.mount(action.geturl(), requests.adapters.HTTPAdapter(max_retries=max_retries)) eventlet.spawn_n(session.post, action.geturl(), **kwargs)
def _get_nova_client(self): global_id = common_context.generate_request_id() return nova_client.Client( api_versions.APIVersion(NOVA_API_VERSION), session=self.session, region_name=cfg.CONF.nova.region_name, endpoint_type=cfg.CONF.nova.endpoint_type, extensions=self.extensions, global_request_id=global_id)
def _get_nova_client(self): global_id = common_context.generate_request_id() return nova_client.Client(api_versions.APIVersion(NOVA_API_VERSION), session=self.session, region_name=cfg.CONF.nova.region_name, endpoint_type=cfg.CONF.nova.endpoint_type, extensions=self.extensions, connect_retries=cfg.CONF.http_retries, global_request_id=global_id)
def __init__(self, user_id, project_id, is_admin=None, read_deleted="no", roles=None, remote_address=None, timestamp=None, request_id=None, auth_token=None, overwrite=True, quota_class=None, service_catalog=None, **kwargs): """Initialize RequestContext. :param read_deleted: 'no' indicates deleted records are hidden, 'yes' indicates deleted records are visible, 'only' indicates that *only* deleted records are visible. :param overwrite: Set to False to ensure that the greenthread local copy of the index is not overwritten. :param kwargs: Extra arguments that might be present, but we ignore because they possibly came in from older rpc messages. """ user = kwargs.pop('user', None) tenant = kwargs.pop('tenant', None) if kwargs: LOG.warn(_LW('Arguments dropped when creating context: %s'), str(kwargs)) self.user_id = user_id or user self.project_id = project_id or tenant self.roles = roles or [] self.is_admin = is_admin if self.is_admin is None: self.is_admin = policy.check_is_admin(self.roles) elif self.is_admin and 'admin' not in self.roles: self.roles.append('admin') self.read_deleted = read_deleted self.remote_address = remote_address if not timestamp: timestamp = timeutils.utcnow() if isinstance(timestamp, six.string_types): timestamp = timeutils.parse_strtime(timestamp) self.timestamp = timestamp if service_catalog: self.service_catalog = [s for s in service_catalog if s.get('type') in ('compute', 'volume')] else: self.service_catalog = [] if not request_id: request_id = common_context.generate_request_id() self.request_id = request_id self.auth_token = auth_token self.quota_class = quota_class if overwrite or not common_context.get_current(): self.update_store()
def __call__(self, req): self.set_global_req_id(req) req_id = context.generate_request_id() req.environ[ENV_REQUEST_ID] = req_id response = req.get_response(self.application) return_headers = [HTTP_RESP_HEADER_REQUEST_ID] return_headers.extend(self.compat_headers) for header in return_headers: if header not in response.headers: response.headers.add(header, req_id) return response
def _execute(self, invoke): class Fake(object): pass fake_ec2_request = Fake() fake_ec2_request.invoke = invoke fake_wsgi_request = Fake() fake_wsgi_request.environ = { 'ec2api.context': mock.Mock( request_id=context.generate_request_id()), 'ec2.request': fake_ec2_request, } return self.executor(fake_wsgi_request)
def test_generate_request_id(self): @webob.dec.wsgify def application(req): return req.environ[ENV_REQUEST_ID] app = compute_req_id.ComputeReqIdMiddleware(application) req = webob.Request.blank('/test') req_id = context.generate_request_id() req.environ[ENV_REQUEST_ID] = req_id res = req.get_response(app) res_id = res.headers.get(compute_req_id.HTTP_RESP_HEADER_REQUEST_ID) self.assertThat(res_id, matchers.StartsWith('req-')) self.assertEqual(res_id.encode('utf-8'), res.body)
def test_generate_request_id(self): @webob.dec.wsgify def application(req): return req.environ[compute_req_id.ENV_REQUEST_ID] app = compute_req_id.ComputeReqIdMiddleware(application) req = webob.Request.blank('/test') req_id = context.generate_request_id() req.environ[compute_req_id.ENV_REQUEST_ID] = req_id res = req.get_response(app) res_id = res.headers.get(compute_req_id.HTTP_RESP_HEADER_REQUEST_ID) self.assertThat(res_id, matchers.StartsWith('req-')) self.assertEqual(res_id, res.body)
def setUp(self): super(ApiInitTestCase, self).setUp() self.controller = self.mock( 'ec2api.api.cloud.VpcCloudController').return_value self.fake_context = mock.NonCallableMock( request_id=context.generate_request_id()) ec2_request = apirequest.APIRequest('FakeAction', 'fake_v1', {'Param': 'fake_param'}) self.environ = {'REQUEST_METHOD': 'FAKE', 'ec2.request': ec2_request, 'ec2api.context': self.fake_context} self.request = wsgi.Request(self.environ) self.application = api.Executor()
def setUp(self): super(ApiInitTestCase, self).setUp() self.controller = self.mock( 'ec2api.api.cloud.VpcCloudController').return_value self.fake_context = mock.NonCallableMock( request_id=context.generate_request_id()) ec2_request = apirequest.APIRequest('FakeAction', 'fake_v1', {'Param': 'fake_param'}) self.environ = { 'REQUEST_METHOD': 'FAKE', 'ec2.request': ec2_request, 'ec2api.context': self.fake_context } self.request = wsgi.Request(self.environ) self.application = api.Executor()
def __call__(self, req): client_request_id = None if self.env_client_request_id in req.headers: client_request_id = req.headers[self.resp_header_client_request_id] req.environ[self.env_client_request_id] = client_request_id if self.resp_header_request_id in req.headers: req_id = req.headers[self.resp_header_request_id] else: req_id = context.generate_request_id() req.environ[self.env_request_id] = req_id response = req.get_response(self.application) if client_request_id: response.headers.add(self.resp_header_client_request_id, client_request_id) if self.resp_header_request_id not in response.headers: response.headers.add(self.resp_header_request_id, req_id) return response
def notify(self, action, alarm_id, alarm_name, severity, previous, current, reason, reason_data, headers=None): headers = headers or {} if not headers.get('x-openstack-request-id'): headers['x-openstack-request-id'] = context.generate_request_id() LOG.info(_( "Notifying alarm %(alarm_name)s %(alarm_id)s with severity" " %(severity)s from %(previous)s to %(current)s with action " "%(action)s because %(reason)s. request-id: %(request_id)s ") % ({'alarm_name': alarm_name, 'alarm_id': alarm_id, 'severity': severity, 'previous': previous, 'current': current, 'action': action, 'reason': reason, 'request_id': headers['x-openstack-request-id']})) body = {'alarm_name': alarm_name, 'alarm_id': alarm_id, 'severity': severity, 'previous': previous, 'current': current, 'reason': reason, 'reason_data': reason_data} headers['content-type'] = 'application/json' kwargs = {'data': jsonutils.dumps(body), 'headers': headers} if action.scheme == 'https': default_verify = int(self.conf.rest_notifier_ssl_verify) options = urlparse.parse_qs(action.query) verify = bool(int(options.get('aodh-alarm-ssl-verify', [default_verify])[-1])) kwargs['verify'] = verify cert = self.conf.rest_notifier_certificate_file key = self.conf.rest_notifier_certificate_key if cert: kwargs['cert'] = (cert, key) if key else cert # FIXME(rhonjo): Retries are automatically done by urllib3 in requests # library. However, there's no interval between retries in urllib3 # implementation. It will be better to put some interval between # retries (future work). max_retries = self.conf.rest_notifier_max_retries session = requests.Session() session.mount(action.geturl(), requests.adapters.HTTPAdapter(max_retries=max_retries)) session.post(action.geturl(), **kwargs)
def __call__(self, req): """Generate a WSGI response based on the exception passed to ctor.""" code = ec2api.api.exception_to_ec2code(self.wrapped_exc) status = self.wrapped_exc.status_int message = self.wrapped_exc.explanation if status == 501: message = "The requested function is not supported" if 'AWSAccessKeyId' not in req.params: raise webob.exc.HTTPBadRequest() user_id, _sep, project_id = req.params['AWSAccessKeyId'].partition(':') project_id = project_id or user_id remote_address = getattr(req, 'remote_address', '127.0.0.1') if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) resp = ec2_error_response(common_context.generate_request_id(), code, message=message, status=status) return resp
def __attach_req_id_to_resp(self, req, resp): req_id = context.generate_request_id() req.env['request-id'] = req_id if 'x-request-id' not in resp._headers: resp._headers['x-request-id'] = req_id
def context(self): self._context.request_id = o_context.generate_request_id() return self._context
def test_generate_request_id_unique(self): id1 = context.generate_request_id() id2 = context.generate_request_id() self.assertNotEqual(id1, id2)
def test_generate_request_id(self): id = context.generate_request_id() self.assertEqual("req-", id[:4])
def __call__(self, req): # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() request_id = common_context.generate_request_id() signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers: auth_params = {} else: # Make a copy of args for authentication and signature verification auth_params = dict(req.params) # Not part of authentication args auth_params.pop('Signature', None) cred_dict = { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': auth_params, 'headers': req.headers, 'body_hash': body_hash } if "ec2" in CONF.keystone_ec2_url: creds = {'ec2Credentials': cred_dict} else: creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}} creds_json = jsonutils.dumps(creds) headers = {'Content-Type': 'application/json'} verify = not CONF.keystone_ec2_insecure if verify and CONF.ssl.ca_file: verify = CONF.ssl.ca_file cert = None if CONF.ssl.cert_file and CONF.ssl.key_file: cert = (CONF.ssl.cert_file, CONF.ssl.key_file) elif CONF.ssl.cert_file: cert = CONF.ssl.cert_file response = requests.request('POST', CONF.keystone_ec2_url, data=creds_json, headers=headers, verify=verify, cert=cert) status_code = response.status_code if status_code != 200: msg = response.reason return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) result = response.json() try: token_id = result['access']['token']['id'] user_id = result['access']['user']['id'] project_id = result['access']['token']['tenant']['id'] user_name = result['access']['user'].get('name') project_name = result['access']['token']['tenant'].get('name') roles = [ role['name'] for role in result['access']['user']['roles'] ] except (AttributeError, KeyError) as e: LOG.error(_LE("Keystone failure: %s"), e) msg = _("Failure parsing response from keystone: %s") % e return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) catalog = result['access']['serviceCatalog'] ctxt = context.RequestContext(user_id, project_id, user_name=user_name, project_name=project_name, roles=roles, auth_token=token_id, remote_address=remote_address, service_catalog=catalog) req.environ['nova.context'] = ctxt return self.application
def context(self): # generate a new request-id on each call to make server side tracking # of RPC calls easier. self._context.request_id = common_context.generate_request_id() return self._context
def __call__(self, req): request_id = common_context.generate_request_id() # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers: params = {} else: # Make a copy of args for authentication and signature verification params = dict(req.params) # Not part of authentication args params.pop('Signature', None) cred_dict = { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': params, # python3 takes only keys for json from headers object 'headers': {k: req.headers[k] for k in req.headers}, 'body_hash': body_hash } token_url = CONF.keystone_ec2_tokens_url if "ec2" in token_url: creds = {'ec2Credentials': cred_dict} else: creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}} creds_json = jsonutils.dumps(creds) headers = {'Content-Type': 'application/json'} params = {'data': creds_json, 'headers': headers} clients.update_request_params_with_ssl(params) response = requests.request('POST', token_url, **params) status_code = response.status_code if status_code != 200: msg = response.reason return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) try: auth_ref = keystone_access.AccessInfo.factory(resp=response, body=response.json()) except (NotImplementedError, KeyError): LOG.exception("Keystone failure") msg = _("Failure communicating with keystone") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) auth = keystone_identity_access.AccessInfoPlugin(auth_ref) params = {'auth': auth} clients.update_request_params_with_ssl(params) session = keystone_session.Session(**params) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) ctxt = context.RequestContext(auth_ref.user_id, auth_ref.project_id, request_id=request_id, user_name=auth_ref.username, project_name=auth_ref.project_name, remote_address=remote_address, session=session, api_version=req.params.get('Version')) req.environ['ec2api.context'] = ctxt return self.application
def setUp(self): super(EC2RequesterTestCase, self).setUp() self.controller = self.mock( 'ec2api.api.cloud.VpcCloudController').return_value self.fake_context = mock.NonCallableMock( request_id=context.generate_request_id())
def __call__(self, req): # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() request_id = common_context.generate_request_id() signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers: auth_params = {} else: # Make a copy of args for authentication and signature verification auth_params = dict(req.params) # Not part of authentication args auth_params.pop('Signature', None) cred_dict = { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': auth_params, 'headers': req.headers, 'body_hash': body_hash } if "ec2" in CONF.keystone_ec2_url: creds = {'ec2Credentials': cred_dict} else: creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}} creds_json = jsonutils.dumps(creds) headers = {'Content-Type': 'application/json'} verify = not CONF.keystone_ec2_insecure if verify and CONF.ssl.ca_file: verify = CONF.ssl.ca_file cert = None if CONF.ssl.cert_file and CONF.ssl.key_file: cert = (CONF.ssl.cert_file, CONF.ssl.key_file) elif CONF.ssl.cert_file: cert = CONF.ssl.cert_file response = requests.request('POST', CONF.keystone_ec2_url, data=creds_json, headers=headers, verify=verify, cert=cert) status_code = response.status_code if status_code != 200: msg = response.reason return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) result = response.json() try: token_id = result['access']['token']['id'] user_id = result['access']['user']['id'] project_id = result['access']['token']['tenant']['id'] user_name = result['access']['user'].get('name') project_name = result['access']['token']['tenant'].get('name') roles = [role['name'] for role in result['access']['user']['roles']] except (AttributeError, KeyError) as e: LOG.error(_LE("Keystone failure: %s"), e) msg = _("Failure parsing response from keystone: %s") % e return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) catalog = result['access']['serviceCatalog'] ctxt = context.RequestContext(user_id, project_id, user_name=user_name, project_name=project_name, roles=roles, auth_token=token_id, remote_address=remote_address, service_catalog=catalog) req.environ['nova.context'] = ctxt return self.application
def __call__(self, req): # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() request_id = common_context.generate_request_id() signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if "X-Amz-Signature" in req.params or "Authorization" in req.headers: auth_params = {} else: # Make a copy of args for authentication and signature verification auth_params = dict(req.params) # Not part of authentication args auth_params.pop("Signature", None) cred_dict = { "access": access, "signature": signature, "host": req.host, "verb": req.method, "path": req.path, "params": auth_params, "headers": req.headers, "body_hash": body_hash, } if "ec2" in CONF.keystone_ec2_url: creds = {"ec2Credentials": cred_dict} else: creds = {"auth": {"OS-KSEC2:ec2Credentials": cred_dict}} creds_json = jsonutils.dumps(creds) headers = {"Content-Type": "application/json"} verify = not CONF.keystone_ec2_insecure if verify and CONF.ssl.ca_file: verify = CONF.ssl.ca_file cert = None if CONF.ssl.cert_file and CONF.ssl.key_file: cert = (CONF.ssl.cert_file, CONF.ssl.key_file) elif CONF.ssl.cert_file: cert = CONF.ssl.cert_file response = requests.request( "POST", CONF.keystone_ec2_url, data=creds_json, headers=headers, verify=verify, cert=cert ) status_code = response.status_code if status_code != 200: msg = response.reason return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) result = response.json() try: token_id = result["access"]["token"]["id"] user_id = result["access"]["user"]["id"] project_id = result["access"]["token"]["tenant"]["id"] user_name = result["access"]["user"].get("name") project_name = result["access"]["token"]["tenant"].get("name") roles = [role["name"] for role in result["access"]["user"]["roles"]] except (AttributeError, KeyError) as e: LOG.error(_LE("Keystone failure: %s"), e) msg = _("Failure parsing response from keystone: %s") % e return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get("X-Forwarded-For", remote_address) catalog = result["access"]["serviceCatalog"] ctxt = context.RequestContext( user_id, project_id, user_name=user_name, project_name=project_name, roles=roles, auth_token=token_id, remote_address=remote_address, service_catalog=catalog, ) req.environ["nova.context"] = ctxt return self.application
def __call__(self, req): """ 参数req: { 'environ': { 'SCRIPT_NAME': '/v2', 'webob.adhoc_attrs': { 'response': <Response at 0x74efa10 200 OK> }, 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/0d6ef9bd028641a8ae239c9c1b1f088f/cloudos-servers/detail', 'SERVER_PROTOCOL': 'HTTP/1.0', 'QUERY_STRING': 'all_tenants=True', 'HTTP_X_AUTH_TOKEN': '42ab4a87008648b5b10e40690aff8fe3', 'HTTP_USER_AGENT': 'python-novaclient', 'HTTP_CONNECTION': 'keep-alive', 'REMOTE_PORT': '48695', 'SERVER_NAME': '192.168.65.18', 'REMOTE_ADDR': '192.168.65.18', 'eventlet.input': <eventlet.wsgi.Input object at 0x7114350>, 'wsgi.url_scheme': 'http', 'SERVER_PORT': '8774', 'wsgi.input': <eventlet.wsgi.Input object at 0x7114350>, 'HTTP_HOST': '192.168.65.18:8774', 'HTTP_X_AUTH_PROJECT_ID': 'service', 'wsgi.multithread': True, 'eventlet.posthooks': [], 'HTTP_ACCEPT': 'application/json', 'wsgi.version': (1, 0), 'RAW_PATH_INFO': '/v2/0d6ef9bd028641a8ae239c9c1b1f088f/cloudos-servers/detail', 'GATEWAY_INTERFACE': 'CGI/1.1', 'wsgi.run_once': False, 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7fd45b2bc1e0>, 'wsgi.multiprocess': False, 'CONTENT_TYPE': 'text/plain', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'nova.best_content_type': 'application/json' } } """ ### def generate_request_id(): ### return b'req-' + str(uuid.uuid4()).encode('ascii') req_id = context.generate_request_id() req.environ[ENV_REQUEST_ID] = req_id ### get_response = Request.send ### self.application = <nova.api.openstack.FaultWrapper object at 0x7096250> response = req.get_response(self.application) if HTTP_RESP_HEADER_REQUEST_ID not in response.headers: response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id) """ response示例: 200 OK Content-Type: application/json Content-Length: 15282 x-compute-request-id: req-b6e5f0cb-e354-4f33-8ced-f85f83ab8372 """ return response