Merge "Add support for microversion 2.29"
This commit is contained in:
commit
e3856a36c2
novaclient
@ -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.28")
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.29")
|
||||
|
@ -753,7 +753,11 @@ class FakeHTTPClient(base_client.HTTPClient):
|
||||
keys.remove('adminPass')
|
||||
if 'host' in keys:
|
||||
keys.remove('host')
|
||||
assert set(keys) == set(['onSharedStorage'])
|
||||
if 'onSharedStorage' in keys:
|
||||
keys.remove('onSharedStorage')
|
||||
if 'force' in keys:
|
||||
keys.remove('force')
|
||||
assert set(keys) == set()
|
||||
else:
|
||||
raise AssertionError("Unexpected server action: %s" % action)
|
||||
_headers.update(FAKE_RESPONSE_HEADERS)
|
||||
|
@ -1179,3 +1179,19 @@ class ServersV226Test(ServersV225Test):
|
||||
ret = s.set_tags(['tag1', 'tag2'])
|
||||
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('PUT', '/servers/1234/tags')
|
||||
|
||||
|
||||
class ServersV229Test(ServersV226Test):
|
||||
def setUp(self):
|
||||
super(ServersV229Test, self).setUp()
|
||||
self.cs.api_version = api_versions.APIVersion("2.29")
|
||||
|
||||
def test_evacuate(self):
|
||||
s = self.cs.servers.get(1234)
|
||||
s.evacuate('fake_target_host')
|
||||
self.assert_called('POST', '/servers/1234/action',
|
||||
{'evacuate': {'host': 'fake_target_host'}})
|
||||
self.cs.servers.evacuate(s, 'fake_target_host', force=True)
|
||||
self.assert_called('POST', '/servers/1234/action',
|
||||
{'evacuate': {'host': 'fake_target_host',
|
||||
'force': True}})
|
||||
|
@ -2009,6 +2009,23 @@ class ShellTest(utils.TestCase):
|
||||
{'evacuate': {'host': 'target_hyper',
|
||||
'onSharedStorage': False}}, pos=4)
|
||||
|
||||
def test_host_evacuate_v2_29(self):
|
||||
self.run_command('host-evacuate hyper --target target_hyper --force',
|
||||
api_version='2.29')
|
||||
self.assert_called('GET', '/os-hypervisors/hyper/servers', pos=0)
|
||||
self.assert_called('POST', '/servers/uuid1/action',
|
||||
{'evacuate': {'host': 'target_hyper', 'force': True}
|
||||
}, pos=1)
|
||||
self.assert_called('POST', '/servers/uuid2/action',
|
||||
{'evacuate': {'host': 'target_hyper', 'force': True}
|
||||
}, pos=2)
|
||||
self.assert_called('POST', '/servers/uuid3/action',
|
||||
{'evacuate': {'host': 'target_hyper', 'force': True}
|
||||
}, pos=3)
|
||||
self.assert_called('POST', '/servers/uuid4/action',
|
||||
{'evacuate': {'host': 'target_hyper', 'force': True}
|
||||
}, pos=4)
|
||||
|
||||
def test_host_evacuate_with_shared_storage(self):
|
||||
self.run_command(
|
||||
'host-evacuate --on-shared-storage hyper --target target_hyper')
|
||||
@ -2410,6 +2427,21 @@ class ShellTest(utils.TestCase):
|
||||
{'evacuate': {'host': 'new_host',
|
||||
'onSharedStorage': True}})
|
||||
|
||||
def test_evacuate_v2_29(self):
|
||||
self.run_command('evacuate sample-server new_host', api_version="2.29")
|
||||
self.assert_called('POST', '/servers/1234/action',
|
||||
{'evacuate': {'host': 'new_host'}})
|
||||
self.run_command('evacuate sample-server new_host '
|
||||
'--password NewAdminPass', api_version="2.29")
|
||||
self.assert_called('POST', '/servers/1234/action',
|
||||
{'evacuate': {'host': 'new_host',
|
||||
'adminPass': 'NewAdminPass'}})
|
||||
self.run_command('evacuate --force sample-server new_host',
|
||||
api_version="2.29")
|
||||
self.assert_called('POST', '/servers/1234/action',
|
||||
{'evacuate': {'host': 'new_host',
|
||||
'force': True}})
|
||||
|
||||
def test_evacuate_with_no_target_host(self):
|
||||
self.run_command('evacuate sample-server')
|
||||
self.assert_called('POST', '/servers/1234/action',
|
||||
|
@ -27,12 +27,17 @@ def _server_evacuate(cs, server, args):
|
||||
success = True
|
||||
error_message = ""
|
||||
try:
|
||||
on_shared_storage = getattr(args, 'on_shared_storage', None)
|
||||
if api_versions.APIVersion("2.14") <= cs.api_version:
|
||||
# if microversion >= 2.14
|
||||
if api_versions.APIVersion("2.29") <= cs.api_version:
|
||||
# if microversion >= 2.29
|
||||
force = getattr(args, 'force', None)
|
||||
cs.servers.evacuate(server=server['uuid'], host=args.target_host,
|
||||
force=force)
|
||||
elif api_versions.APIVersion("2.14") <= cs.api_version:
|
||||
# if microversion 2.14 - 2.28
|
||||
cs.servers.evacuate(server=server['uuid'], host=args.target_host)
|
||||
else:
|
||||
# else microversion 2.0 - 2.13
|
||||
on_shared_storage = getattr(args, 'on_shared_storage', None)
|
||||
cs.servers.evacuate(server=server['uuid'],
|
||||
host=args.target_host,
|
||||
on_shared_storage=on_shared_storage)
|
||||
@ -60,6 +65,13 @@ def _server_evacuate(cs, server, args):
|
||||
help=_('Specifies whether all instances files are on shared storage'),
|
||||
start_version='2.0',
|
||||
end_version='2.13')
|
||||
@utils.arg(
|
||||
'--force',
|
||||
dest='force',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Force to not verify the scheduler if a host is provided.'),
|
||||
start_version='2.29')
|
||||
def do_host_evacuate(cs, args):
|
||||
"""Evacuate all instances from failed host."""
|
||||
hypervisors = cs.hypervisors.search(args.host, servers=True)
|
||||
|
@ -499,7 +499,7 @@ class Server(base.Resource):
|
||||
"""
|
||||
return self.manager.evacuate(self, host, on_shared_storage, password)
|
||||
|
||||
@api_versions.wraps("2.14")
|
||||
@api_versions.wraps("2.14", "2.28")
|
||||
def evacuate(self, host=None, password=None):
|
||||
"""
|
||||
Evacuate an instance from failed host to specified host.
|
||||
@ -511,6 +511,19 @@ class Server(base.Resource):
|
||||
"""
|
||||
return self.manager.evacuate(self, host, password)
|
||||
|
||||
@api_versions.wraps("2.29")
|
||||
def evacuate(self, host=None, password=None, force=None):
|
||||
"""
|
||||
Evacuate an instance from failed host to specified host.
|
||||
|
||||
:param host: Name of the target host
|
||||
:param password: string to set as admin password on the evacuated
|
||||
server.
|
||||
:param force: forces to bypass the scheduler if host is provided.
|
||||
:returns: An instance of novaclient.base.TupleWithMeta
|
||||
"""
|
||||
return self.manager.evacuate(self, host, password, force)
|
||||
|
||||
def interface_list(self):
|
||||
"""
|
||||
List interfaces attached to an instance.
|
||||
@ -1658,7 +1671,7 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
body)
|
||||
return base.TupleWithMeta((resp, body), resp)
|
||||
|
||||
@api_versions.wraps("2.14")
|
||||
@api_versions.wraps("2.14", "2.28")
|
||||
def evacuate(self, server, host=None, password=None):
|
||||
"""
|
||||
Evacuate a server instance.
|
||||
@ -1680,6 +1693,32 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
body)
|
||||
return base.TupleWithMeta((resp, body), resp)
|
||||
|
||||
@api_versions.wraps("2.29")
|
||||
def evacuate(self, server, host=None, password=None, force=None):
|
||||
"""
|
||||
Evacuate a server instance.
|
||||
|
||||
:param server: The :class:`Server` (or its ID) to share onto.
|
||||
:param host: Name of the target host.
|
||||
:param password: string to set as password on the evacuated server.
|
||||
:param force: forces to bypass the scheduler if host is provided.
|
||||
:returns: An instance of novaclient.base.TupleWithMeta
|
||||
"""
|
||||
|
||||
body = {}
|
||||
if host is not None:
|
||||
body['host'] = host
|
||||
|
||||
if password is not None:
|
||||
body['adminPass'] = password
|
||||
|
||||
if force:
|
||||
body['force'] = force
|
||||
|
||||
resp, body = self._action_return_resp_and_body('evacuate', server,
|
||||
body)
|
||||
return base.TupleWithMeta((resp, body), resp)
|
||||
|
||||
def interface_list(self, server):
|
||||
"""
|
||||
List attached network interfaces
|
||||
|
@ -4688,12 +4688,26 @@ def do_quota_class_update(cs, args):
|
||||
help=_('Specifies whether server files are located on shared storage.'),
|
||||
start_version='2.0',
|
||||
end_version='2.13')
|
||||
@utils.arg(
|
||||
'--force',
|
||||
dest='force',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Force to not verify the scheduler if a host is provided.'),
|
||||
start_version='2.29')
|
||||
def do_evacuate(cs, args):
|
||||
"""Evacuate server from failed host."""
|
||||
|
||||
server = _find_server(cs, args.server)
|
||||
on_shared_storage = getattr(args, 'on_shared_storage', None)
|
||||
res = server.evacuate(args.host, on_shared_storage, args.password)[1]
|
||||
force = getattr(args, 'force', None)
|
||||
update_kwargs = {}
|
||||
if on_shared_storage is not None:
|
||||
update_kwargs['on_shared_storage'] = on_shared_storage
|
||||
if force:
|
||||
update_kwargs['force'] = force
|
||||
res = server.evacuate(host=args.host, password=args.password,
|
||||
**update_kwargs)[1]
|
||||
if isinstance(res, dict):
|
||||
utils.print_dict(res)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user