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:
parent
1aa042e0cb
commit
c649678991
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.29")
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.30")
|
||||
|
@ -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')
|
||||
|
@ -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}})
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user