Add support for microversion 2.30

Now the os-migrateLive API supports a new body argument called 'force' which
helps the operators to bypass the scheduler call in case they provide a host.

Also modifies the host_evacuate_live helper method in the contrib tree to make
sure operators also have the force flag in case they need it for a global call.

Change-Id: Id7fcd88ad060390ac6d1a21510d84363ed643957
Implements: blueprint check-destination-on-migrations-newton
This commit is contained in:
Sylvain Bauza 2016-06-21 18:08:06 +02:00
parent 1aa042e0cb
commit c649678991
7 changed files with 118 additions and 20 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.29")
API_MAX_VERSION = api_versions.APIVersion("2.30")

View File

@ -715,13 +715,14 @@ class FakeHTTPClient(base_client.HTTPClient):
# raise AssertionError if we didn't find 'action' at all.
pass
elif action == 'os-migrateLive':
expected = set(['host', 'block_migration'])
if self.api_version >= api_versions.APIVersion("2.30"):
if 'force' in body[action].keys():
# force can be optional
expected.add('force')
if self.api_version < api_versions.APIVersion("2.25"):
assert set(body[action].keys()) == set(['host',
'block_migration',
'disk_over_commit'])
else:
assert set(body[action].keys()) == set(['host',
'block_migration'])
expected.add('disk_over_commit')
assert set(body[action].keys()) == expected
elif action == 'rebuild':
body = body[action]
adminPass = body.get('adminPass', 'randompassword')

View File

@ -1195,3 +1195,25 @@ class ServersV229Test(ServersV226Test):
self.assert_called('POST', '/servers/1234/action',
{'evacuate': {'host': 'fake_target_host',
'force': True}})
class ServersV230Test(ServersV229Test):
def setUp(self):
super(ServersV230Test, self).setUp()
self.cs.api_version = api_versions.APIVersion("2.30")
def test_live_migrate_server(self):
s = self.cs.servers.get(1234)
ret = s.live_migrate(host='hostname', block_migration='auto')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'os-migrateLive': {'host': 'hostname',
'block_migration': 'auto'}})
ret = self.cs.servers.live_migrate(s, host='hostname',
block_migration='auto',
force=True)
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'os-migrateLive': {'host': 'hostname',
'block_migration': 'auto',
'force': True}})

View File

@ -1758,6 +1758,19 @@ class ShellTest(utils.TestCase):
{'os-migrateLive': {'host': None,
'block_migration': 'auto'}})
def test_live_migration_v2_30(self):
self.run_command('live-migration sample-server hostname',
api_version='2.30')
self.assert_called('POST', '/servers/1234/action',
{'os-migrateLive': {'host': 'hostname',
'block_migration': 'auto'}})
self.run_command('live-migration --force sample-server hostname',
api_version='2.30')
self.assert_called('POST', '/servers/1234/action',
{'os-migrateLive': {'host': 'hostname',
'block_migration': 'auto',
'force': True}})
def test_live_migration_force_complete(self):
self.run_command('live-migration-force-complete sample-server 1',
api_version='2.22')
@ -1811,6 +1824,19 @@ class ShellTest(utils.TestCase):
self.assert_called('POST', '/servers/uuid3/action', body, pos=3)
self.assert_called('POST', '/servers/uuid4/action', body, pos=4)
def test_host_evacuate_live_2_30(self):
self.run_command('host-evacuate-live --force hyper '
'--target-host hostname',
api_version='2.30')
self.assert_called('GET', '/os-hypervisors/hyper/servers', pos=0)
body = {'os-migrateLive': {'host': 'hostname',
'block_migration': 'auto',
'force': True}}
self.assert_called('POST', '/servers/uuid1/action', body, pos=1)
self.assert_called('POST', '/servers/uuid2/action', body, pos=2)
self.assert_called('POST', '/servers/uuid3/action', body, pos=3)
self.assert_called('POST', '/servers/uuid4/action', body, pos=4)
def test_host_evacuate_live_with_block_migration(self):
self.run_command('host-evacuate-live --block-migrate hyper')
self.assert_called('GET', '/os-hypervisors/hyper/servers', pos=0)

