--- /dev/null
+# Copyright 2011 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Base class(es) for WSGI Middleware."""
+
+import webob.dec
+
+
+class Middleware(object):
+ """Base WSGI middleware wrapper.
+
+ These classes require an application to be initialized that will be called
+ next. By default the middleware will simply call its wrapped app, or you
+ can override __call__ to customize its behavior.
+ """
+
+ @classmethod
+ def factory(cls, global_conf, **local_conf):
+ """Factory method for paste.deploy."""
+ return cls
+
+ def __init__(self, application):
+ self.application = application
+
+ def process_request(self, req):
+ """Called on each request.
+
+ If this returns None, the next application down the stack will be
+ executed. If it returns a response then that response will be returned
+ and execution will stop here.
+ """
+ return None
+
+ def process_response(self, response):
+ """Do whatever you'd like to the response."""
+ return response
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ response = self.process_request(req)
+ if response:
+ return response
+ response = req.get_response(self.application)
+ return self.process_response(response)
--- /dev/null
+# Copyright (c) 2013 NEC Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Middleware that ensures request ID.
+
+It ensures to assign request ID for each API request and set it to
+request environment. The request ID is also added to API response.
+"""
+
+from cinder.openstack.common import context
+from cinder.openstack.common.middleware import base
+
+
+ENV_REQUEST_ID = 'openstack.request_id'
+HTTP_RESP_HEADER_REQUEST_ID = 'x-openstack-request-id'
+
+
+class RequestIdMiddleware(base.Middleware):
+
+ def process_request(self, req):
+ self.req_id = context.generate_request_id()
+ req.environ[ENV_REQUEST_ID] = self.req_id
+
+ def process_response(self, response):
+ response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, self.req_id)
+ return response
--- /dev/null
+# Copyright 2014 Rackspace Hosting
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+Utilities for linking request ID's across service calls.
+"""
+
+import logging
+
+from openstack.common.gettextutils import _ # noqa
+
+
+LOG = logging.getLogger(__name__)
+
+
+def link_request_ids(context, source_id, target_id=None, stage=None,
+ target_name=None, notifier=None):
+ """Links the Request ID from the Source service to
+ the Request ID returned from the Target service.
+
+ Linkages are logged and emitted as INFO notifications.
+
+ :params context: context object
+ :params source_id: the Request ID of the source
+ :params target_id: the Request ID of the target
+ :params stage: optional event name extension to
+ indicate which part of the linkage
+ this is.
+ :params target_name: human readable name of the
+ target system you are talking to.
+ :params notifier: notifier object
+
+ A typical use case is: System A asking System B
+ to perform some action. The linkages might look
+ like this:
+
+ link_request_ids(sys_A.request_ID, stage="start")
+ # send request to System B and get request ID
+ link_request_ids(sys_A.request_ID, target_id=sys_B.request.ID)
+ # optionally wait for System B to complete
+ link_request_ids(sys_A.request_ID, target_id=sys_B.request.ID,
+ stage="end")
+
+ But, it could be as simple as:
+ link_request_ids(sys_A.request_ID, target_id=sys_B.request.ID)
+ """
+
+ event_name = "request.link"
+ if stage:
+ event_name += ".%s" % stage
+
+ rtarget_id = ""
+ if target_id:
+ rtarget_id = _("TargetId=%(id)s ") % {'id': target_id}
+
+ rtarget_name = ""
+ if target_name:
+ rtarget_name = _("Target='%(name)s' ") % {'name': target_name}
+
+ arrow = ""
+ if target_name or target_id:
+ arrow = " -> "
+
+ LOG.info(_("Request ID Link: %(event_name)s '%(source_id)s'%(arrow)s"
+ "%(target_name)s%(target_id)s") % {"event_name": event_name,
+ "source_id": source_id,
+ "target_name": rtarget_name,
+ "arrow": arrow,
+ "target_id": rtarget_id})
+
+ if notifier:
+ payload = {"source_request_id": source_id,
+ "target_request_id": target_id,
+ "target_name": target_name,
+ "stage": stage}
+ notifier.info(context, event_name, payload)
module=lockutils
module=log
module=log_handler
+module=middleware
module=network_utils
module=notifier
module=periodic_task
module=policy
module=processutils
+module=request_utils
module=rootwrap
module=rpc
module=scheduler