From ec65605eded61801b817cc1e556de0ae8cb74f7c Mon Sep 17 00:00:00 2001
From: Ankit Agrawal <ankit11.agrawal@nttdata.com>
Date: Sun, 13 Dec 2015 23:59:38 -0800
Subject: [PATCH] Add request_ids attribute to resource objects

Added request_ids attribute to resource object for all the
cgsnapshots, consistencygroups, qos_specs, quota_classes,
quotas and services APIs by updating following APIs:

cgsnapshots: delete, update
consistencygroups: delete, update, create
qos_specs: delete, associate, disassociate, disassociate_all
quota_classes: update
quotas: update
services: enable, disable, disable_log_reason

These changes are required to return 'request_id' from client to
log request_id mappings of cross projects.

For more details on how request_id will be returned to the caller,
please refer to the approved blueprint [1] discussed with the
cross-project team.
[1] http://specs.openstack.org/openstack/openstack-specs/specs/return-request-id.html

DocImpact
'request-ids' will be returned as an attribute with response object.
User can access it using 'res.request_ids' where 'res' is a
response object.

Change-Id: I7b399512fcec9ecd31938656deb60e325bb76ad4
Partial-Implements: blueprint return-request-id-to-caller
---
 .../unit/fixture_data/availability_zones.py   | 11 ++-
 .../tests/unit/v2/test_availability_zone.py   |  2 +
 .../tests/unit/v2/test_capabilities.py        |  1 +
 .../tests/unit/v2/test_cgsnapshots.py         | 39 ++++++----
 .../tests/unit/v2/test_consistencygroups.py   | 74 +++++++++++++------
 cinderclient/tests/unit/v2/test_limits.py     | 14 +++-
 cinderclient/tests/unit/v2/test_pools.py      |  2 +
 cinderclient/tests/unit/v2/test_qos.py        | 30 +++++---
 .../tests/unit/v2/test_quota_classes.py       |  6 +-
 cinderclient/tests/unit/v2/test_quotas.py     | 12 ++-
 cinderclient/tests/unit/v2/test_services.py   |  7 ++
 cinderclient/v2/cgsnapshots.py                | 12 +--
 cinderclient/v2/consistencygroups.py          | 17 +++--
 cinderclient/v2/qos_specs.py                  | 23 ++++--
 cinderclient/v2/quota_classes.py              |  3 +-
 cinderclient/v2/quotas.py                     |  3 +-
 cinderclient/v2/services.py                   |  6 +-
 17 files changed, 181 insertions(+), 81 deletions(-)

diff --git a/cinderclient/tests/unit/fixture_data/availability_zones.py b/cinderclient/tests/unit/fixture_data/availability_zones.py
index 124e897c3..f1140a79f 100644
--- a/cinderclient/tests/unit/fixture_data/availability_zones.py
+++ b/cinderclient/tests/unit/fixture_data/availability_zones.py
@@ -15,6 +15,7 @@ from cinderclient.tests.unit.fixture_data import base
 
 # FIXME(jamielennox): use timeutils from oslo
 FORMAT = '%Y-%m-%d %H:%M:%S'
+REQUEST_ID = 'req-test-request-id'
 
 
 class Fixture(base.Fixture):
@@ -38,7 +39,10 @@ class Fixture(base.Fixture):
                 },
             ]
         }
-        self.requests.register_uri('GET', self.url(), json=get_availability)
+        self.requests.register_uri(
+            'GET', self.url(), json=get_availability,
+            headers={'x-openstack-request-id': REQUEST_ID}
+        )
 
         updated_1 = datetime(2012, 12, 26, 14, 45, 25, 0).strftime(FORMAT)
         updated_2 = datetime(2012, 12, 26, 14, 45, 24, 0).strftime(FORMAT)
@@ -77,4 +81,7 @@ class Fixture(base.Fixture):
                 },
             ]
         }
-        self.requests.register_uri('GET', self.url('detail'), json=get_detail)
+        self.requests.register_uri(
+            'GET', self.url('detail'), json=get_detail,
+            headers={'x-openstack-request-id': REQUEST_ID}
+        )
diff --git a/cinderclient/tests/unit/v2/test_availability_zone.py b/cinderclient/tests/unit/v2/test_availability_zone.py
index cc6da9bb8..7c46440b7 100644
--- a/cinderclient/tests/unit/v2/test_availability_zone.py
+++ b/cinderclient/tests/unit/v2/test_availability_zone.py
@@ -35,6 +35,7 @@ class AvailabilityZoneTest(utils.FixturedTestCase):
     def test_list_availability_zone(self):
         zones = self.cs.availability_zones.list(detailed=False)
         self.assert_called('GET', '/os-availability-zone')
