diff --git a/cinderclient/openstack/common/apiclient/base.py b/cinderclient/openstack/common/apiclient/base.py
index 82670aa56..460e7b995 100644
--- a/cinderclient/openstack/common/apiclient/base.py
+++ b/cinderclient/openstack/common/apiclient/base.py
@@ -26,6 +26,7 @@ Base utilities to build API operation managers and objects on top of.
 import abc
 import copy
 
+from requests import Response
 import six
 from six.moves.urllib import parse
 
@@ -409,7 +410,43 @@ class Extension(HookableMixin):
         return "<Extension '%s'>" % self.name
 
 
-class Resource(object):
+class RequestIdMixin(object):
+    """Wrapper class to expose x-openstack-request-id to the caller."""
+    def setup(self):
+        self.x_openstack_request_ids = []
+
+    @property
+    def request_ids(self):
+        return self.x_openstack_request_ids
+
+    def append_request_ids(self, resp):
+        """Add request_ids as an attribute to the object
+
+        :param resp: list, Response object or string
+        """
+        if resp is None:
+            return
+
+        if isinstance(resp, list):
+            # Add list of request_ids if response is of type list.
+            for resp_obj in resp:
+                self._append_request_id(resp_obj)
+        else:
+            # Add request_ids if response contains single object.
+            self._append_request_id(resp)
+
+    def _append_request_id(self, resp):
+        if isinstance(resp, Response):
+            # Extract 'x-openstack-request-id' from headers if
+            # response is a Response object.
+            request_id = resp.headers.get('x-openstack-request-id')
+            self.x_openstack_request_ids.append(request_id)
+        else:
+            # If resp is of type string (in case of encryption type list)
+            self.x_openstack_request_ids.append(resp)
+
+
+class Resource(RequestIdMixin):
     """Base class for OpenStack resources (tenant, user, etc.).
 
     This is pretty much just a bag for attributes.
@@ -418,22 +455,26 @@ class Resource(object):
     HUMAN_ID = False
     NAME_ATTR = 'name'
 
-    def __init__(self, manager, info, loaded=False):
+    def __init__(self, manager, info, loaded=False, resp=None):
         """Populate and bind to a manager.
 
         :param manager: BaseManager object
         :param info: dictionary representing resource attributes
         :param loaded: prevent lazy-loading if set to True
+        :param resp: Response or list of Response objects
         """
         self.manager = manager
         self._info = info
         self._add_details(info)
         self._loaded = loaded
+        self.setup()
+        self.append_request_ids(resp)
 
     def __repr__(self):
         reprkeys = sorted(k
                           for k in self.__dict__.keys()
-                          if k[0] != '_' and k != 'manager')
+                          if k[0] != '_' and
+                          k not in ['manager', 'x_openstack_request_ids'])
         info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
         return "<%s %s>" % (self.__class__.__name__, info)
 
@@ -493,3 +534,26 @@ class Resource(object):
 
     def to_dict(self):
         return copy.deepcopy(self._info)
+
+
+class ListWithMeta(list, RequestIdMixin):
+    def __init__(self, values, resp):
+        super(ListWithMeta, self).__init__(values)
+        self.setup()
+        self.append_request_ids(resp)
+
+
+class DictWithMeta(dict, RequestIdMixin):
+    def __init__(self, values, resp):
+        super(DictWithMeta, self).__init__(values)
+        self.setup()
+        self.append_request_ids(resp)
+
+
+class TupleWithMeta(tuple, RequestIdMixin):
+    def __new__(cls, resp, values):
+        return super(TupleWithMeta, cls).__new__(cls, (resp, values))
+
+    def __init__(self, resp, values):
+        self.setup()
+        self.append_request_ids(resp)
diff --git a/cinderclient/tests/unit/test_base.py b/cinderclient/tests/unit/test_base.py
index 105d9b7c0..7d329dedc 100644
--- a/cinderclient/tests/unit/test_base.py
+++ b/cinderclient/tests/unit/test_base.py
@@ -11,8 +11,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from requests import Response
+
 from cinderclient import base
 from cinderclient import exceptions
+from cinderclient.openstack.common.apiclient import base as common_base
 from cinderclient.v1 import volumes
 from cinderclient.tests.unit import utils
 from cinderclient.tests.unit.v1 import fakes
@@ -21,11 +24,21 @@ from cinderclient.tests.unit.v1 import fakes
 cs = fakes.FakeClient()
 
 
+REQUEST_ID = 'req-test-request-id'
+
+
+def create_response_obj_with_header():
+    resp = Response()
+    resp.headers['x-openstack-request-id'] = REQUEST_ID
+    return resp
+
+
 class BaseTest(utils.TestCase):
 
     def test_resource_repr(self):
         r = base.Resource(None, dict(foo="bar", baz="spam"))
         self.assertEqual("<Resource baz=spam, foo=bar>", repr(r))
+        self.assertNotIn("x_openstack_request_ids", repr(r))
 
     def test_getid(self):
         self.assertEqual(4, base.getid(4))
@@ -63,3 +76,38 @@ class BaseTest(utils.TestCase):
     def test_to_dict(self):
         r1 = base.Resource(None, {'id': 1, 'name': 'hi'})
         self.assertEqual({'id': 1, 'name': 'hi'}, r1.to_dict())
+
+    def test_resource_object_with_request_ids(self):
+        resp_obj = create_response_obj_with_header()
+        r = base.Resource(None, {"name": "1"}, resp=resp_obj)
+        self.assertEqual([REQUEST_ID], r.request_ids)
+
+
+class ListWithMetaTest(utils.TestCase):
+    def test_list_with_meta(self):
+        resp = create_response_obj_with_header()
+        obj = common_base.ListWithMeta([], resp)
+        self.assertEqual([], obj)
+        # Check request_ids attribute is added to obj
+        self.assertTrue(hasattr(obj, 'request_ids'))
+        self.assertEqual([REQUEST_ID], obj.request_ids)
+
+
+class DictWithMetaTest(utils.TestCase):
+    def test_dict_with_meta(self):
+        resp = create_response_obj_with_header()
+        obj = common_base.DictWithMeta([], resp)
+        self.assertEqual({}, obj)
+        # Check request_ids attribute is added to obj
+        self.assertTrue(hasattr(obj, 'request_ids'))
+        self.assertEqual([REQUEST_ID], obj.request_ids)
+
+
+class TupleWithMetaTest(utils.TestCase):
+    def test_tuple_with_meta(self):
+        resp = create_response_obj_with_header()
+        obj = common_base.TupleWithMeta(resp, None)
+        self.assertIsInstance(obj, tuple)
+        # Check request_ids attribute is added to obj
+        self.assertTrue(hasattr(obj, 'request_ids'))
+        self.assertEqual([REQUEST_ID], obj.request_ids)