summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPawel Koniszewski <pawel.koniszewski@intel.com>2016-02-15 19:34:44 +0100
committerPaul Murray <pmurray@hpe.com>2016-02-25 13:59:11 +0000
commit62c76301a281b41282531f6419d55823106270d1 (patch)
treec4d92be1c6e5c5c0e276a8df5a273d65c6b62219
parentcd88097ff59ad40002ac4f624b53efe72bc84386 (diff)
downloadpython-novaclient-62c76301a281b41282531f6419d55823106270d1.tar.gz
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
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/fixture_data/server_migrations.py27
-rw-r--r--novaclient/tests/unit/v2/fakes.py3
-rw-r--r--novaclient/tests/unit/v2/test_server_migrations.py33
-rw-r--r--novaclient/tests/unit/v2/test_shell.py6
-rw-r--r--novaclient/v2/client.py3
-rw-r--r--novaclient/v2/server_migrations.py42
-rw-r--r--novaclient/v2/shell.py9
8 files changed, 124 insertions, 1 deletions
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index f5588d09..509d2a20 100644
--- a/novaclient/__init__.py
+++ b/novaclient/__init__.py
@@ -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")
diff --git a/novaclient/tests/unit/fixture_data/server_migrations.py b/novaclient/tests/unit/fixture_data/server_migrations.py
new file mode 100644
index 00000000..3aed49a5
--- /dev/null
+++ b/novaclient/tests/unit/fixture_data/server_migrations.py
@@ -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)
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index e0efff06..d3d1e405 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -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):
diff --git a/novaclient/tests/unit/v2/test_server_migrations.py b/novaclient/tests/unit/v2/test_server_migrations.py
new file mode 100644
index 00000000..12c5a269
--- /dev/null
+++ b/novaclient/tests/unit/v2/test_server_migrations.py
@@ -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)
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index eb86eee9..cb30ce40 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -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)
diff --git a/novaclient/v2/client.py b/novaclient/v2/client.py
index a3ec98fe..56339a34 100644
--- a/novaclient/v2/client.py
+++ b/novaclient/v2/client.py
@@ -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:
diff --git a/novaclient/v2/server_migrations.py b/novaclient/v2/server_migrations.py
new file mode 100644
index 00000000..476c0a80
--- /dev/null
+++ b/novaclient/v2/server_migrations.py
@@ -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)
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index 95b892d8..d5087ca6 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -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',