+        self._assert_request_id(zones)
 
         for zone in zones:
             self.assertIsInstance(zone,
@@ -56,6 +57,7 @@ class AvailabilityZoneTest(utils.FixturedTestCase):
     def test_detail_availability_zone(self):
         zones = self.cs.availability_zones.list(detailed=True)
         self.assert_called('GET', '/os-availability-zone/detail')
+        self._assert_request_id(zones)
 
         for zone in zones:
             self.assertIsInstance(zone,
diff --git a/cinderclient/tests/unit/v2/test_capabilities.py b/cinderclient/tests/unit/v2/test_capabilities.py
index d23bdcd3b..ce0b67e7c 100644
--- a/cinderclient/tests/unit/v2/test_capabilities.py
+++ b/cinderclient/tests/unit/v2/test_capabilities.py
@@ -39,3 +39,4 @@ class CapabilitiesTest(utils.TestCase):
         capabilities = cs.capabilities.get('host')
         cs.assert_called('GET', '/capabilities/host')
         self.assertEqual(expected, capabilities._info)
+        self._assert_request_id(capabilities)
diff --git a/cinderclient/tests/unit/v2/test_cgsnapshots.py b/cinderclient/tests/unit/v2/test_cgsnapshots.py
index e4d480612..3ebef9e4f 100644
--- a/cinderclient/tests/unit/v2/test_cgsnapshots.py
+++ b/cinderclient/tests/unit/v2/test_cgsnapshots.py
@@ -25,19 +25,23 @@ class cgsnapshotsTest(utils.TestCase):
 
     def test_delete_cgsnapshot(self):
         v = cs.cgsnapshots.list()[0]
-        v.delete()
+        vol = v.delete()
+        self._assert_request_id(vol)
         cs.assert_called('DELETE', '/cgsnapshots/1234')
-        cs.cgsnapshots.delete('1234')
+        vol = cs.cgsnapshots.delete('1234')
         cs.assert_called('DELETE', '/cgsnapshots/1234')
-        cs.cgsnapshots.delete(v)
+        self._assert_request_id(vol)
+        vol = cs.cgsnapshots.delete(v)
         cs.assert_called('DELETE', '/cgsnapshots/1234')
+        self._assert_request_id(vol)
 
     def test_create_cgsnapshot(self):
-        cs.cgsnapshots.create('cgsnap')
+        vol = cs.cgsnapshots.create('cgsnap')
         cs.assert_called('POST', '/cgsnapshots')
+        self._assert_request_id(vol)
 
     def test_create_cgsnapshot_with_cg_id(self):
-        cs.cgsnapshots.create('1234')
+        vol = cs.cgsnapshots.create('1234')
         expected = {'cgsnapshot': {'status': 'creating',
                                    'description': None,
                                    'user_id': None,
@@ -45,37 +49,46 @@ class cgsnapshotsTest(utils.TestCase):
                                    'consistencygroup_id': '1234',
                                    'project_id': None}}
         cs.assert_called('POST', '/cgsnapshots', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_cgsnapshot(self):
         v = cs.cgsnapshots.list()[0]
         expected = {'cgsnapshot': {'name': 'cgs2'}}
-        v.update(name='cgs2')
+        vol = v.update(name='cgs2')
         cs.assert_called('PUT', '/cgsnapshots/1234', body=expected)
-        cs.cgsnapshots.update('1234', name='cgs2')
+        self._assert_request_id(vol)
+        vol = cs.cgsnapshots.update('1234', name='cgs2')
         cs.assert_called('PUT', '/cgsnapshots/1234', body=expected)
-        cs.cgsnapshots.update(v, name='cgs2')
+        self._assert_request_id(vol)
+        vol = cs.cgsnapshots.update(v, name='cgs2')
         cs.assert_called('PUT', '/cgsnapshots/1234', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_cgsnapshot_no_props(self):
         cs.cgsnapshots.update('1234')
 
     def test_list_cgsnapshot(self):
-        cs.cgsnapshots.list()
+        lst = cs.cgsnapshots.list()
         cs.assert_called('GET', '/cgsnapshots/detail')
+        self._assert_request_id(lst)
 
     def test_list_cgsnapshot_detailed_false(self):
-        cs.cgsnapshots.list(detailed=False)
+        lst = cs.cgsnapshots.list(detailed=False)
         cs.assert_called('GET', '/cgsnapshots')
+        self._assert_request_id(lst)
 
     def test_list_cgsnapshot_with_search_opts(self):
-        cs.cgsnapshots.list(search_opts={'foo': 'bar'})
+        lst = cs.cgsnapshots.list(search_opts={'foo': 'bar'})
         cs.assert_called('GET', '/cgsnapshots/detail?foo=bar')
+        self._assert_request_id(lst)
 
     def test_list_cgsnapshot_with_empty_search_opt(self):
-        cs.cgsnapshots.list(search_opts={'foo': 'bar', '123': None})
+        lst = cs.cgsnapshots.list(search_opts={'foo': 'bar', '123': None})
         cs.assert_called('GET', '/cgsnapshots/detail?foo=bar')
+        self._assert_request_id(lst)
 
     def test_get_cgsnapshot(self):
         cgsnapshot_id = '1234'
-        cs.cgsnapshots.get(cgsnapshot_id)
+        vol = cs.cgsnapshots.get(cgsnapshot_id)
         cs.assert_called('GET', '/cgsnapshots/%s' % cgsnapshot_id)
+        self._assert_request_id(vol)
diff --git a/cinderclient/tests/unit/v2/test_consistencygroups.py b/cinderclient/tests/unit/v2/test_consistencygroups.py
index 8ced91bec..a695fe9d9 100644
--- a/cinderclient/tests/unit/v2/test_consistencygroups.py
+++ b/cinderclient/tests/unit/v2/test_consistencygroups.py
@@ -24,19 +24,23 @@ class ConsistencygroupsTest(utils.TestCase):
 
     def test_delete_consistencygroup(self):
         v = cs.consistencygroups.list()[0]
-        v.delete(force='True')
+        vol = v.delete(force='True')
+        self._assert_request_id(vol)
         cs.assert_called('POST', '/consistencygroups/1234/delete')
-        cs.consistencygroups.delete('1234', force=True)
+        vol = cs.consistencygroups.delete('1234', force=True)
+        self._assert_request_id(vol)
         cs.assert_called('POST', '/consistencygroups/1234/delete')
-        cs.consistencygroups.delete(v, force=True)
+        vol = cs.consistencygroups.delete(v, force=True)
+        self._assert_request_id(vol)
         cs.assert_called('POST', '/consistencygroups/1234/delete')
 
     def test_create_consistencygroup(self):
-        cs.consistencygroups.create('type1,type2', 'cg')
+        vol = cs.consistencygroups.create('type1,type2', 'cg')
         cs.assert_called('POST', '/consistencygroups')
+        self._assert_request_id(vol)
 
     def test_create_consistencygroup_with_volume_types(self):
-        cs.consistencygroups.create('type1,type2', 'cg')
+        vol = cs.consistencygroups.create('type1,type2', 'cg')
         expected = {'consistencygroup': {'status': 'creating',
                                          'description': None,
                                          'availability_zone': None,
@@ -45,48 +49,61 @@ class ConsistencygroupsTest(utils.TestCase):
                                          'volume_types': 'type1,type2',
                                          'project_id': None}}
         cs.assert_called('POST', '/consistencygroups', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_consistencygroup_name(self):
         v = cs.consistencygroups.list()[0]
         expected = {'consistencygroup': {'name': 'cg2'}}
-        v.update(name='cg2')
+        vol = v.update(name='cg2')
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update('1234', name='cg2')
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update('1234', name='cg2')
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update(v, name='cg2')
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update(v, name='cg2')
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_consistencygroup_description(self):
         v = cs.consistencygroups.list()[0]
         expected = {'consistencygroup': {'description': 'cg2 desc'}}
-        v.update(description='cg2 desc')
+        vol = v.update(description='cg2 desc')
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update('1234', description='cg2 desc')
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update('1234', description='cg2 desc')
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update(v, description='cg2 desc')
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update(v, description='cg2 desc')
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_consistencygroup_add_volumes(self):
         v = cs.consistencygroups.list()[0]
         uuids = 'uuid1,uuid2'
         expected = {'consistencygroup': {'add_volumes': uuids}}
-        v.update(add_volumes=uuids)
+        vol = v.update(add_volumes=uuids)
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update('1234', add_volumes=uuids)
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update('1234', add_volumes=uuids)
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update(v, add_volumes=uuids)
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update(v, add_volumes=uuids)
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_consistencygroup_remove_volumes(self):
         v = cs.consistencygroups.list()[0]
         uuids = 'uuid3,uuid4'
         expected = {'consistencygroup': {'remove_volumes': uuids}}
-        v.update(remove_volumes=uuids)
+        vol = v.update(remove_volumes=uuids)
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update('1234', remove_volumes=uuids)
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update('1234', remove_volumes=uuids)
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
-        cs.consistencygroups.update(v, remove_volumes=uuids)
+        self._assert_request_id(vol)
+        vol = cs.consistencygroups.update(v, remove_volumes=uuids)
         cs.assert_called('PUT', '/consistencygroups/1234', body=expected)
+        self._assert_request_id(vol)
 
     def test_update_consistencygroup_none(self):
         self.assertIsNone(cs.consistencygroups.update('1234'))
@@ -95,7 +112,7 @@ class ConsistencygroupsTest(utils.TestCase):
         cs.consistencygroups.update('1234')
 
     def test_create_consistencygroup_from_src_snap(self):
-        cs.consistencygroups.create_from_src('5678', None, name='cg')
+        vol = cs.consistencygroups.create_from_src('5678', None, name='cg')
         expected = {
             'consistencygroup-from-src': {
                 'status': 'creating',
@@ -109,9 +126,10 @@ class ConsistencygroupsTest(utils.TestCase):
         }
         cs.assert_called('POST', '/consistencygroups/create_from_src',
                          body=expected)
+        self._assert_request_id(vol)
 
     def test_create_consistencygroup_from_src_cg(self):
-        cs.consistencygroups.create_from_src(None, '5678', name='cg')
+        vol = cs.consistencygroups.create_from_src(None, '5678', name='cg')
         expected = {
             'consistencygroup-from-src': {
                 'status': 'creating',
@@ -125,24 +143,32 @@ class ConsistencygroupsTest(utils.TestCase):
         }
         cs.assert_called('POST', '/consistencygroups/create_from_src',
                          body=expected)
+        self._assert_request_id(vol)
 
     def test_list_consistencygroup(self):
-        cs.consistencygroups.list()
+        lst = cs.consistencygroups.list()
         cs.assert_called('GET', '/consistencygroups/detail')
+        self._assert_request_id(lst)
 
     def test_list_consistencygroup_detailed_false(self):
-        cs.consistencygroups.list(detailed=False)
+        lst = cs.consistencygroups.list(detailed=False)
         cs.assert_called('GET', '/consistencygroups')
+        self._assert_request_id(lst)
 
     def test_list_consistencygroup_with_search_opts(self):
-        cs.consistencygroups.list(search_opts={'foo': 'bar'})
+        lst = cs.consistencygroups.list(search_opts={'foo': 'bar'})
         cs.assert_called('GET', '/consistencygroups/detail?foo=bar')
+        self._assert_request_id(lst)
 
     def test_list_consistencygroup_with_empty_search_opt(self):
-        cs.consistencygroups.list(search_opts={'foo': 'bar', 'abc': None})
+        lst = cs.consistencygroups.list(
+            search_opts={'foo': 'bar', 'abc': None}
+        )
         cs.assert_called('GET', '/consistencygroups/detail?foo=bar')
+        self._assert_request_id(lst)
 
     def test_get_consistencygroup(self):
         consistencygroup_id = '1234'
-        cs.consistencygroups.get(consistencygroup_id)
+        vol = cs.consistencygroups.get(consistencygroup_id)
         cs.assert_called('GET', '/consistencygroups/%s' % consistencygroup_id)
+        self._assert_request_id(vol)
diff --git a/cinderclient/tests/unit/v2/test_limits.py b/cinderclient/tests/unit/v2/test_limits.py
index e296541a5..6c143bf80 100644
--- a/cinderclient/tests/unit/v2/test_limits.py
+++ b/cinderclient/tests/unit/v2/test_limits.py
@@ -19,6 +19,9 @@ from cinderclient.tests.unit import utils
 from cinderclient.v2 import limits
 
 
+REQUEST_ID = 'req-test-request-id'
+
+
 def _get_default_RateLimit(verb="verb1", uri="uri1", regex="regex1",
                            value="value1",
                            remain="remain1", unit="unit1",
@@ -29,16 +32,19 @@ def _get_default_RateLimit(verb="verb1", uri="uri1", regex="regex1",
 
 class TestLimits(utils.TestCase):
     def test_repr(self):
-        l = limits.Limits(None, {"foo": "bar"})
+        l = limits.Limits(None, {"foo": "bar"}, resp=REQUEST_ID)
         self.assertEqual("<Limits>", repr(l))
+        self._assert_request_id(l)
 
     def test_absolute(self):
         l = limits.Limits(None,
-                          {"absolute": {"name1": "value1", "name2": "value2"}})
+                          {"absolute": {"name1": "value1", "name2": "value2"}},
+                          resp=REQUEST_ID)
         l1 = limits.AbsoluteLimit("name1", "value1")
         l2 = limits.AbsoluteLimit("name2", "value2")
         for item in l.absolute:
             self.assertIn(item, [l1, l2])
+        self._assert_request_id(l)
 
     def test_rate(self):
         l = limits.Limits(None,
@@ -71,13 +77,15 @@ class TestLimits(utils.TestCase):
                                       ],
                                   },
                               ],
-                          })
+                          },
+                          resp=REQUEST_ID)
         l1 = limits.RateLimit("verb1", "uri1", "regex1", "value1", "remain1",
                               "unit1", "next1")
         l2 = limits.RateLimit("verb2", "uri2", "regex2", "value2", "remain2",
                               "unit2", "next2")
         for item in l.rate:
             self.assertIn(item, [l1, l2])
+        self._assert_request_id(l)
 
 
 class TestRateLimit(utils.TestCase):
diff --git a/cinderclient/tests/unit/v2/test_pools.py b/cinderclient/tests/unit/v2/test_pools.py
index 921d58f82..9ab90493e 100644
--- a/cinderclient/tests/unit/v2/test_pools.py
+++ b/cinderclient/tests/unit/v2/test_pools.py
@@ -25,6 +25,7 @@ class PoolsTest(utils.TestCase):
     def test_get_pool_stats(self):
         sl = cs.pools.list()
         cs.assert_called('GET', '/scheduler-stats/get_pools')
+        self._assert_request_id(sl)
         for s in sl:
             self.assertIsInstance(s, Pool)
             self.assertTrue(hasattr(s, "name"))
@@ -35,6 +36,7 @@ class PoolsTest(utils.TestCase):
 
     def test_get_detail_pool_stats(self):
         sl = cs.pools.list(detailed=True)
+        self._assert_request_id(sl)
         cs.assert_called('GET', '/scheduler-stats/get_pools?detail=True')
         for s in sl:
             self.assertIsInstance(s, Pool)
diff --git a/cinderclient/tests/unit/v2/test_qos.py b/cinderclient/tests/unit/v2/test_qos.py
index bd303f5cc..809a71947 100644
--- a/cinderclient/tests/unit/v2/test_qos.py
+++ b/cinderclient/tests/unit/v2/test_qos.py
@@ -24,56 +24,66 @@ class QoSSpecsTest(utils.TestCase):
 
     def test_create(self):
         specs = dict(k1='v1', k2='v2')
-        cs.qos_specs.create('qos-name', specs)
+        qos = cs.qos_specs.create('qos-name', specs)
         cs.assert_called('POST', '/qos-specs')
+        self._assert_request_id(qos)
 
     def test_get(self):
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
-        cs.qos_specs.get(qos_id)
+        qos = cs.qos_specs.get(qos_id)
         cs.assert_called('GET', '/qos-specs/%s' % qos_id)
+        self._assert_request_id(qos)
 
     def test_list(self):
-        cs.qos_specs.list()
+        lst = cs.qos_specs.list()
         cs.assert_called('GET', '/qos-specs')
+        self._assert_request_id(lst)
 
     def test_delete(self):
-        cs.qos_specs.delete('1B6B6A04-A927-4AEB-810B-B7BAAD49F57C')
+        qos = cs.qos_specs.delete('1B6B6A04-A927-4AEB-810B-B7BAAD49F57C')
         cs.assert_called('DELETE',
                          '/qos-specs/1B6B6A04-A927-4AEB-810B-B7BAAD49F57C?'
                          'force=False')
+        self._assert_request_id(qos)
 
     def test_set_keys(self):
         body = {'qos_specs': dict(k1='v1')}
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
-        cs.qos_specs.set_keys(qos_id, body)
+        qos = cs.qos_specs.set_keys(qos_id, body)
         cs.assert_called('PUT', '/qos-specs/%s' % qos_id)
+        self._assert_request_id(qos)
 
     def test_unset_keys(self):
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
         body = {'keys': ['k1']}
-        cs.qos_specs.unset_keys(qos_id, body)
+        qos = cs.qos_specs.unset_keys(qos_id, body)
         cs.assert_called('PUT', '/qos-specs/%s/delete_keys' % qos_id)
+        self._assert_request_id(qos)
 
     def test_get_associations(self):
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
-        cs.qos_specs.get_associations(qos_id)
+        qos = cs.qos_specs.get_associations(qos_id)
         cs.assert_called('GET', '/qos-specs/%s/associations' % qos_id)
+        self._assert_request_id(qos)
 
     def test_associate(self):
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
         type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
-        cs.qos_specs.associate(qos_id, type_id)
+        qos = cs.qos_specs.associate(qos_id, type_id)
         cs.assert_called('GET', '/qos-specs/%s/associate?vol_type_id=%s'
                          % (qos_id, type_id))
+        self._assert_request_id(qos)
 
     def test_disassociate(self):
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
         type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
-        cs.qos_specs.disassociate(qos_id, type_id)
+        qos = cs.qos_specs.disassociate(qos_id, type_id)
         cs.assert_called('GET', '/qos-specs/%s/disassociate?vol_type_id=%s'
                          % (qos_id, type_id))
+        self._assert_request_id(qos)
 
     def test_disassociate_all(self):
         qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
-        cs.qos_specs.disassociate_all(qos_id)
+        qos = cs.qos_specs.disassociate_all(qos_id)
         cs.assert_called('GET', '/qos-specs/%s/disassociate_all' % qos_id)
+        self._assert_request_id(qos)
diff --git a/cinderclient/tests/unit/v2/test_quota_classes.py b/cinderclient/tests/unit/v2/test_quota_classes.py
index 8bb675f63..91cf98b09 100644
--- a/cinderclient/tests/unit/v2/test_quota_classes.py
+++ b/cinderclient/tests/unit/v2/test_quota_classes.py
@@ -24,8 +24,9 @@ class QuotaClassSetsTest(utils.TestCase):
 
     def test_class_quotas_get(self):
         class_name = 'test'
-        cs.quota_classes.get(class_name)
+        cls = cs.quota_classes.get(class_name)
         cs.assert_called('GET', '/os-quota-class-sets/%s' % class_name)
+        self._assert_request_id(cls)
 
     def test_update_quota(self):
         q = cs.quota_classes.get('test')
@@ -33,6 +34,7 @@ class QuotaClassSetsTest(utils.TestCase):
                  backups=2, backup_gigabytes=2000,
                  consistencygroups=2, per_volume_gigabytes=100)
         cs.assert_called('PUT', '/os-quota-class-sets/test')
+        self._assert_request_id(q)
 
     def test_refresh_quota(self):
         q = cs.quota_classes.get('test')
@@ -66,3 +68,5 @@ class QuotaClassSetsTest(utils.TestCase):
         self.assertEqual(q.backup_gigabytes, q2.backup_gigabytes)
         self.assertEqual(q.consistencygroups, q2.consistencygroups)
         self.assertEqual(q.per_volume_gigabytes, q2.per_volume_gigabytes)
+        self._assert_request_id(q)
+        self._assert_request_id(q2)
diff --git a/cinderclient/tests/unit/v2/test_quotas.py b/cinderclient/tests/unit/v2/test_quotas.py
index f14ff3553..6dd20b01d 100644
--- a/cinderclient/tests/unit/v2/test_quotas.py
+++ b/cinderclient/tests/unit/v2/test_quotas.py
@@ -24,13 +24,15 @@ class QuotaSetsTest(utils.TestCase):
 
     def test_tenant_quotas_get(self):
         tenant_id = 'test'
-        cs.quotas.get(tenant_id)
+        quota = cs.quotas.get(tenant_id)
         cs.assert_called('GET', '/os-quota-sets/%s?usage=False' % tenant_id)
+        self._assert_request_id(quota)
 
     def test_tenant_quotas_defaults(self):
         tenant_id = 'test'
-        cs.quotas.defaults(tenant_id)
+        quota = cs.quotas.defaults(tenant_id)
         cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id)
