summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené Ribaud <rribaud@redhat.com>2022-03-03 11:18:59 +0100
committerRené Ribaud <rribaud@redhat.com>2022-07-28 14:49:46 +0200
commitee9b277c5f442f299b853118c900c3ee2996c67a (patch)
treebf4dc5e298c820c37f7994921cc1d435e11dcc38
parent63d368168c87bc0b9a9b7928b42553c609e46089 (diff)
downloadpython-novaclient-ee9b277c5f442f299b853118c900c3ee2996c67a.tar.gz
Microversion 2.91: Support specifying destination host to unshelve
This patch adds ``host`` to novaclient api. This can help administrators to specify a ``host`` to unshelve a shelve offloaded server from 2.91 microversion. Depends-On: https://review.opendev.org/c/openstack/nova/+/831507 Implements: blueprint unshelve-to-host Change-Id: I7efc8f0b0ef159e16cefee761bff5d7e90d0c427
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/fixture_data/servers.py11
-rw-r--r--novaclient/tests/unit/v2/fakes.py2
-rw-r--r--novaclient/tests/unit/v2/test_servers.py98
-rw-r--r--novaclient/v2/servers.py65
-rw-r--r--releasenotes/notes/bp-unshelve-to-host-b220131a00dff8a2.yaml9
6 files changed, 182 insertions, 5 deletions
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index d49e8841..bbfd9522 100644
--- a/novaclient/__init__.py
+++ b/novaclient/__init__.py
@@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
# when client supported the max version, and bumped sequentially, otherwise
# the client may break due to server side new version may include some
# backward incompatible change.
-API_MAX_VERSION = api_versions.APIVersion("2.90")
+API_MAX_VERSION = api_versions.APIVersion("2.91")
diff --git a/novaclient/tests/unit/fixture_data/servers.py b/novaclient/tests/unit/fixture_data/servers.py
index a8301548..8e53ecdb 100644
--- a/novaclient/tests/unit/fixture_data/servers.py
+++ b/novaclient/tests/unit/fixture_data/servers.py
@@ -439,6 +439,17 @@ class V1(Base):
elif action == 'lock':
return None
elif action == 'unshelve':
+ if api_version >= api_versions.APIVersion("2.91"):
+ # In 2.91 and above, we allow body to be one of these:
+ # {'unshelve': None}
+ # {'unshelve': {'availability_zone': <string>}}
+ # {'unshelve': {'availability_zone': None}} (Unpin az)
+ # {'unshelve': {'host': <fqdn>}}
+ # {'unshelve': {'availability_zone': <string>, 'host': <fqdn>}}
+ # {'unshelve': {'availability_zone': None, 'host': <fqdn>}}
+ if body[action] is not None:
+ for key in body[action].keys():
+ key in ['availability_zone', 'host']
return None
elif action == 'rebuild':
body = body[action]
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index 07216adc..059a7147 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -835,7 +835,7 @@ class FakeSessionClient(base_client.SessionClient):
if self.api_version < api_versions.APIVersion("2.77"):
assert body[action] is None
else:
- # In 2.77 and above, we allow body to be one of these:
+ # In 2.77 to 2.91, we allow body to be one of these:
# {'unshelve': None}
# {'unshelve': {'availability_zone': 'foo-az'}}
if body[action] is not None:
diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py
index 071ae5c1..93fefabf 100644
--- a/novaclient/tests/unit/v2/test_servers.py
+++ b/novaclient/tests/unit/v2/test_servers.py
@@ -1851,6 +1851,23 @@ class ServersV277Test(ServersV274Test):
api_version = "2.77"
+ def test_unshelve(self):
+ s = self.cs.servers.get(1234)
+ # Test going through the Server object.
+ ret = s.unshelve()
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': None})
+ # Test going through the ServerManager directly.
+ ret = self.cs.servers.unshelve(s)
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': None})
+
def test_unshelve_with_az(self):
s = self.cs.servers.get(1234)
# Test going through the Server object.
@@ -1883,7 +1900,7 @@ class ServersV277Test(ServersV274Test):
str(ex))
-class ServersV278Test(ServersV273Test):
+class ServersV278Test(ServersV277Test):
api_version = "2.78"
@@ -1992,3 +2009,82 @@ class ServersV290Test(ServersV278Test):
s.update,
hostname='new-hostname')
self.assertIn('hostname', str(ex))
+
+
+class ServersV291Test(ServersV290Test):
+
+ api_version = "2.91"
+
+ def test_unshelve_with_host(self):
+ s = self.cs.servers.get(1234)
+ # Test going through the Server object.
+ ret = s.unshelve(host='server1')
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'host': 'server1'}})
+ # Test going through the ServerManager directly.
+ ret = self.cs.servers.unshelve(s, host='server1')
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'host': 'server1'}})
+
+ def test_unshelve_server_with_az_and_host(self):
+ s = self.cs.servers.get(1234)
+ # Test going through the Server object.
+ ret = s.unshelve(host='server1', availability_zone='foo-az')
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'host': 'server1',
+ 'availability_zone': 'foo-az'}})
+ # Test going through the ServerManager directly.
+ ret = self.cs.servers.unshelve(
+ s, host='server1', availability_zone='foo-az')
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'host': 'server1',
+ 'availability_zone': 'foo-az'}})
+
+ def test_unshelve_unpin_az(self):
+ s = self.cs.servers.get(1234)
+ # Test going through the Server object.
+ ret = s.unshelve(availability_zone=None)
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'availability_zone': None}})
+ # Test going through the ServerManager directly.
+ ret = self.cs.servers.unshelve(s, availability_zone=None)
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'availability_zone': None}})
+
+ def test_unshelve_server_with_host_and_unpin(self):
+ s = self.cs.servers.get(1234)
+ # Test going through the Server object.
+ ret = s.unshelve(availability_zone=None, host='server1')
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'host': 'server1',
+ 'availability_zone': None}})
+ # Test going through the ServerManager directly.
+ ret = self.cs.servers.unshelve(
+ s, availability_zone=None, host='server1')
+ self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called(
+ 'POST',
+ '/servers/1234/action',
+ {'unshelve': {'host': 'server1',
+ 'availability_zone': None}})
diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py
index 76709ec5..8a9301f6 100644
--- a/novaclient/v2/servers.py
+++ b/novaclient/v2/servers.py
@@ -314,7 +314,7 @@ class Server(base.Resource):
"""
return self.manager.unshelve(self)
- @api_versions.wraps("2.77")
+ @api_versions.wraps("2.77", "2.90")
def unshelve(self, availability_zone=None):
"""
Unshelve -- Unshelve the server.
@@ -326,6 +326,37 @@ class Server(base.Resource):
return self.manager.unshelve(self,
availability_zone=availability_zone)
+ @api_versions.wraps("2.91")
+ def unshelve(self, availability_zone=object(), host=None):
+ """
+ Unshelve -- Unshelve the server.
+
+ :param availability_zone: If specified the instance will be unshelved
+ to the availability_zone.
+ If None is passed the instance defined
+ availability_zone is unpin and the instance
+ will be scheduled to any availability_zone
+ (free scheduling).
+ If not specified the instance will be
+ unshelved to either its defined
+ availability_zone or any
+ availability_zone (free scheduling).
+ :param host: The specified host
+ (Optional)
+ :returns: An instance of novaclient.base.TupleWithMeta
+ """
+ if (
+ availability_zone is None or isinstance(availability_zone, str)
+ ) and host:
+ return self.manager.unshelve(
+ self, availability_zone=availability_zone, host=host)
+ if availability_zone is None or isinstance(availability_zone, str):
+ return self.manager.unshelve(
+ self, availability_zone=availability_zone)
+ if host:
+ return self.manager.unshelve(self, host=host)
+ return self.manager.unshelve(self)
+
def diagnostics(self):
"""Diagnostics -- Retrieve server diagnostics."""
return self.manager.diagnostics(self)
@@ -1266,7 +1297,7 @@ class ServerManager(base.BootingManagerWithFind):
"""
return self._action('unshelve', server, None)
- @api_versions.wraps("2.77")
+ @api_versions.wraps("2.77", "2.90")
def unshelve(self, server, availability_zone=None):
"""
Unshelve the server.
@@ -1281,6 +1312,36 @@ class ServerManager(base.BootingManagerWithFind):
info = {'availability_zone': availability_zone}
return self._action('unshelve', server, info)
+ @api_versions.wraps("2.91")
+ def unshelve(self, server, availability_zone=object(), host=None):
+ """
+ Unshelve the server.
+
+ :param availability_zone: If specified the instance will be unshelved
+ to the availability_zone.
+ If None is passed the instance defined
+ availability_zone is unpin and the instance
+ will be scheduled to any availability_zone
+ (free scheduling).
+ If not specified the instance will be
+ unshelved to either its defined
+ availability_zone or any
+ availability_zone (free scheduling).
+ :param host: The specified host
+ (Optional)
+ :returns: An instance of novaclient.base.TupleWithMeta
+ """
+ info = None
+
+ if availability_zone is None or isinstance(availability_zone, str):
+ info = {'availability_zone': availability_zone}
+ if host:
+ if info:
+ info['host'] = host
+ else:
+ info = {'host': host}
+ return self._action('unshelve', server, info)
+
def ips(self, server):
"""
Return IP Addresses associated with the server.
diff --git a/releasenotes/notes/bp-unshelve-to-host-b220131a00dff8a2.yaml b/releasenotes/notes/bp-unshelve-to-host-b220131a00dff8a2.yaml
new file mode 100644
index 00000000..98fe2c9f
--- /dev/null
+++ b/releasenotes/notes/bp-unshelve-to-host-b220131a00dff8a2.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ Support has been added for `microversion 2.91`_. This microversion
+ allows specifying a destination host to unshelve a shelve
+ offloaded server. And availability zone can be set to None to unpin
+ the availability zone of a server.
+
+ .. _microversion 2.91: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#microversion-2-91