Provide user with coherent interface to get request_ids

Currently, users must use different interface to get request_ids.
1. Commonly, ListWithMeta, DictWithMeta or TupleWithMeta, etc is
returned to user. And request_ids is returned as an attribute of
*WithMeta.

    For a server delete action:
        result = serverManager.delete(server)
        # result = TupelWithMeta
        request_ids = result.request_ids

2. Some places reutrn a tuple which contains request_ids in one of
its elements.

    For a server stop action:
        result = serverManager.stop(server)
        # result = (Response, TupleWithMeta)
        request_ids = result[1].request_ids

Such kind of difference makes user confused.
This change provides a backwards compatibility solution for users
who don't care about request_ids as TupleWithMeta is subclass of
tuple.

Change-Id: I164bb95abce6dc96cf455033f02822ccb0d87b8f
Closes-Bug: 1542179
This commit is contained in:
Cao Shufeng 2016-02-05 16:59:21 +08:00 committed by Cao ShuFeng
parent 0927de6c8e
commit f535e6945b
4 changed files with 42 additions and 56 deletions

View File

@ -73,21 +73,21 @@ class HostsTest(utils.FixturedTestCase):
def test_host_startup(self):
host = self.cs.hosts.get('sample_host')[0]
resp, result = host.startup()
result = host.startup()
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called(
'GET', '/os-hosts/sample_host/startup')
def test_host_reboot(self):
host = self.cs.hosts.get('sample_host')[0]
resp, result = host.reboot()
result = host.reboot()
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called(
'GET', '/os-hosts/sample_host/reboot')
def test_host_shutdown(self):
host = self.cs.hosts.get('sample_host')[0]
resp, result = host.shutdown()
result = host.shutdown()
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called(
'GET', '/os-hosts/sample_host/shutdown')

View File

@ -597,28 +597,28 @@ class ServersTest(utils.FixturedTestCase):
def test_stop(self):
s = self.cs.servers.get(1234)
resp, ret = s.stop()
ret = s.stop()
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
resp, ret = self.cs.servers.stop(s)
ret = self.cs.servers.stop(s)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
def test_force_delete(self):
s = self.cs.servers.get(1234)
resp, ret = s.force_delete()
ret = s.force_delete()
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
resp, ret = self.cs.servers.force_delete(s)
ret = self.cs.servers.force_delete(s)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
def test_restore(self):
s = self.cs.servers.get(1234)
resp, ret = s.restore()
ret = s.restore()
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
resp, ret = self.cs.servers.restore(s)
ret = self.cs.servers.restore(s)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
@ -633,31 +633,31 @@ class ServersTest(utils.FixturedTestCase):
def test_rescue(self):
s = self.cs.servers.get(1234)
resp, ret = s.rescue()
ret = s.rescue()
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
resp, ret = self.cs.servers.rescue(s)
ret = self.cs.servers.rescue(s)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
def test_rescue_password(self):
s = self.cs.servers.get(1234)
resp, ret = s.rescue(password='asdf')
ret = s.rescue(password='asdf')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'rescue': {'adminPass': 'asdf'}})
resp, ret = self.cs.servers.rescue(s, password='asdf')
ret = self.cs.servers.rescue(s, password='asdf')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'rescue': {'adminPass': 'asdf'}})
def test_rescue_image(self):
s = self.cs.servers.get(1234)
resp, ret = s.rescue(image=1)
ret = s.rescue(image=1)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'rescue': {'rescue_image_ref': 1}})
resp, ret = self.cs.servers.rescue(s, image=1)
ret = self.cs.servers.rescue(s, image=1)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'rescue': {'rescue_image_ref': 1}})
@ -768,18 +768,18 @@ class ServersTest(utils.FixturedTestCase):
def test_get_server_diagnostics(self):
s = self.cs.servers.get(1234)
resp, diagnostics = s.diagnostics()
diagnostics = s.diagnostics()
self.assert_request_id(diagnostics, fakes.FAKE_REQUEST_ID_LIST)
self.assertIsNotNone(diagnostics)
self.assert_called('GET', '/servers/1234/diagnostics')
resp, diagnostics_from_manager = self.cs.servers.diagnostics(1234)
diagnostics_from_manager = self.cs.servers.diagnostics(1234)
self.assert_request_id(diagnostics_from_manager,
fakes.FAKE_REQUEST_ID_LIST)
self.assertIsNotNone(diagnostics_from_manager)
self.assert_called('GET', '/servers/1234/diagnostics')
self.assertEqual(diagnostics, diagnostics_from_manager)
self.assertEqual(diagnostics[1], diagnostics_from_manager[1])
def test_get_vnc_console(self):
s = self.cs.servers.get(1234)
@ -892,11 +892,11 @@ class ServersTest(utils.FixturedTestCase):
def test_evacuate(self):
s = self.cs.servers.get(1234)
resp, ret = s.evacuate('fake_target_host', 'True')
ret = s.evacuate('fake_target_host', 'True')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')
resp, ret = self.cs.servers.evacuate(s, 'fake_target_host',
'False', 'NewAdminPassword')
ret = self.cs.servers.evacuate(s, 'fake_target_host',
'False', 'NewAdminPassword')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action')