+        self._assert_request_id(quota)
 
     def test_update_quota(self):
         q = cs.quotas.get('test')
@@ -42,6 +44,7 @@ class QuotaSetsTest(utils.TestCase):
         q.update(consistencygroups=2)
         q.update(per_volume_gigabytes=100)
         cs.assert_called('PUT', '/os-quota-sets/test')
+        self._assert_request_id(q)
 
     def test_refresh_quota(self):
         q = cs.quotas.get('test')
@@ -75,8 +78,11 @@ class QuotaSetsTest(utils.TestCase):
         self.assertEqual(q.backup_gigabytes, q2.backup_gigabytes)
         self.assertEqual(q.consistencygroups, q2.consistencygroups)
         self.assertEqual(q.per_volume_gigabytes, q2.per_volume_gigabytes)
+        self._assert_request_id(q)
+        self._assert_request_id(q2)
 
     def test_delete_quota(self):
         tenant_id = 'test'
-        cs.quotas.delete(tenant_id)
+        quota = cs.quotas.delete(tenant_id)
         cs.assert_called('DELETE', '/os-quota-sets/test')
+        self._assert_request_id(quota)
diff --git a/cinderclient/tests/unit/v2/test_services.py b/cinderclient/tests/unit/v2/test_services.py
index 12da4c38a..4e08e69fe 100644
--- a/cinderclient/tests/unit/v2/test_services.py
+++ b/cinderclient/tests/unit/v2/test_services.py
@@ -28,6 +28,7 @@ class ServicesTest(utils.TestCase):
         cs.assert_called('GET', '/os-services')
         self.assertEqual(3, len(svs))
         [self.assertIsInstance(s, services.Service) for s in svs]
