From f9aa277c62a05648e030dfeaf21d653ec6a388f3 Mon Sep 17 00:00:00 2001 From: Takashi NATSUME Date: Fri, 25 Dec 2015 11:40:22 +0900 Subject: [PATCH] Add return-request-id-to-caller function(1/5) Add return-request-id-to-caller function to 'Server' resource and 'ServerManager'. The methods in the resource class and resource manager return a wrapper class that has 'request_ids' property. The caller can get request ids of the callee via the property. * novaclient/v2/servers.py Co-authored-by: Ankit Agrawal Change-Id: I8c2d3abcebba7823f42e2f27356e73bc6d7ade42 Implements: blueprint return-request-id-to-caller --- novaclient/tests/unit/fixture_data/base.py | 5 +- novaclient/tests/unit/fixture_data/servers.py | 21 +- novaclient/tests/unit/utils.py | 3 + novaclient/tests/unit/v2/fakes.py | 4 +- novaclient/tests/unit/v2/test_servers.py | 361 ++++++++++----- novaclient/v2/servers.py | 417 +++++++++++++----- 6 files changed, 581 insertions(+), 230 deletions(-) diff --git a/novaclient/tests/unit/fixture_data/base.py b/novaclient/tests/unit/fixture_data/base.py index 6a2e238b5..899a60929 100644 --- a/novaclient/tests/unit/fixture_data/base.py +++ b/novaclient/tests/unit/fixture_data/base.py @@ -13,13 +13,16 @@ import fixtures from six.moves.urllib import parse +from novaclient.tests.unit.v2 import fakes + COMPUTE_URL = 'http://compute.host' class Fixture(fixtures.Fixture): base_url = None - json_headers = {'Content-Type': 'application/json'} + json_headers = {'Content-Type': 'application/json', + 'x-openstack-request-id': fakes.FAKE_REQUEST_ID} def __init__(self, requests, compute_url=COMPUTE_URL): super(Fixture, self).__init__() diff --git a/novaclient/tests/unit/fixture_data/servers.py b/novaclient/tests/unit/fixture_data/servers.py index 4aff762a6..4d2df95b3 100644 --- a/novaclient/tests/unit/fixture_data/servers.py +++ b/novaclient/tests/unit/fixture_data/servers.py @@ -180,12 +180,14 @@ class Base(base.Fixture): headers=self.json_headers) for s in (1234, 5678): - self.requests.register_uri('DELETE', self.url(s), status_code=202) + self.requests.register_uri('DELETE', self.url(s), status_code=202, + headers=self.json_headers) for k in ('test_key', 'key1', 'key2'): self.requests.register_uri('DELETE', self.url(1234, 'metadata', k), - status_code=204) + status_code=204, + headers=self.json_headers) metadata1 = {'metadata': {'test_key': 'test_value'}} self.requests.register_uri('POST', self.url(1234, 'metadata'), @@ -218,7 +220,8 @@ class Base(base.Fixture): self.requests.register_uri('GET', self.url('1234', 'os-security-groups'), - json=get_security_groups) + json=get_security_groups, + headers=self.json_headers) self.requests.register_uri('POST', self.url(), json=self.post_servers, @@ -311,7 +314,8 @@ class Base(base.Fixture): self.requests.register_uri('DELETE', self.url(1234, 'os-server-password'), - status_code=202) + status_code=202, + headers=self.json_headers) class V1(Base): @@ -342,10 +346,12 @@ class V1(Base): self.requests.register_uri('GET', self.url('1234', 'diagnostics'), - json=self.diagnostic) + json=self.diagnostic, + headers=self.json_headers) self.requests.register_uri('DELETE', - self.url('1234', 'os-interface', 'port-id')) + self.url('1234', 'os-interface', 'port-id'), + headers=self.json_headers) # Testing with the following password and key # @@ -371,7 +377,8 @@ class V1(Base): 'Hi/fmZZNQQqj1Ijq0caOIw=='} self.requests.register_uri('GET', self.url(1234, 'os-server-password'), - json=get_server_password) + json=get_server_password, + headers=self.json_headers) def post_servers(self, request, context): body = jsonutils.loads(request.body) diff --git a/novaclient/tests/unit/utils.py b/novaclient/tests/unit/utils.py index 4c5ec4932..c4fd70f56 100644 --- a/novaclient/tests/unit/utils.py +++ b/novaclient/tests/unit/utils.py @@ -66,6 +66,9 @@ class TestCase(testtools.TestCase): stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) + def assert_request_id(self, request_id_mixin, request_id_list): + self.assertEqual(request_id_list, request_id_mixin.request_ids) + class FixturedTestCase(testscenarios.TestWithScenarios, TestCase): diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py index 149835b06..ceb6672ec 100644 --- a/novaclient/tests/unit/v2/fakes.py +++ b/novaclient/tests/unit/v2/fakes.py @@ -48,6 +48,7 @@ FAKE_IMAGE_UUID_2 = 'f27f479a-ddda-419a-9bbc-d6b56b210161' # fake request id FAKE_REQUEST_ID = fakes.FAKE_REQUEST_ID FAKE_REQUEST_ID_LIST = fakes.FAKE_REQUEST_ID_LIST +FAKE_RESPONSE_HEADERS = {'x-openstack-request-id': FAKE_REQUEST_ID} class FakeClient(fakes.FakeClient, client.Client): @@ -724,7 +725,7 @@ class FakeHTTPClient(base_client.HTTPClient): return True def post_servers_1234_action(self, body, **kw): - _headers = None + _headers = dict() _body = None resp = 202 assert len(body.keys()) == 1 @@ -770,6 +771,7 @@ class FakeHTTPClient(base_client.HTTPClient): assert set(keys) == set(['onSharedStorage']) else: raise AssertionError("Unexpected server action: %s" % action) + _headers.update(FAKE_RESPONSE_HEADERS) return (resp, _headers, _body) def post_servers_5678_action(self, body, **kw): diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py index 8fb3c6079..171a5dbc3 100644 --- a/novaclient/tests/unit/v2/test_servers.py +++ b/novaclient/tests/unit/v2/test_servers.py @@ -26,6 +26,7 @@ from novaclient.tests.unit.fixture_data import client from novaclient.tests.unit.fixture_data import floatingips from novaclient.tests.unit.fixture_data import servers as data from novaclient.tests.unit import utils +from novaclient.tests.unit.v2 import fakes from novaclient.v2 import servers @@ -40,12 +41,14 @@ class ServersTest(utils.FixturedTestCase): def test_list_servers(self): sl = self.cs.servers.list() + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/detail') for s in sl: self.assertIsInstance(s, servers.Server) def test_filter_servers_unicode(self): sl = self.cs.servers.list(search_opts={'name': u't€sting'}) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/detail?name=t%E2%82%ACsting') for s in sl: self.assertIsInstance(s, servers.Server) @@ -53,6 +56,7 @@ class ServersTest(utils.FixturedTestCase): def test_list_all_servers(self): # use marker just to identify this call in fixtures sl = self.cs.servers.list(limit=-1, marker=1234) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual(2, len(sl)) @@ -66,12 +70,14 @@ class ServersTest(utils.FixturedTestCase): def test_list_servers_undetailed(self): sl = self.cs.servers.list(detailed=False) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers') for s in sl: self.assertIsInstance(s, servers.Server) def test_list_servers_with_marker_limit(self): sl = self.cs.servers.list(marker=1234, limit=2) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/detail?limit=2&marker=1234') for s in sl: self.assertIsInstance(s, servers.Server) @@ -79,6 +85,7 @@ class ServersTest(utils.FixturedTestCase): def test_list_servers_sort_single(self): sl = self.cs.servers.list(sort_keys=['display_name'], sort_dirs=['asc']) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assert_called( 'GET', '/servers/detail?sort_dir=asc&sort_key=display_name') @@ -88,6 +95,7 @@ class ServersTest(utils.FixturedTestCase): def test_list_servers_sort_multiple(self): sl = self.cs.servers.list(sort_keys=['display_name', 'id'], sort_dirs=['asc', 'desc']) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assert_called( 'GET', ('/servers/detail?sort_dir=asc&sort_dir=desc&' @@ -97,6 +105,7 @@ class ServersTest(utils.FixturedTestCase): def test_get_server_details(self): s = self.cs.servers.get(1234) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/1234') self.assertIsInstance(s, servers.Server) self.assertEqual(1234, s.id) @@ -122,6 +131,7 @@ class ServersTest(utils.FixturedTestCase): '/tmp/foo.txt': six.StringIO('data'), # a stream } ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -152,6 +162,7 @@ class ServersTest(utils.FixturedTestCase): block_device_mapping=bdm, nics=nics ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/os-volumes_boot') self.assertIsInstance(s, servers.Server) @@ -179,6 +190,7 @@ class ServersTest(utils.FixturedTestCase): key_name="fakekey", block_device_mapping_v2=bdm ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/os-volumes_boot') self.assertIsInstance(s, servers.Server) @@ -201,6 +213,7 @@ class ServersTest(utils.FixturedTestCase): key_name="fakekey", nics=nics ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -225,6 +238,7 @@ class ServersTest(utils.FixturedTestCase): access_ip_v6=access_ip_v6, access_ip_v4=access_ip_v4 ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -240,6 +254,7 @@ class ServersTest(utils.FixturedTestCase): '/tmp/foo.txt': six.StringIO('data'), # a stream }, ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -256,6 +271,7 @@ class ServersTest(utils.FixturedTestCase): '/tmp/foo.txt': six.StringIO('data'), # a stream }, ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -272,6 +288,7 @@ class ServersTest(utils.FixturedTestCase): '/tmp/foo.txt': six.StringIO('data'), # a stream }, ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -285,6 +302,7 @@ class ServersTest(utils.FixturedTestCase): admin_pass=test_password, key_name=test_key ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) body = jsonutils.loads(self.requests.last_request.body) @@ -308,6 +326,7 @@ class ServersTest(utils.FixturedTestCase): '/tmp/foo.txt': six.StringIO('data'), # a stream }, ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) # verify userdata matches original @@ -323,6 +342,7 @@ class ServersTest(utils.FixturedTestCase): flavor=1, disk_config=disk_config ) + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers') self.assertIsInstance(s, servers.Server) @@ -343,8 +363,10 @@ class ServersTest(utils.FixturedTestCase): # Update via instance s.update(name='hi') + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('PUT', '/servers/1234') s.update(name='hi') + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('PUT', '/servers/1234') # Silly, but not an error @@ -352,33 +374,41 @@ class ServersTest(utils.FixturedTestCase): # Update via manager self.cs.servers.update(s, name='hi') + self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('PUT', '/servers/1234') def test_delete_server(self): s = self.cs.servers.get(1234) - s.delete() + ret = s.delete() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(1234) + ret = self.cs.servers.delete(1234) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(s) + ret = self.cs.servers.delete(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('DELETE', '/servers/1234') def test_delete_server_meta(self): - self.cs.servers.delete_meta(1234, ['test_key']) + ret = self.cs.servers.delete_meta(1234, ['test_key']) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('DELETE', '/servers/1234/metadata/test_key') def test_set_server_meta(self): - self.cs.servers.set_meta(1234, {'test_key': 'test_value'}) + m = self.cs.servers.set_meta(1234, {'test_key': 'test_value'}) + self.assert_request_id(m, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/metadata', {'metadata': {'test_key': 'test_value'}}) def test_set_server_meta_item(self): - self.cs.servers.set_meta_item(1234, 'test_key', 'test_value') + m = self.cs.servers.set_meta_item(1234, 'test_key', 'test_value') + self.assert_request_id(m, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('PUT', '/servers/1234/metadata/test_key', {'meta': {'test_key': 'test_value'}}) def test_find(self): server = self.cs.servers.find(name='sample-server') + self.assert_request_id(server, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/1234') self.assertEqual('sample-server', server.name) @@ -386,33 +416,41 @@ class ServersTest(utils.FixturedTestCase): flavor={"id": 1, "name": "256 MB Server"}) sl = self.cs.servers.findall(flavor={"id": 1, "name": "256 MB Server"}) + self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual([1234, 5678, 9012], [s.id for s in sl]) def test_reboot_server(self): s = self.cs.servers.get(1234) - s.reboot() + ret = s.reboot() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reboot(s, reboot_type='HARD') + ret = self.cs.servers.reboot(s, reboot_type='HARD') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_rebuild_server(self): s = self.cs.servers.get(1234) - s.rebuild(image=1) + ret = s.rebuild(image=1) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1) + ret = self.cs.servers.rebuild(s, image=1) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - s.rebuild(image=1, password='5678') + ret = s.rebuild(image=1, password='5678') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1, password='5678') + ret = self.cs.servers.rebuild(s, image=1, password='5678') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def _rebuild_resize_disk_config(self, disk_config, operation="rebuild"): s = self.cs.servers.get(1234) if operation == "rebuild": - s.rebuild(image=1, disk_config=disk_config) + ret = s.rebuild(image=1, disk_config=disk_config) elif operation == "resize": - s.resize(flavor=1, disk_config=disk_config) + ret = s.resize(flavor=1, disk_config=disk_config) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') # verify disk config param was used in the request: @@ -430,7 +468,8 @@ class ServersTest(utils.FixturedTestCase): def test_rebuild_server_preserve_ephemeral(self): s = self.cs.servers.get(1234) - s.rebuild(image=1, preserve_ephemeral=True) + ret = s.rebuild(image=1, preserve_ephemeral=True) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') body = jsonutils.loads(self.requests.last_request.body) d = body['rebuild'] @@ -440,7 +479,8 @@ class ServersTest(utils.FixturedTestCase): def test_rebuild_server_name_meta_files(self): files = {'/etc/passwd': 'some data'} s = self.cs.servers.get(1234) - s.rebuild(image=1, name='new', meta={'foo': 'bar'}, files=files) + ret = s.rebuild(image=1, name='new', meta={'foo': 'bar'}, files=files) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) body = jsonutils.loads(self.requests.last_request.body) d = body['rebuild'] self.assertEqual('new', d['name']) @@ -450,7 +490,8 @@ class ServersTest(utils.FixturedTestCase): def test_resize_server(self): s = self.cs.servers.get(1234) - s.resize(flavor=1) + ret = s.resize(flavor=1) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') self.cs.servers.resize(s, flavor=1) self.assert_called('POST', '/servers/1234/action') @@ -463,165 +504,210 @@ class ServersTest(utils.FixturedTestCase): def test_confirm_resized_server(self): s = self.cs.servers.get(1234) - s.confirm_resize() + ret = s.confirm_resize() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') self.cs.servers.confirm_resize(s) self.assert_called('POST', '/servers/1234/action') def test_revert_resized_server(self): s = self.cs.servers.get(1234) - s.revert_resize() + ret = s.revert_resize() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.revert_resize(s) + ret = self.cs.servers.revert_resize(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_migrate_server(self): s = self.cs.servers.get(1234) - s.migrate() + ret = s.migrate() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.migrate(s) + ret = self.cs.servers.migrate(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_add_fixed_ip(self): s = self.cs.servers.get(1234) - s.add_fixed_ip(1) + fip = s.add_fixed_ip(1) + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_fixed_ip(s, 1) + fip = self.cs.servers.add_fixed_ip(s, 1) + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_remove_fixed_ip(self): s = self.cs.servers.get(1234) - s.remove_fixed_ip('10.0.0.1') + ret = s.remove_fixed_ip('10.0.0.1') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_fixed_ip(s, '10.0.0.1') + ret = self.cs.servers.remove_fixed_ip(s, '10.0.0.1') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_add_floating_ip(self): s = self.cs.servers.get(1234) - s.add_floating_ip('11.0.0.1') + fip = s.add_floating_ip('11.0.0.1') + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_floating_ip(s, '11.0.0.1') + fip = self.cs.servers.add_floating_ip(s, '11.0.0.1') + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') f = self.cs.floating_ips.list()[0] - self.cs.servers.add_floating_ip(s, f) + fip = self.cs.servers.add_floating_ip(s, f) + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - s.add_floating_ip(f) + fip = s.add_floating_ip(f) + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_add_floating_ip_to_fixed(self): s = self.cs.servers.get(1234) - s.add_floating_ip('11.0.0.1', fixed_address='12.0.0.1') + fip = s.add_floating_ip('11.0.0.1', fixed_address='12.0.0.1') + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_floating_ip(s, '11.0.0.1', - fixed_address='12.0.0.1') + fip = self.cs.servers.add_floating_ip(s, '11.0.0.1', + fixed_address='12.0.0.1') + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') f = self.cs.floating_ips.list()[0] - self.cs.servers.add_floating_ip(s, f) + fip = self.cs.servers.add_floating_ip(s, f) + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - s.add_floating_ip(f) + fip = s.add_floating_ip(f) + self.assert_request_id(fip, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_remove_floating_ip(self): s = self.cs.servers.get(1234) - s.remove_floating_ip('11.0.0.1') + ret = s.remove_floating_ip('11.0.0.1') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_floating_ip(s, '11.0.0.1') + ret = self.cs.servers.remove_floating_ip(s, '11.0.0.1') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') f = self.cs.floating_ips.list()[0] - self.cs.servers.remove_floating_ip(s, f) + ret = self.cs.servers.remove_floating_ip(s, f) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - s.remove_floating_ip(f) + ret = s.remove_floating_ip(f) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_stop(self): s = self.cs.servers.get(1234) - s.stop() + resp, ret = s.stop() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.stop(s) + resp, 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) - s.force_delete() + resp, ret = s.force_delete() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.force_delete(s) + resp, 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) - s.restore() + resp, ret = s.restore() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.restore(s) + resp, ret = self.cs.servers.restore(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_start(self): s = self.cs.servers.get(1234) - s.start() + ret = s.start() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.start(s) + ret = self.cs.servers.start(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_rescue(self): s = self.cs.servers.get(1234) - s.rescue() + resp, ret = s.rescue() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rescue(s) + resp, 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) - s.rescue(password='asdf') + resp, 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'}}) - self.cs.servers.rescue(s, password='asdf') + resp, 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) - s.rescue(image=1) + resp, 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}}) - self.cs.servers.rescue(s, image=1) + resp, 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}}) def test_unrescue(self): s = self.cs.servers.get(1234) - s.unrescue() + ret = s.unrescue() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unrescue(s) + ret = self.cs.servers.unrescue(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_lock(self): s = self.cs.servers.get(1234) - s.lock() + ret = s.lock() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.lock(s) + ret = self.cs.servers.lock(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_unlock(self): s = self.cs.servers.get(1234) - s.unlock() + ret = s.unlock() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unlock(s) + ret = self.cs.servers.unlock(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_backup(self): s = self.cs.servers.get(1234) - s.backup('back1', 'daily', 1) + sb = s.backup('back1', 'daily', 1) + self.assert_request_id(sb, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.backup(s, 'back1', 'daily', 2) + sb = self.cs.servers.backup(s, 'back1', 'daily', 2) + self.assert_request_id(sb, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_get_console_output_without_length(self): success = 'foo' s = self.cs.servers.get(1234) - s.get_console_output() + co = s.get_console_output() + self.assert_request_id(co, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual(success, s.get_console_output()) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.get_console_output(s) + co = self.cs.servers.get_console_output(s) + self.assert_request_id(co, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual(success, self.cs.servers.get_console_output(s)) self.assert_called('POST', '/servers/1234/action') @@ -629,11 +715,13 @@ class ServersTest(utils.FixturedTestCase): success = 'foo' s = self.cs.servers.get(1234) - s.get_console_output(length=50) + co = s.get_console_output(length=50) + self.assert_request_id(co, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual(success, s.get_console_output(length=50)) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.get_console_output(s, length=50) + co = self.cs.servers.get_console_output(s, length=50) + self.assert_request_id(co, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual(success, self.cs.servers.get_console_output(s, length=50)) self.assert_called('POST', '/servers/1234/action') @@ -654,133 +742,168 @@ class ServersTest(utils.FixturedTestCase): def test_get_password(self): s = self.cs.servers.get(1234) - self.assertEqual(b'FooBar123', - s.get_password('novaclient/tests/unit/idfake.pem')) + password = s.get_password('novaclient/tests/unit/idfake.pem') + self.assert_request_id(password, fakes.FAKE_REQUEST_ID_LIST) + self.assertEqual(b'FooBar123', password) self.assert_called('GET', '/servers/1234/os-server-password') def test_get_password_without_key(self): s = self.cs.servers.get(1234) + password = s.get_password() + self.assert_request_id(password, fakes.FAKE_REQUEST_ID_LIST) self.assertEqual( 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw==', s.get_password()) + 'Hi/fmZZNQQqj1Ijq0caOIw==', password) self.assert_called('GET', '/servers/1234/os-server-password') def test_clear_password(self): s = self.cs.servers.get(1234) - s.clear_password() + ret = s.clear_password() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('DELETE', '/servers/1234/os-server-password') def test_get_server_diagnostics(self): s = self.cs.servers.get(1234) - diagnostics = s.diagnostics() + resp, diagnostics = s.diagnostics() + self.assert_request_id(diagnostics, fakes.FAKE_REQUEST_ID_LIST) self.assertIsNotNone(diagnostics) self.assert_called('GET', '/servers/1234/diagnostics') - diagnostics_from_manager = self.cs.servers.diagnostics(1234) + resp, 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[1], diagnostics_from_manager[1]) + self.assertEqual(diagnostics, diagnostics_from_manager) def test_get_vnc_console(self): s = self.cs.servers.get(1234) - s.get_vnc_console('fake') + vc = s.get_vnc_console('fake') + self.assert_request_id(vc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.get_vnc_console(s, 'fake') + vc = self.cs.servers.get_vnc_console(s, 'fake') + self.assert_request_id(vc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_get_spice_console(self): s = self.cs.servers.get(1234) - s.get_spice_console('fake') + sc = s.get_spice_console('fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.get_spice_console(s, 'fake') + sc = self.cs.servers.get_spice_console(s, 'fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_get_serial_console(self): s = self.cs.servers.get(1234) - s.get_serial_console('fake') + sc = s.get_serial_console('fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.get_serial_console(s, 'fake') + sc = self.cs.servers.get_serial_console(s, 'fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_get_rdp_console(self): s = self.cs.servers.get(1234) - s.get_rdp_console('fake') + rc = s.get_rdp_console('fake') + self.assert_request_id(rc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.get_rdp_console(s, 'fake') + rc = self.cs.servers.get_rdp_console(s, 'fake') + self.assert_request_id(rc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_create_image(self): s = self.cs.servers.get(1234) - s.create_image('123') + im = s.create_image('123') + self.assert_request_id(im, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - s.create_image('123', {}) + im = s.create_image('123', {}) + self.assert_request_id(im, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123') + im = self.cs.servers.create_image(s, '123') + self.assert_request_id(im, fakes.FAKE_REQUEST_ID_LIST) + self.assert_called('POST', '/servers/1234/action') + im = self.cs.servers.create_image(s, '123', {}) + self.assert_request_id(im, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123', {}) def test_live_migrate_server(self): s = self.cs.servers.get(1234) - s.live_migrate(host='hostname', block_migration=False, - disk_over_commit=False) + ret = s.live_migrate(host='hostname', block_migration=False, + disk_over_commit=False) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.live_migrate(s, host='hostname', block_migration=False, - disk_over_commit=False) + ret = self.cs.servers.live_migrate(s, host='hostname', + block_migration=False, + disk_over_commit=False) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_reset_state(self): s = self.cs.servers.get(1234) - s.reset_state('newstate') + ret = s.reset_state('newstate') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_state(s, 'newstate') + ret = self.cs.servers.reset_state(s, 'newstate') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_reset_network(self): s = self.cs.servers.get(1234) - s.reset_network() + ret = s.reset_network() + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_network(s) + ret = self.cs.servers.reset_network(s) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_add_security_group(self): s = self.cs.servers.get(1234) - s.add_security_group('newsg') + sg = s.add_security_group('newsg') + self.assert_request_id(sg, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_security_group(s, 'newsg') + sg = self.cs.servers.add_security_group(s, 'newsg') + self.assert_request_id(sg, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_remove_security_group(self): s = self.cs.servers.get(1234) - s.remove_security_group('oldsg') + ret = s.remove_security_group('oldsg') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_security_group(s, 'oldsg') + ret = self.cs.servers.remove_security_group(s, 'oldsg') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') def test_list_security_group(self): s = self.cs.servers.get(1234) - s.list_security_group() + sgs = s.list_security_group() + self.assert_request_id(sgs, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/1234/os-security-groups') def test_evacuate(self): s = self.cs.servers.get(1234) - s.evacuate('fake_target_host', 'True') + resp, ret = s.evacuate('fake_target_host', 'True') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/action') - self.cs.servers.evacuate(s, 'fake_target_host', - 'False', 'NewAdminPassword') + resp, 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') def test_interface_list(self): s = self.cs.servers.get(1234) - s.interface_list() + il = s.interface_list() + self.assert_request_id(il, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('GET', '/servers/1234/os-interface') def test_interface_list_result_string_representable(self): @@ -812,12 +935,14 @@ class ServersTest(utils.FixturedTestCase): def test_interface_attach(self): s = self.cs.servers.get(1234) - s.interface_attach(None, None, None) + ret = s.interface_attach(None, None, None) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/os-interface') def test_interface_detach(self): s = self.cs.servers.get(1234) - s.interface_detach('port-id') + ret = s.interface_detach('port-id') + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('DELETE', '/servers/1234/os-interface/port-id') @@ -828,34 +953,42 @@ class ServersV26Test(ServersTest): def test_get_vnc_console(self): s = self.cs.servers.get(1234) - s.get_vnc_console('fake') + vc = s.get_vnc_console('fake') + self.assert_request_id(vc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') - self.cs.servers.get_vnc_console(s, 'fake') + vc = self.cs.servers.get_vnc_console(s, 'fake') + self.assert_request_id(vc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') def test_get_spice_console(self): s = self.cs.servers.get(1234) - s.get_spice_console('fake') + sc = s.get_spice_console('fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') - self.cs.servers.get_spice_console(s, 'fake') + sc = self.cs.servers.get_spice_console(s, 'fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') def test_get_serial_console(self): s = self.cs.servers.get(1234) - s.get_serial_console('fake') + sc = s.get_serial_console('fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') - self.cs.servers.get_serial_console(s, 'fake') + sc = self.cs.servers.get_serial_console(s, 'fake') + self.assert_request_id(sc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') def test_get_rdp_console(self): s = self.cs.servers.get(1234) - s.get_rdp_console('fake') + rc = s.get_rdp_console('fake') + self.assert_request_id(rc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') - self.cs.servers.get_rdp_console(s, 'fake') + rc = self.cs.servers.get_rdp_console(s, 'fake') + self.assert_request_id(rc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') @@ -866,10 +999,12 @@ class ServersV28Test(ServersV26Test): def test_get_mks_console(self): s = self.cs.servers.get(1234) - s.get_mks_console() + mksc = s.get_mks_console() + self.assert_request_id(mksc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') - self.cs.servers.get_mks_console(s) + mksc = self.cs.servers.get_mks_console(s) + self.assert_request_id(mksc, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/remote-consoles') diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py index cd2d2f4b5..7120df1ab 100644 --- a/novaclient/v2/servers.py +++ b/novaclient/v2/servers.py @@ -44,16 +44,19 @@ class Server(base.Resource): def delete(self): """ Delete (i.e. shut down and delete the image) this server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.delete(self) + return self.manager.delete(self) def update(self, name=None): """ Update the name for this server. :param name: Update the server's name. + :returns: :class:`Server` """ - self.manager.update(self, name=name) + return self.manager.update(self, name=name) def get_console_output(self, length=None): """ @@ -126,8 +129,9 @@ class Server(base.Resource): Add an IP address on a network. :param network_id: The ID of the network the IP should be on. + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.add_fixed_ip(self, network_id) + return self.manager.add_fixed_ip(self, network_id) def add_floating_ip(self, address, fixed_address=None): """ @@ -136,76 +140,101 @@ class Server(base.Resource): :param address: The IP address or FloatingIP to add to the instance :param fixed_address: The fixedIP address the FloatingIP is to be associated with (optional) + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.add_floating_ip(self, address, fixed_address) + return self.manager.add_floating_ip(self, address, fixed_address) def remove_floating_ip(self, address): """ Remove floating IP from an instance :param address: The IP address or FloatingIP to remove + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.remove_floating_ip(self, address) + return self.manager.remove_floating_ip(self, address) def stop(self): """ Stop -- Stop the running server. + + :returns: A Response object and an instance of + novaclient.base.TupleWithMeta """ - self.manager.stop(self) + return self.manager.stop(self) def force_delete(self): """ Force delete -- Force delete a server. + + :returns: A Response object and an instance of + novaclient.base.TupleWithMeta """ - self.manager.force_delete(self) + return self.manager.force_delete(self) def restore(self): """ Restore -- Restore a server in 'soft-deleted' state. + + :returns: A Response object and an instance of + novaclient.base.TupleWithMeta """ - self.manager.restore(self) + return self.manager.restore(self) def start(self): """ Start -- Start the paused server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.start(self) + return self.manager.start(self) def pause(self): """ Pause -- Pause the running server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.pause(self) + return self.manager.pause(self) def unpause(self): """ Unpause -- Unpause the paused server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.unpause(self) + return self.manager.unpause(self) def lock(self): """ Lock -- Lock the instance from certain operations. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.lock(self) + return self.manager.lock(self) def unlock(self): """ Unlock -- Remove instance lock. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.unlock(self) + return self.manager.unlock(self) def suspend(self): """ Suspend -- Suspend the running server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.suspend(self) + return self.manager.suspend(self) def resume(self): """ Resume -- Resume the suspended server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.resume(self) + return self.manager.resume(self) def rescue(self, password=None, image=None): """ @@ -213,32 +242,42 @@ 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 """ return self.manager.rescue(self, password, image) def unrescue(self): """ Unrescue -- Unrescue the rescued server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.unrescue(self) + return self.manager.unrescue(self) def shelve(self): """ Shelve -- Shelve the server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.shelve(self) + return self.manager.shelve(self) def shelve_offload(self): """ Shelve_offload -- Remove a shelved server from the compute node. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.shelve_offload(self) + return self.manager.shelve_offload(self) def unshelve(self): """ Unshelve -- Unshelve the server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.unshelve(self) + return self.manager.unshelve(self) def diagnostics(self): """Diagnostics -- Retrieve server diagnostics.""" @@ -247,24 +286,28 @@ class Server(base.Resource): def migrate(self): """ Migrate a server to a new host. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.migrate(self) + return self.manager.migrate(self) def remove_fixed_ip(self, address): """ Remove an IP address. :param address: The IP address to remove. + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.remove_fixed_ip(self, address) + return self.manager.remove_fixed_ip(self, address) def change_password(self, password): """ Update the admin password for a server. :param password: string to set as the admin password on the server + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.change_password(self, password) + return self.manager.change_password(self, password) def reboot(self, reboot_type=REBOOT_SOFT): """ @@ -272,8 +315,9 @@ class Server(base.Resource): :param reboot_type: either :data:`REBOOT_SOFT` for a software-level reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.reboot(self, reboot_type) + return self.manager.reboot(self, reboot_type) def rebuild(self, image, password=None, preserve_ephemeral=False, **kwargs): @@ -295,13 +339,14 @@ class Server(base.Resource): Resize the server's resources. :param flavor: the :class:`Flavor` (or its ID) to resize to. + :returns: An instance of novaclient.base.TupleWithMeta Until a resize event is confirmed with :meth:`confirm_resize`, the old server will be kept around and you'll be able to roll back to the old flavor quickly with :meth:`revert_resize`. All resizes are automatically confirmed after 24 hours. """ - self.manager.resize(self, flavor, **kwargs) + return self.manager.resize(self, flavor, **kwargs) def create_image(self, image_name, metadata=None): """ @@ -320,20 +365,25 @@ class Server(base.Resource): :param backup_type: The backup type, like 'daily' or 'weekly' :param rotation: Int parameter representing how many backups to keep around. + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.backup(self, backup_name, backup_type, rotation) + return self.manager.backup(self, backup_name, backup_type, rotation) def confirm_resize(self): """ Confirm that the resize worked, thus removing the original server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.confirm_resize(self) + return self.manager.confirm_resize(self) def revert_resize(self): """ Revert a previous resize, switching back to the old server. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.revert_resize(self) + return self.manager.revert_resize(self) @property def networks(self): @@ -353,34 +403,48 @@ class Server(base.Resource): disk_over_commit=False): """ Migrates a running instance to a new machine. + + :param host: destination host name. + :param block_migration: if True, do block_migration. + :param disk_over_commit: if True, Allow overcommit. + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.live_migrate(self, host, - block_migration, - disk_over_commit) + return self.manager.live_migrate(self, host, + block_migration, + disk_over_commit) def reset_state(self, state='error'): """ Reset the state of an instance to active or error. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.reset_state(self, state) + return self.manager.reset_state(self, state) def reset_network(self): """ Reset network of an instance. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.reset_network(self) + return self.manager.reset_network(self) def add_security_group(self, security_group): """ Add a security group to an instance. + + :param security_group: The name of security group to add + :returns: An instance of novaclient.base.DictWithMeta """ - self.manager.add_security_group(self, security_group) + return self.manager.add_security_group(self, security_group) def remove_security_group(self, security_group): """ Remove a security group from an instance. + + :returns: An instance of novaclient.base.TupleWithMeta """ - self.manager.remove_security_group(self, security_group) + return self.manager.remove_security_group(self, security_group) def list_security_group(self): """ @@ -398,6 +462,8 @@ 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 """ if api_versions.APIVersion("2.14") <= self.manager.api_version: if on_shared_storage is not None: @@ -651,6 +717,7 @@ class ServerManager(base.BootingManagerWithFind): servers = self._list("/servers%s%s" % (detail, query_string), "servers") result.extend(servers) + result.append_request_ids(servers.request_ids) if not servers or limit != -1: break @@ -663,8 +730,9 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to add an IP to. :param network_id: The ID of the network the IP should be on. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('addFixedIp', server, {'networkId': network_id}) + return self._action('addFixedIp', server, {'networkId': network_id}) def remove_fixed_ip(self, server, address): """ @@ -672,8 +740,9 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to add an IP to. :param address: The IP address to remove. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('removeFixedIp', server, {'address': address}) + return self._action('removeFixedIp', server, {'address': address}) def add_floating_ip(self, server, address, fixed_address=None): """ @@ -683,16 +752,18 @@ class ServerManager(base.BootingManagerWithFind): :param address: The FloatingIP or string floating address to add. :param fixed_address: The FixedIP the floatingIP should be associated with (optional) + :returns: An instance of novaclient.base.TupleWithMeta """ address = address.ip if hasattr(address, 'ip') else address if fixed_address: if hasattr(fixed_address, 'ip'): fixed_address = fixed_address.ip - self._action('addFloatingIp', server, - {'address': address, 'fixed_address': fixed_address}) + return self._action('addFloatingIp', server, + {'address': address, + 'fixed_address': fixed_address}) else: - self._action('addFloatingIp', server, {'address': address}) + return self._action('addFloatingIp', server, {'address': address}) def remove_floating_ip(self, server, address): """ @@ -700,10 +771,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to remove an IP from. :param address: The FloatingIP or string floating address to remove. + :returns: An instance of novaclient.base.TupleWithMeta """ address = address.ip if hasattr(address, 'ip') else address - self._action('removeFloatingIp', server, {'address': address}) + return self._action('removeFloatingIp', server, {'address': address}) @api_versions.wraps('2.0', '2.5') def get_vnc_console(self, server, console_type): @@ -712,10 +784,10 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of vnc console to get ('novnc' or 'xvpvnc') + :returns: An instance of novaclient.base.DictWithMeta """ - return self._action('os-getVNCConsole', server, - {'type': console_type})[1] + return self._action('os-getVNCConsole', server, {'type': console_type}) @api_versions.wraps('2.0', '2.5') def get_spice_console(self, server, console_type): @@ -724,10 +796,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of spice console to get ('spice-html5') + :returns: An instance of novaclient.base.DictWithMeta """ return self._action('os-getSPICEConsole', server, - {'type': console_type})[1] + {'type': console_type}) @api_versions.wraps('2.0', '2.5') def get_rdp_console(self, server, console_type): @@ -736,10 +809,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of rdp console to get ('rdp-html5') + :returns: An instance of novaclient.base.DictWithMeta """ return self._action('os-getRDPConsole', server, - {'type': console_type})[1] + {'type': console_type}) @api_versions.wraps('2.0', '2.5') def get_serial_console(self, server, console_type): @@ -748,10 +822,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of serial console to get ('serial') + :returns: An instance of novaclient.base.DictWithMeta """ return self._action('os-getSerialConsole', server, - {'type': console_type})[1] + {'type': console_type}) @api_versions.wraps('2.6') def get_vnc_console(self, server, console_type): @@ -760,10 +835,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of vnc console to get ('novnc' or 'xvpvnc') + :returns: An instance of novaclient.base.DictWithMeta """ return self._console(server, - {'protocol': 'vnc', 'type': console_type})[1] + {'protocol': 'vnc', 'type': console_type}) @api_versions.wraps('2.6') def get_spice_console(self, server, console_type): @@ -772,10 +848,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of spice console to get ('spice-html5') + :returns: An instance of novaclient.base.DictWithMeta """ return self._console(server, - {'protocol': 'spice', 'type': console_type})[1] + {'protocol': 'spice', 'type': console_type}) @api_versions.wraps('2.6') def get_rdp_console(self, server, console_type): @@ -784,10 +861,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of rdp console to get ('rdp-html5') + :returns: An instance of novaclient.base.DictWithMeta """ return self._console(server, - {'protocol': 'rdp', 'type': console_type})[1] + {'protocol': 'rdp', 'type': console_type}) @api_versions.wraps('2.6') def get_serial_console(self, server, console_type): @@ -796,10 +874,11 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to get console for. :param console_type: Type of serial console to get ('serial') + :returns: An instance of novaclient.base.DictWithMeta """ return self._console(server, - {'protocol': 'serial', 'type': console_type})[1] + {'protocol': 'serial', 'type': console_type}) @api_versions.wraps('2.8') def get_mks_console(self, server): @@ -807,10 +886,11 @@ class ServerManager(base.BootingManagerWithFind): Get a mks console for an instance :param server: The :class:`Server` (or its ID) to get console for. + :returns: An instance of novaclient.base.DictWithMeta """ return self._console(server, - {'protocol': 'mks', 'type': 'webmks'})[1] + {'protocol': 'mks', 'type': 'webmks'}) def get_password(self, server, private_key=None): """ @@ -825,17 +905,20 @@ class ServerManager(base.BootingManagerWithFind): password is to be returned :param private_key: The private key to decrypt password (optional) + :returns: An instance of novaclient.base.StrWithMeta or + novaclient.base.BytesWithMeta or + novaclient.base.UnicodeWithMeta """ - _resp, body = self.api.client.get("/servers/%s/os-server-password" - % base.getid(server)) + resp, body = self.api.client.get("/servers/%s/os-server-password" + % base.getid(server)) ciphered_pw = body.get('password', '') if body else '' if private_key and ciphered_pw: try: - return crypto.decrypt_password(private_key, ciphered_pw) + ciphered_pw = crypto.decrypt_password(private_key, ciphered_pw) except Exception as exc: - return '%sFailed to decrypt:\n%s' % (exc, ciphered_pw) - return ciphered_pw + ciphered_pw = '%sFailed to decrypt:\n%s' % (exc, ciphered_pw) + return self.convert_into_with_meta(ciphered_pw, resp) def clear_password(self, server): """ @@ -853,62 +936,99 @@ class ServerManager(base.BootingManagerWithFind): def stop(self, server): """ Stop the server. + + :param server: The :class:`Server` (or its ID) to stop + :returns: A Response object and an instance of + novaclient.base.TupleWithMeta """ - return self._action('os-stop', server, None) + resp, body = self._action_return_resp_and_body('os-stop', server, None) + return resp, self.convert_into_with_meta(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 """ - return self._action('forceDelete', server, None) + resp, body = self._action_return_resp_and_body('forceDelete', server, + None) + return resp, self.convert_into_with_meta(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 """ - return self._action('restore', server, None) + resp, body = self._action_return_resp_and_body('restore', server, None) + return resp, self.convert_into_with_meta(body, resp) def start(self, server): """ Start the server. + + :param server: The :class:`Server` (or its ID) to start + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('os-start', server, None) + return self._action('os-start', server, None) def pause(self, server): """ Pause the server. + + :param server: The :class:`Server` (or its ID) to pause + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('pause', server, None) + return self._action('pause', server, None) def unpause(self, server): """ Unpause the server. + + :param server: The :class:`Server` (or its ID) to unpause + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('unpause', server, None) + return self._action('unpause', server, None) def lock(self, server): """ Lock the server. + + :param server: The :class:`Server` (or its ID) to lock + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('lock', server, None) + return self._action('lock', server, None) def unlock(self, server): """ Unlock the server. + + :param server: The :class:`Server` (or its ID) to unlock + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('unlock', server, None) + return self._action('unlock', server, None) def suspend(self, server): """ Suspend the server. + + :param server: The :class:`Server` (or its ID) to suspend + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('suspend', server, None) + return self._action('suspend', server, None) def resume(self, server): """ Resume the server. + + :param server: The :class:`Server` (or its ID) to resume + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('resume', server, None) + return self._action('resume', server, None) def rescue(self, server, password=None, image=None): """ @@ -917,52 +1037,82 @@ 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 """ info = {} if password: info['adminPass'] = password if image: info['rescue_image_ref'] = base.getid(image) - return self._action('rescue', server, info or None) + 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) def unrescue(self, server): """ Unrescue the server. + + :param server: The :class:`Server` (or its ID) to unrescue + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('unrescue', server, None) + return self._action('unrescue', server, None) def shelve(self, server): """ Shelve the server. + + :param server: The :class:`Server` (or its ID) to shelve + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('shelve', server, None) + return self._action('shelve', server, None) def shelve_offload(self, server): """ Remove a shelved instance from the compute node. + + :param server: The :class:`Server` (or its ID) to shelve offload + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('shelveOffload', server, None) + return self._action('shelveOffload', server, None) def unshelve(self, server): """ Unshelve the server. + + :param server: The :class:`Server` (or its ID) to unshelve + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('unshelve', server, None) + return self._action('unshelve', server, None) def ips(self, server): """ Return IP Addresses associated with the server. Often a cheaper call then getting all the details for a server. + + :param server: The :class:`Server` (or its ID) for which + the IP adresses are to be returned + :returns: An instance of novaclient.base.DictWithMeta """ - _resp, body = self.api.client.get("/servers/%s/ips" % - base.getid(server)) - return body['addresses'] + resp, body = self.api.client.get("/servers/%s/ips" % + base.getid(server)) + return base.DictWithMeta(body['addresses'], resp) def diagnostics(self, server): - """Retrieve server diagnostics.""" - return self.api.client.get("/servers/%s/diagnostics" % - base.getid(server)) + """ + Retrieve server diagnostics. + + :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 + """ + 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) def create(self, name, image, flavor, meta=None, files=None, reservation_id=None, min_count=None, @@ -1073,14 +1223,21 @@ class ServerManager(base.BootingManagerWithFind): def change_password(self, server, password): """ Update the password for a server. + + :param server: The :class:`Server` (or its ID) for which the admin + password is to be changed + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action("changePassword", server, {"adminPass": password}) + return self._action("changePassword", server, {"adminPass": password}) def delete(self, server): """ Delete (i.e. shut down and delete the image) this server. + + :param server: The :class:`Server` (or its ID) to delete + :returns: An instance of novaclient.base.TupleWithMeta """ - self._delete("/servers/%s" % base.getid(server)) + return self._delete("/servers/%s" % base.getid(server)) def reboot(self, server, reboot_type=REBOOT_SOFT): """ @@ -1089,8 +1246,9 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to share onto. :param reboot_type: either :data:`REBOOT_SOFT` for a software-level reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('reboot', server, {'type': reboot_type}) + return self._action('reboot', server, {'type': reboot_type}) def rebuild(self, server, image, password=None, disk_config=None, preserve_ephemeral=False, name=None, meta=None, files=None, @@ -1113,6 +1271,7 @@ class ServerManager(base.BootingManagerWithFind): are the file contents (either as a string or as a file-like object). A maximum of five entries is allowed, and each file must be 10k or less. + :returns: :class:`Server` """ body = {'imageRef': base.getid(image)} if password is not None: @@ -1140,16 +1299,18 @@ class ServerManager(base.BootingManagerWithFind): 'contents': cont, }) - _resp, body = self._action('rebuild', server, body, **kwargs) - return Server(self, body['server']) + resp, body = self._action_return_resp_and_body('rebuild', server, + body, **kwargs) + return Server(self, body['server'], resp=resp) def migrate(self, server): """ Migrate a server to a new host. :param server: The :class:`Server` (or its ID). + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('migrate', server) + return self._action('migrate', server) def resize(self, server, flavor, disk_config=None, **kwargs): """ @@ -1159,6 +1320,7 @@ class ServerManager(base.BootingManagerWithFind): :param flavor: the :class:`Flavor` (or its ID) to resize to. :param disk_config: partitioning mode to use on the rebuilt server. Valid values are 'AUTO' or 'MANUAL' + :returns: An instance of novaclient.base.TupleWithMeta Until a resize event is confirmed with :meth:`confirm_resize`, the old server will be kept around and you'll be able to roll back to the old @@ -1169,23 +1331,25 @@ class ServerManager(base.BootingManagerWithFind): if disk_config is not None: info['OS-DCF:diskConfig'] = disk_config - self._action('resize', server, info=info, **kwargs) + return self._action('resize', server, info=info, **kwargs) def confirm_resize(self, server): """ Confirm that the resize worked, thus removing the original server. :param server: The :class:`Server` (or its ID) to share onto. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('confirmResize', server) + return self._action('confirmResize', server) def revert_resize(self, server): """ Revert a previous resize, switching back to the old server. :param server: The :class:`Server` (or its ID) to share onto. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('revertResize', server) + return self._action('revertResize', server) def create_image(self, server, image_name, metadata=None): """ @@ -1194,12 +1358,15 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to share onto. :param image_name: Name to give the snapshot image :param metadata: Metadata to give newly-created image entity + :returns: An instance of novaclient.base.StrWithMeta + (The snapshot image's UUID) """ body = {'name': image_name, 'metadata': metadata or {}} - resp = self._action('createImage', server, body)[0] + resp, body = self._action_return_resp_and_body('createImage', server, + body) location = resp.headers['location'] image_uuid = location.split('/')[-1] - return image_uuid + return base.StrWithMeta(image_uuid, resp) def backup(self, server, backup_name, backup_type, rotation): """ @@ -1210,11 +1377,12 @@ class ServerManager(base.BootingManagerWithFind): :param backup_type: The backup type, like 'daily' or 'weekly' :param rotation: Int parameter representing how many backups to keep around. + :returns: An instance of novaclient.base.TupleWithMeta """ body = {'name': backup_name, 'backup_type': backup_type, 'rotation': rotation} - self._action('createBackup', server, body) + return self._action('createBackup', server, body) def set_meta(self, server, metadata): """ @@ -1244,19 +1412,29 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) whose console output you would like to retrieve. :param length: The number of tail loglines you would like to retrieve. + :returns: An instance of novaclient.base.StrWithMeta or + novaclient.base.UnicodeWithMeta """ - return self._action('os-getConsoleOutput', - server, - {'length': length})[1]['output'] + resp, body = self._action_return_resp_and_body('os-getConsoleOutput', + server, + {'length': length}) + return self.convert_into_with_meta(body['output'], resp) def delete_meta(self, server, keys): """ Delete metadata from a server + :param server: The :class:`Server` to add metadata to :param keys: A list of metadata keys to delete from the server + :returns: An instance of novaclient.base.TupleWithMeta """ + result = base.TupleWithMeta((), None) for k in keys: - self._delete("/servers/%s/metadata/%s" % (base.getid(server), k)) + ret = self._delete("/servers/%s/metadata/%s" % + (base.getid(server), k)) + result.append_request_ids(ret.request_ids) + + return result def live_migrate(self, server, host, block_migration, disk_over_commit): """ @@ -1266,12 +1444,12 @@ class ServerManager(base.BootingManagerWithFind): :param host: destination host name. :param block_migration: if True, do block_migration. :param disk_over_commit: if True, Allow overcommit. - + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('os-migrateLive', server, - {'host': host, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}) + return self._action('os-migrateLive', server, + {'host': host, + 'block_migration': block_migration, + 'disk_over_commit': disk_over_commit}) def reset_state(self, server, state='error'): """ @@ -1280,14 +1458,18 @@ class ServerManager(base.BootingManagerWithFind): :param server: ID of the instance to reset the state of. :param state: Desired state; either 'active' or 'error'. Defaults to 'error'. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('os-resetState', server, dict(state=state)) + return self._action('os-resetState', server, dict(state=state)) def reset_network(self, server): """ Reset network of an instance. + + :param server: The :class:`Server` for network is to be reset + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('resetNetwork', server) + return self._action('resetNetwork', server) def add_security_group(self, server, security_group): """ @@ -1295,9 +1477,10 @@ class ServerManager(base.BootingManagerWithFind): :param server: ID of the instance. :param security_group: The name of security group to add. - + :returns: An instance of novaclient.base.DictWithMeta """ - self._action('addSecurityGroup', server, {'name': security_group}) + return self._action('addSecurityGroup', server, + {'name': security_group}) def remove_security_group(self, server, security_group): """ @@ -1305,9 +1488,10 @@ class ServerManager(base.BootingManagerWithFind): :param server: ID of the instance. :param security_group: The name of security group to remove. - + :returns: An instance of novaclient.base.TupleWithMeta """ - self._action('removeSecurityGroup', server, {'name': security_group}) + return self._action('removeSecurityGroup', server, + {'name': security_group}) def list_security_group(self, server): """ @@ -1331,6 +1515,8 @@ 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 """ body = {'onSharedStorage': on_shared_storage} @@ -1340,7 +1526,9 @@ class ServerManager(base.BootingManagerWithFind): if password is not None: body['adminPass'] = password - return self._action('evacuate', server, body) + resp, body = self._action_return_resp_and_body('evacuate', server, + body) + return resp, self.convert_into_with_meta(body, resp) @api_versions.wraps("2.14") def evacuate(self, server, host=None, password=None): @@ -1359,7 +1547,9 @@ class ServerManager(base.BootingManagerWithFind): if password is not None: body['adminPass'] = password - return self._action('evacuate', server, body) + resp, body = self._action_return_resp_and_body('evacuate', server, + body) + return resp, self.convert_into_with_meta(body, resp) def interface_list(self, server): """ @@ -1396,9 +1586,10 @@ class ServerManager(base.BootingManagerWithFind): :param server: The :class:`Server` (or its ID) to detach from. :param port_id: The port to detach. + :returns: An instance of novaclient.base.TupleWithMeta """ - self._delete('/servers/%s/os-interface/%s' % (base.getid(server), - port_id)) + return self._delete('/servers/%s/os-interface/%s' % + (base.getid(server), port_id)) @api_versions.wraps("2.17") def trigger_crash_dump(self, server): @@ -1409,6 +1600,15 @@ class ServerManager(base.BootingManagerWithFind): """ Perform a server "action" -- reboot/rebuild/resize/etc. """ + resp, body = self._action_return_resp_and_body(action, server, + info=info, **kwargs) + return self.convert_into_with_meta(body, resp) + + def _action_return_resp_and_body(self, action, server, info=None, + **kwargs): + """ + Perform a server "action" and return response headers and body + """ body = {action: info} self.run_hooks('modify_body_for_action', body, **kwargs) url = '/servers/%s/action' % base.getid(server) @@ -1420,4 +1620,5 @@ class ServerManager(base.BootingManagerWithFind): """ body = {'remote_console': info} url = '/servers/%s/remote-consoles' % base.getid(server) - return self.api.client.post(url, body=body) + resp, body = self.api.client.post(url, body=body) + return self.convert_into_with_meta(body, resp)