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
This commit is contained in:
parent
63d368168c
commit
ee9b277c5f
@ -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")
|
||||
|
@ -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]
|
||||
|
@ -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:
|
||||
|
@ -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}})
|
||||
|
@ -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.
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user