+        self._assert_request_id(svs)
 
     def test_list_services_with_hostname(self):
         svs = cs.services.list(host='host2')
@@ -35,6 +36,7 @@ class ServicesTest(utils.TestCase):
         self.assertEqual(2, len(svs))
         [self.assertIsInstance(s, services.Service) for s in svs]
         [self.assertEqual('host2', s.host) for s in svs]
+        self._assert_request_id(svs)
 
     def test_list_services_with_binary(self):
         svs = cs.services.list(binary='cinder-volume')
@@ -42,6 +44,7 @@ class ServicesTest(utils.TestCase):
         self.assertEqual(2, len(svs))
         [self.assertIsInstance(s, services.Service) for s in svs]
         [self.assertEqual('cinder-volume', s.binary) for s in svs]
+        self._assert_request_id(svs)
 
     def test_list_services_with_host_binary(self):
         svs = cs.services.list('host2', 'cinder-volume')
@@ -50,6 +53,7 @@ class ServicesTest(utils.TestCase):
         [self.assertIsInstance(s, services.Service) for s in svs]
         [self.assertEqual('host2', s.host) for s in svs]
         [self.assertEqual('cinder-volume', s.binary) for s in svs]
+        self._assert_request_id(svs)
 
     def test_services_enable(self):
         s = cs.services.enable('host1', 'cinder-volume')