View File

@ -74,13 +74,11 @@ class HostManager(base.ManagerWithFind):
:param host: The host to perform an action
:param actiob: The action to perform
:returns: A Response object and an instance of
novaclient.base.DictWithMeta
returns: An instance of novaclient.base.TupleWithMeta
"""
url = '/os-hosts/{0}/{1}'.format(host, action)
resp, body = self.api.client.get(url)
# For compatibility, return Response object as a first return value
return resp, self.convert_into_with_meta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def list(self, zone=None):
url = '/os-hosts'

View File

@ -157,8 +157,7 @@ class Server(base.Resource):
"""
Stop -- Stop the running server.
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
return self.manager.stop(self)
@ -166,8 +165,7 @@ class Server(base.Resource):
"""
Force delete -- Force delete a server.
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
return self.manager.force_delete(self)
@ -175,8 +173,7 @@ class Server(base.Resource):
"""
Restore -- Restore a server in 'soft-deleted' state.
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
return self.manager.restore(self)
@ -242,8 +239,7 @@ class Server(base.Resource):
:param password: The admin password to be set in the rescue instance.
:param image: The :class:`Image` to rescue with.
:returns: A Response object and an instance of
novaclient.base.DictWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
return self.manager.rescue(self, password, image)
@ -462,8 +458,7 @@ class Server(base.Resource):
parameter must have its default value of None.
:param password: string to set as admin password on the evacuated
server.
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
if api_versions.APIVersion("2.14") <= self.manager.api_version:
if on_shared_storage is not None:
@ -938,34 +933,31 @@ class ServerManager(base.BootingManagerWithFind):
Stop the server.
:param server: The :class:`Server` (or its ID) to stop
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
resp, body = self._action_return_resp_and_body('os-stop', server, None)
return resp, self.convert_into_with_meta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def force_delete(self, server):
"""
Force delete the server.
:param server: The :class:`Server` (or its ID) to force delete
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
resp, body = self._action_return_resp_and_body('forceDelete', server,
None)
return resp, self.convert_into_with_meta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def restore(self, server):
"""
Restore soft-deleted server.
:param server: The :class:`Server` (or its ID) to restore
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
resp, body = self._action_return_resp_and_body('restore', server, None)
return resp, self.convert_into_with_meta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def start(self, server):
"""
@ -1037,8 +1029,7 @@ class ServerManager(base.BootingManagerWithFind):
:param server: The :class:`Server` to rescue.
:param password: The admin password to be set in the rescue instance.
:param image: The :class:`Image` to rescue with.
:returns: A Response object and an instance of
novaclient.base.DictWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
info = {}
if password:
@ -1047,8 +1038,7 @@ class ServerManager(base.BootingManagerWithFind):
info['rescue_image_ref'] = base.getid(image)
resp, body = self._action_return_resp_and_body('rescue', server,
info or None)
# For compatibility, return Response object as a first return value
return resp, base.DictWithMeta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def unrescue(self, server):
"""
@ -1106,13 +1096,11 @@ class ServerManager(base.BootingManagerWithFind):
:param server: The :class:`Server` (or its ID) for which
diagnostics to be returned
:returns: A Respose object and an instance of
novaclient.base.DictWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
resp, body = self.api.client.get("/servers/%s/diagnostics" %
base.getid(server))
# For compatibility, return Response object as a first return value
return resp, base.DictWithMeta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def create(self, name, image, flavor, meta=None, files=None,
reservation_id=None, min_count=None,
@ -1515,8 +1503,7 @@ class ServerManager(base.BootingManagerWithFind):
:param on_shared_storage: Specifies whether instance files located
on shared storage
:param password: string to set as password on the evacuated server.
:returns: A Response object and an instance of
novaclient.base.TupleWithMeta
:returns: An instance of novaclient.base.TupleWithMeta
"""
body = {'onSharedStorage': on_shared_storage}
@ -1528,7 +1515,7 @@ class ServerManager(base.BootingManagerWithFind):
resp, body = self._action_return_resp_and_body('evacuate', server,
body)
return resp, self.convert_into_with_meta(body, resp)
return base.TupleWithMeta((resp, body), resp)
@api_versions.wraps("2.14")
def evacuate(self, server, host=None, password=None):
@ -1538,6 +1525,7 @@ class ServerManager(base.BootingManagerWithFind):
:param server: The :class:`Server` (or its ID) to share onto.
:param host: Name of the target host.
:param password: string to set as password on the evacuated server.
:returns: An instance of novaclient.base.TupleWithMeta
"""
body = {}
@ -1549,7 +1537,7 @@ class ServerManager(base.BootingManagerWithFind):
resp, body = self._action_return_resp_and_body('evacuate', server,
body)
return resp, self.convert_into_with_meta(body, resp)
return base.TupleWithMeta((resp, body), resp)
def interface_list(self, server):
"""