Support for forcing live migration to complete

In API microversion 2.22 in Nova there is new ServerMigrations resource
that allows opertators to force on-going live migration to complete:
https://review.openstack.org/#/c/245921/

This patch implements new method in python-novaclient to take advantage
of the new API:
nova live-migration-force-complete <instance_id/name> <migration_id>

Change-Id: I823c20b4e0c7b63e905f564a7dff13d3fb314a26
Implements blueprint pause-vm-during-live-migration
This commit is contained in:
Pawel Koniszewski 2016-02-15 19:34:44 +01:00 committed by Paul Murray
parent cd88097ff5
commit 62c76301a2
8 changed files with 124 additions and 1 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.21")
API_MAX_VERSION = api_versions.APIVersion("2.22")

View File

@ -0,0 +1,27 @@
# Copyright 2016 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from novaclient.tests.unit.fixture_data import base
class Fixture(base.Fixture):
base_url = 'servers'
def setUp(self):
super(Fixture, self).setUp()
url = self.url('1234', 'migrations', '1', 'action')
self.requests.register_uri('POST', url,
status_code=202,
headers=self.json_headers)

View File

@ -2432,6 +2432,9 @@ class FakeHTTPClient(base_client.HTTPClient):
self, **kw):
return (202, {}, None)
def post_servers_1234_migrations_1_action(self, body):
return (202, {}, None)
class FakeSessionClient(fakes.FakeClient, client.Client):

View File

@ -0,0 +1,33 @@
# Copyright 2016 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from novaclient import api_versions
from novaclient.tests.unit.fixture_data import client
from novaclient.tests.unit.fixture_data import server_migrations as data
from novaclient.tests.unit import utils
class ServerMigrationsTest(utils.FixturedTestCase):
client_fixture_class = client.V1
data_fixture_class = data.Fixture
def setUp(self):
super(ServerMigrationsTest, self).setUp()
self.cs.api_version = api_versions.APIVersion("2.22")
def test_live_migration_force_complete(self):
body = {'force_complete': None}
self.cs.server_migrations.live_migrate_force_complete(1234, 1)
self.assert_called('POST', '/servers/1234/migrations/1/action', body)

View File

@ -1681,6 +1681,12 @@ class ShellTest(utils.TestCase):
'block_migration': True,
'disk_over_commit': True}})
def test_live_migration_force_complete(self):
self.run_command('live-migration-force-complete sample-server 1',
api_version='2.22')
self.assert_called('POST', '/servers/1234/migrations/1/action',
{'force_complete': None})
def test_host_evacuate_live_with_no_target_host(self):
self.run_command('host-evacuate-live hyper')
self.assert_called('GET', '/os-hypervisors/hyper/servers', pos=0)

View File

@ -41,6 +41,7 @@ from novaclient.v2 import security_group_default_rules
from novaclient.v2 import security_group_rules
from novaclient.v2 import security_groups
from novaclient.v2 import server_groups
from novaclient.v2 import server_migrations
from novaclient.v2 import servers
from novaclient.v2 import services
from novaclient.v2 import usage
@ -167,6 +168,8 @@ class Client(object):
self.availability_zones = \
availability_zones.AvailabilityZoneManager(self)
self.server_groups = server_groups.ServerGroupsManager(self)
self.server_migrations = \
server_migrations.ServerMigrationsManager(self)
# Add in any extensions...
if extensions:

View File

@ -0,0 +1,42 @@
# Copyright 2016 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from novaclient import api_versions
from novaclient import base
class ServerMigration(base.Resource):
def __repr__(self):
return "<ServerMigration>"
class ServerMigrationsManager(base.Manager):
resource_class = ServerMigration
@api_versions.wraps("2.22")
def live_migrate_force_complete(self, server, migration):
"""
Force on-going live migration to complete
:param server: The :class:`Server` (or its ID)
:param migration: Migration id that will be forced to complete
:returns: An instance of novaclient.base.TupleWithMeta
"""
body = {'force_complete': None}
resp, body = self.api.client.post(
'/servers/%s/migrations/%s/action' % (base.getid(server),
base.getid(migration)),
body=body)
return self.convert_into_with_meta(body, resp)

View File

@ -3838,6 +3838,15 @@ def do_live_migration(cs, args):
args.disk_over_commit)
@api_versions.wraps("2.22")
@cliutils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
@cliutils.arg('migration', metavar='<migration>', help=_('ID of migration.'))
def do_live_migration_force_complete(cs, args):
"""Force on-going live migration to complete."""
server = _find_server(cs, args.server)
cs.server_migrations.live_migrate_force_complete(server, args.migration)
@cliutils.arg(
'--all-tenants',
action='store_const',