Merge "Microversion 2.56 - Enable cold migration with target host"

This commit is contained in:
Zuul 2017-12-06 10:30:26 +00:00 committed by Gerrit Code Review
commit 0de65d26fd
8 changed files with 101 additions and 4 deletions

View File

@ -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.55")
API_MAX_VERSION = api_versions.APIVersion("2.56")

View File

@ -452,6 +452,8 @@ class V1(Base):
# but we can not specify version in data_fixture now and this is
# V1 data, so just let it pass
pass
elif action == 'migrate':
return None
elif action == 'rebuild':
body = body[action]
adminPass = body.get('adminPass', 'randompassword')

View File

@ -687,7 +687,7 @@ class FakeSessionClient(base_client.SessionClient):
# Server actions
#
none_actions = ['revertResize', 'migrate', 'os-stop', 'os-start',
none_actions = ['revertResize', 'os-stop', 'os-start',
'forceDelete', 'restore', 'pause', 'unpause', 'unlock',
'unrescue', 'resume', 'suspend', 'lock', 'shelve',
'shelveOffload', 'unshelve', 'resetNetwork']
@ -749,6 +749,15 @@ class FakeSessionClient(base_client.SessionClient):
if self.api_version < api_versions.APIVersion("2.25"):
expected.add('disk_over_commit')
assert set(body[action].keys()) == expected
elif action == 'migrate':
if self.api_version < api_versions.APIVersion("2.56"):
assert body[action] is None
else:
expected = set()
if 'host' in body[action].keys():
# host can be optional
expected.add('host')
assert set(body[action].keys()) == expected
elif action == 'rebuild':
body = body[action]
adminPass = body.get('adminPass', 'randompassword')

View File

@ -1581,3 +1581,26 @@ class ServersV254Test(ServersV252Test):
'1234', fakes.FAKE_IMAGE_UUID_1,
key_name='test_keypair')
self.assertIn('key_name', six.text_type(ex.message))
class ServersV256Test(ServersV254Test):
api_version = "2.56"
def test_migrate_server(self):
s = self.cs.servers.get(1234)
ret = s.migrate()
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'migrate': {}})
ret = s.migrate(host='target-host')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'migrate': {'host': 'target-host'}})
def test_migrate_server_pre_256_fails(self):
self.cs.api_version = api_versions.APIVersion('2.55')
s = self.cs.servers.get(1234)
ex = self.assertRaises(TypeError,
s.migrate, host='target-host')
self.assertIn('host', six.text_type(ex))

View File

@ -1628,6 +1628,23 @@ class ShellTest(utils.TestCase):
self.run_command('migrate sample-server')
self.assert_called('POST', '/servers/1234/action', {'migrate': None})
def test_migrate_pre_v256(self):
self.assertRaises(SystemExit,
self.run_command,
'migrate --host target-host sample-server',
api_version='2.55')
def test_migrate_v256(self):
self.run_command('migrate sample-server',
api_version='2.56')
self.assert_called('POST', '/servers/1234/action',
{'migrate': {}})
self.run_command('migrate --host target-host sample-server',
api_version='2.56')
self.assert_called('POST', '/servers/1234/action',
{'migrate': {'host': 'target-host'}})
def test_resize(self):
self.run_command('resize sample-server 1')
self.assert_called('POST', '/servers/1234/action',

View File

@ -327,6 +327,7 @@ class Server(base.Resource):
"""Diagnostics -- Retrieve server diagnostics."""
return self.manager.diagnostics(self)
@api_versions.wraps("2.0", "2.55")
def migrate(self):
"""
Migrate a server to a new host.
@ -335,6 +336,16 @@ class Server(base.Resource):
"""
return self.manager.migrate(self)
@api_versions.wraps("2.56")
def migrate(self, host=None):
"""
Migrate a server to a new host.
:param host: (Optional) The target host.
:returns: An instance of novaclient.base.TupleWithMeta
"""
return self.manager.migrate(self, host=host)
def remove_fixed_ip(self, address):
"""
Remove an IP address.
@ -1545,6 +1556,7 @@ class ServerManager(base.BootingManagerWithFind):
body, **kwargs)
return Server(self, body['server'], resp=resp)
@api_versions.wraps("2.0", "2.55")
def migrate(self, server):
"""
Migrate a server to a new host.
@ -1554,6 +1566,22 @@ class ServerManager(base.BootingManagerWithFind):
"""
return self._action('migrate', server)
@api_versions.wraps("2.56")
def migrate(self, server, host=None):
"""
Migrate a server to a new host.
:param server: The :class:`Server` (or its ID).
:param host: (Optional) The target host.
:returns: An instance of novaclient.base.TupleWithMeta
"""
info = {}
if host:
info['host'] = host
return self._action('migrate', server, info)
def resize(self, server, flavor, disk_config=None, **kwargs):
"""
Resize a server's resources.

View File

@ -1950,6 +1950,12 @@ def do_resize_revert(cs, args):
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
@utils.arg(
'--host',
metavar='<host>',
default=None,
help=_('Destination host name.'),
start_version='2.56')
@utils.arg(
'--poll',
dest='poll',
@ -1957,9 +1963,13 @@ def do_resize_revert(cs, args):
default=False,
help=_('Report the server migration progress until it completes.'))
def do_migrate(cs, args):
"""Migrate a server. The new host will be selected by the scheduler."""
"""Migrate a server."""
update_kwargs = {}
if 'host' in args and args.host:
update_kwargs['host'] = args.host
server = _find_server(cs, args.server)
server.migrate()
server.migrate(**update_kwargs)
if args.poll:
_poll_for_status(cs.servers.get, server.id, 'migrating',

View File

@ -0,0 +1,8 @@
---
features:
- Added a new ``--host`` option to ``nova migrate`` command
in microversion 2.56. It enables administrators to specify
a target host when cold migating a server. The target host will be
validated by the scheduler. The target host cannot be the same as
the current host on which the server is running and must be in the
same cell that the server is currently in.