@@ -57,6 +61,7 @@ class ServicesTest(utils.TestCase):
         cs.assert_called('PUT', '/os-services/enable', values)
         self.assertIsInstance(s, services.Service)
         self.assertEqual('enabled', s.status)
+        self._assert_request_id(s)
 
     def test_services_disable(self):
         s = cs.services.disable('host1', 'cinder-volume')
@@ -64,6 +69,7 @@ class ServicesTest(utils.TestCase):
         cs.assert_called('PUT', '/os-services/disable', values)
         self.assertIsInstance(s, services.Service)
         self.assertEqual('disabled', s.status)
+        self._assert_request_id(s)
 
     def test_services_disable_log_reason(self):
         s = cs.services.disable_log_reason(
@@ -73,3 +79,4 @@ class ServicesTest(utils.TestCase):
         cs.assert_called('PUT', '/os-services/disable-log-reason', values)
         self.assertIsInstance(s, services.Service)
         self.assertEqual('disabled', s.status)
+        self._assert_request_id(s)
diff --git a/cinderclient/v2/cgsnapshots.py b/cinderclient/v2/cgsnapshots.py
index 29513a9ab..f41434a8b 100644
--- a/cinderclient/v2/cgsnapshots.py
+++ b/cinderclient/v2/cgsnapshots.py
@@ -22,6 +22,7 @@ except ImportError:
     from urllib.parse import urlencode
 
 from cinderclient import base
+from cinderclient.openstack.common.apiclient import base as common_base
 
 
 class Cgsnapshot(base.Resource):
@@ -31,11 +32,11 @@ class Cgsnapshot(base.Resource):
 
     def delete(self):
         """Delete this cgsnapshot."""
-        self.manager.delete(self)
+        return self.manager.delete(self)
 
     def update(self, **kwargs):
         """Update the name or description for this cgsnapshot."""
-        self.manager.update(self, **kwargs)
+        return self.manager.update(self, **kwargs)
 
 
 class CgsnapshotManager(base.ManagerWithFind):
@@ -101,7 +102,7 @@ class CgsnapshotManager(base.ManagerWithFind):
 
         :param cgsnapshot: The :class:`Cgsnapshot` to delete.
         """
-        self._delete("/cgsnapshots/%s" % base.getid(cgsnapshot))
+        return self._delete("/cgsnapshots/%s" % base.getid(cgsnapshot))
 
     def update(self, cgsnapshot, **kwargs):
         """Update the name or description for a cgsnapshot.
@@ -113,7 +114,7 @@ class CgsnapshotManager(base.ManagerWithFind):
 
         body = {"cgsnapshot": kwargs}
 
-        self._update("/cgsnapshots/%s" % base.getid(cgsnapshot), body)
+        return self._update("/cgsnapshots/%s" % base.getid(cgsnapshot), body)
 
     def _action(self, action, cgsnapshot, info=None, **kwargs):
         """Perform a cgsnapshot "action."
@@ -121,4 +122,5 @@ class CgsnapshotManager(base.ManagerWithFind):
         body = {action: info}
         self.run_hooks('modify_body_for_action', body, **kwargs)
         url = '/cgsnapshots/%s/action' % base.getid(cgsnapshot)
-        return self.api.client.post(url, body=body)
+        resp, body = self.api.client.post(url, body=body)
+        return common_base.TupleWithMeta((resp, body), resp)
diff --git a/cinderclient/v2/consistencygroups.py b/cinderclient/v2/consistencygroups.py
index 122468582..4f68bf822 100644
--- a/cinderclient/v2/consistencygroups.py
+++ b/cinderclient/v2/consistencygroups.py
@@ -22,6 +22,7 @@ except ImportError:
     from urllib.parse import urlencode
 
 from cinderclient import base
+from cinderclient.openstack.common.apiclient import base as common_base
 
 
 class Consistencygroup(base.Resource):
@@ -31,11 +32,11 @@ class Consistencygroup(base.Resource):
 
     def delete(self, force='False'):
         """Delete this consistencygroup."""
-        self.manager.delete(self, force)
+        return self.manager.delete(self, force)
 
     def update(self, **kwargs):
         """Update the name or description for this consistencygroup."""
-        self.manager.update(self, **kwargs)
+        return self.manager.update(self, **kwargs)
 
 
 class ConsistencygroupManager(base.ManagerWithFind):
@@ -93,7 +94,7 @@ class ConsistencygroupManager(base.ManagerWithFind):
                        'consistencygroup-from-src')
         resp, body = self.api.client.post(
             "/consistencygroups/create_from_src", body=body)
-        return body['consistencygroup']
+        return common_base.DictWithMeta(body['consistencygroup'], resp)
 
     def get(self, group_id):
         """Get a consistencygroup.
@@ -135,7 +136,8 @@ class ConsistencygroupManager(base.ManagerWithFind):
         body = {'consistencygroup': {'force': force}}
         self.run_hooks('modify_body_for_action', body, 'consistencygroup')
         url = '/consistencygroups/%s/delete' % base.getid(consistencygroup)
-        return self.api.client.post(url, body=body)
+        resp, body = self.api.client.post(url, body=body)
+        return common_base.TupleWithMeta((resp, body), resp)
 
     def update(self, consistencygroup, **kwargs):
         """Update the name or description for a consistencygroup.
@@ -147,8 +149,8 @@ class ConsistencygroupManager(base.ManagerWithFind):
 
         body = {"consistencygroup": kwargs}
 
-        self._update("/consistencygroups/%s" % base.getid(consistencygroup),
-                     body)
+        return self._update("/consistencygroups/%s" %
+                            base.getid(consistencygroup), body)
 
     def _action(self, action, consistencygroup, info=None, **kwargs):
         """Perform a consistencygroup "action."
@@ -156,4 +158,5 @@ class ConsistencygroupManager(base.ManagerWithFind):
         body = {action: info}
         self.run_hooks('modify_body_for_action', body, **kwargs)
         url = '/consistencygroups/%s/action' % base.getid(consistencygroup)
-        return self.api.client.post(url, body=body)
+        resp, body = self.api.client.post(url, body=body)
+        return common_base.TupleWithMeta((resp, body), resp)
diff --git a/cinderclient/v2/qos_specs.py b/cinderclient/v2/qos_specs.py
index b7836e31f..84b8e0ac5 100644
--- a/cinderclient/v2/qos_specs.py
+++ b/cinderclient/v2/qos_specs.py
@@ -20,6 +20,7 @@ QoS Specs interface.
 """
 
 from cinderclient import base
+from cinderclient.openstack.common.apiclient import base as common_base
 
 
 class QoSSpecs(base.Resource):
@@ -65,8 +66,8 @@ class QoSSpecsManager(base.ManagerWithFind):
         :param force: Flag that indicates whether to delete target qos specs
                       if it was in-use.
         """
-        self._delete("/qos-specs/%s?force=%s" %
-                     (base.getid(qos_specs), force))
+        return self._delete("/qos-specs/%s?force=%s" %
+                            (base.getid(qos_specs), force))
 
     def create(self, name, specs):
         """Create a qos specs.
@@ -128,8 +129,10 @@ class QoSSpecsManager(base.ManagerWithFind):
         :param qos_specs: The qos specs to be associated with
         :param vol_type_id: The volume type id to be associated with
         """
-        self.api.client.get("/qos-specs/%s/associate?vol_type_id=%s" %
-                            (base.getid(qos_specs), vol_type_id))
+        resp, body = self.api.client.get(
+            "/qos-specs/%s/associate?vol_type_id=%s" %
+            (base.getid(qos_specs), vol_type_id))
+        return common_base.TupleWithMeta((resp, body), resp)
 
     def disassociate(self, qos_specs, vol_type_id):
         """Disassociate qos specs from volume type.
@@ -137,13 +140,17 @@ class QoSSpecsManager(base.ManagerWithFind):
         :param qos_specs: The qos specs to be associated with
         :param vol_type_id: The volume type id to be associated with
         """
-        self.api.client.get("/qos-specs/%s/disassociate?vol_type_id=%s" %
-                            (base.getid(qos_specs), vol_type_id))
+        resp, body = self.api.client.get(
+            "/qos-specs/%s/disassociate?vol_type_id=%s" %
+            (base.getid(qos_specs), vol_type_id))
+        return common_base.TupleWithMeta((resp, body), resp)
 
     def disassociate_all(self, qos_specs):
         """Disassociate all entities from specific qos specs.
 
         :param qos_specs: The qos specs to be associated with
         """
-        self.api.client.get("/qos-specs/%s/disassociate_all" %
-                            base.getid(qos_specs))
+        resp, body = self.api.client.get(
+            "/qos-specs/%s/disassociate_all" %
+            base.getid(qos_specs))
+        return common_base.TupleWithMeta((resp, body), resp)
diff --git a/cinderclient/v2/quota_classes.py b/cinderclient/v2/quota_classes.py
index c9c40f13b..0e5fb5b83 100644
--- a/cinderclient/v2/quota_classes.py
+++ b/cinderclient/v2/quota_classes.py
@@ -42,4 +42,5 @@ class QuotaClassSetManager(base.Manager):
 
         result = self._update('/os-quota-class-sets/%s' % (class_name), body)
         return self.resource_class(self,
-                                   result['quota_class_set'], loaded=True)
+                                   result['quota_class_set'], loaded=True,
+                                   resp=result.request_ids)
diff --git a/cinderclient/v2/quotas.py b/cinderclient/v2/quotas.py
index fbc691450..bebf32a39 100644
--- a/cinderclient/v2/quotas.py
+++ b/cinderclient/v2/quotas.py
@@ -43,7 +43,8 @@ class QuotaSetManager(base.Manager):
             body['quota_set'][update] = updates[update]
 
         result = self._update('/os-quota-sets/%s' % (tenant_id), body)