View File

@ -26,14 +26,16 @@ def _server_live_migrate(cs, server, args):
self.error_message = error_message
success = True
error_message = ""
update_kwargs = {}
try:
# API >= 2.30
if 'force' in args and args.force:
update_kwargs['force'] = args.force
# API 2.0->2.24
if 'disk_over_commit' in args:
cs.servers.live_migrate(server['uuid'], args.target_host,
args.block_migrate, args.disk_over_commit)
else: # API 2.25+
cs.servers.live_migrate(server['uuid'], args.target_host,
args.block_migrate)
update_kwargs['disk_over_commit'] = args.disk_over_commit
cs.servers.live_migrate(server['uuid'], args.target_host,
args.block_migrate, **update_kwargs)
except Exception as e:
success = False
error_message = _("Error while live migrating instance: %s") % e
@ -72,6 +74,13 @@ def _server_live_migrate(cs, server, args):
dest='max_servers',
metavar='<max_servers>',
help='Maximum number of servers to live migrate simultaneously')
@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.30')
def do_host_evacuate_live(cs, args):
"""Live migrate all instances of the specified host
to other available hosts.

View File

@ -432,7 +432,7 @@ class Server(base.Resource):
block_migration,
disk_over_commit)
@api_versions.wraps("2.25")
@api_versions.wraps("2.25", "2.29")
def live_migrate(self, host=None, block_migration=None):
"""
Migrates a running instance to a new machine.
@ -446,6 +446,21 @@ class Server(base.Resource):
block_migration = "auto"
return self.manager.live_migrate(self, host, block_migration)
@api_versions.wraps("2.30")
def live_migrate(self, host=None, block_migration=None, force=None):
"""
Migrates a running instance to a new machine.
:param host: destination host name.
:param block_migration: if True, do block_migration, the default
value is None which is mapped to 'auto'.
:param force: force to bypass the scheduler if host is provided.
:returns: An instance of novaclient.base.TupleWithMeta
"""
if block_migration is None:
block_migration = "auto"
return self.manager.live_migrate(self, host, block_migration, force)
def reset_state(self, state='error'):
"""
Reset the state of an instance to active or error.
@ -1578,7 +1593,7 @@ class ServerManager(base.BootingManagerWithFind):
'block_migration': block_migration,
'disk_over_commit': disk_over_commit})
@api_versions.wraps('2.25')
@api_versions.wraps('2.25', '2.29')
def live_migrate(self, server, host, block_migration):
"""
Migrates a running instance to a new machine.
@ -1593,6 +1608,23 @@ class ServerManager(base.BootingManagerWithFind):
{'host': host,
'block_migration': block_migration})
@api_versions.wraps('2.30')
def live_migrate(self, server, host, block_migration, force=None):
"""
Migrates a running instance to a new machine.
:param server: instance id which comes from nova list.
:param host: destination host name.
:param block_migration: if True, do block_migration, can be set as
'auto'
:param force: forces to bypass the scheduler if host is provided.
:returns: An instance of novaclient.base.TupleWithMeta
"""
body = {'host': host, 'block_migration': block_migration}
if force:
body['force'] = force
return self._action('os-migrateLive', server, body)
def reset_state(self, server, state='error'):
"""
Reset the state of an instance to active or error.

View File

@ -3768,16 +3768,24 @@ def _print_aggregate_details(aggregate):
'novaclient 3.3.0.') % '--disk-over-commit',
help=argparse.SUPPRESS,
start_version="2.0", end_version="2.24")
@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.30')
def do_live_migration(cs, args):
"""Migrate running server to a new machine."""
update_kwargs = {}
if 'disk_over_commit' in args:
_find_server(cs, args.server).live_migrate(args.host,
args.block_migrate,
args.disk_over_commit)
else:
_find_server(cs, args.server).live_migrate(args.host,
args.block_migrate)
update_kwargs['disk_over_commit'] = args.disk_over_commit
if 'force' in args and args.force:
update_kwargs['force'] = args.force
_find_server(cs, args.server).live_migrate(args.host, args.block_migrate,
**update_kwargs)
@api_versions.wraps("2.22")