-        return self.resource_class(self, result['quota_set'], loaded=True)
+        return self.resource_class(self, result['quota_set'], loaded=True,
+                                   resp=result.request_ids)
 
     def defaults(self, tenant_id):
         return self._get('/os-quota-sets/%s/defaults' % tenant_id,
diff --git a/cinderclient/v2/services.py b/cinderclient/v2/services.py
index 3bc4b3b43..b58efa61a 100644
--- a/cinderclient/v2/services.py
+++ b/cinderclient/v2/services.py
@@ -49,16 +49,16 @@ class ServiceManager(base.ManagerWithFind):
         """Enable the service specified by hostname and binary."""
         body = {"host": host, "binary": binary}
         result = self._update("/os-services/enable", body)
-        return self.resource_class(self, result)
+        return self.resource_class(self, result, resp=result.request_ids)
 
     def disable(self, host, binary):
         """Disable the service specified by hostname and binary."""
         body = {"host": host, "binary": binary}
         result = self._update("/os-services/disable", body)
-        return self.resource_class(self, result)
+        return self.resource_class(self, result, resp=result.request_ids)
 
     def disable_log_reason(self, host, binary, reason):
         """Disable the service with reason."""
         body = {"host": host, "binary": binary, "disabled_reason": reason}
         result = self._update("/os-services/disable-log-reason", body)
-        return self.resource_class(self, result)
+        return self.resource_class(self, result, resp=result.request_ids)