summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-03-01 15:11:11 +0000
committerGerrit Code Review <review@openstack.org>2016-03-01 15:11:12 +0000
commit3a3a5c8ac6c2e767cd30f93401226f5c64717553 (patch)
tree2cc2dd2c4fea5aaf06b9f4edbee81760d23dd167
parenteb461f082ba622dbc3b431b3d3deba5b950d60f6 (diff)
parente0c7d2c6731744374ea83385305624254454b0ed (diff)
downloadpython-novaclient-3a3a5c8ac6c2e767cd30f93401226f5c64717553.tar.gz
Merge "Add two server-migration commands and bump migration-list command"
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/fixture_data/server_migrations.py51
-rw-r--r--novaclient/tests/unit/v2/contrib/test_migrations.py12
-rw-r--r--novaclient/tests/unit/v2/fakes.py95
-rw-r--r--novaclient/tests/unit/v2/test_server_migrations.py49
-rw-r--r--novaclient/tests/unit/v2/test_shell.py14
-rw-r--r--novaclient/v2/contrib/migrations.py15
-rw-r--r--novaclient/v2/server_migrations.py27
-rw-r--r--novaclient/v2/shell.py36
9 files changed, 279 insertions, 22 deletions
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index 509d2a20..c7bff335 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.22")
+API_MAX_VERSION = api_versions.APIVersion("2.23")
diff --git a/novaclient/tests/unit/fixture_data/server_migrations.py b/novaclient/tests/unit/fixture_data/server_migrations.py
index 3aed49a5..93f299fb 100644
--- a/novaclient/tests/unit/fixture_data/server_migrations.py
+++ b/novaclient/tests/unit/fixture_data/server_migrations.py
@@ -25,3 +25,54 @@ class Fixture(base.Fixture):
self.requests.register_uri('POST', url,
status_code=202,
headers=self.json_headers)
+
+ get_migrations = {'migrations': [
+ {
+ "created_at": "2016-01-29T13:42:02.000000",
+ "dest_compute": "compute2",
+ "dest_host": "1.2.3.4",
+ "dest_node": "node2",
+ "id": 1,
+ "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe",
+ "source_compute": "compute1",
+ "source_node": "node1",
+ "status": "running",
+ "memory_total_bytes": 123456,
+ "memory_processed_bytes": 12345,
+ "memory_remaining_bytes": 120000,
+ "disk_total_bytes": 234567,
+ "disk_processed_bytes": 23456,
+ "disk_remaining_bytes": 230000,
+ "updated_at": "2016-01-29T13:42:02.000000"
+ }]}
+
+ url = self.url('1234', 'migrations')
+ self.requests.register_uri('GET', url,
+ status_code=200,
+ json=get_migrations,
+ headers=self.json_headers)
+
+ get_migration = {'migration': {
+ "created_at": "2016-01-29T13:42:02.000000",
+ "dest_compute": "compute2",
+ "dest_host": "1.2.3.4",
+ "dest_node": "node2",
+ "id": 1,
+ "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe",
+ "source_compute": "compute1",
+ "source_node": "node1",
+ "status": "running",
+ "memory_total_bytes": 123456,
+ "memory_processed_bytes": 12345,
+ "memory_remaining_bytes": 120000,
+ "disk_total_bytes": 234567,
+ "disk_processed_bytes": 23456,
+ "disk_remaining_bytes": 230000,
+ "updated_at": "2016-01-29T13:42:02.000000"
+ }}
+
+ url = self.url('1234', 'migrations', '1')
+ self.requests.register_uri('GET', url,
+ status_code=200,
+ json=get_migration,
+ headers=self.json_headers)
diff --git a/novaclient/tests/unit/v2/contrib/test_migrations.py b/novaclient/tests/unit/v2/contrib/test_migrations.py
index 29cac5d4..8d12633e 100644
--- a/novaclient/tests/unit/v2/contrib/test_migrations.py
+++ b/novaclient/tests/unit/v2/contrib/test_migrations.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from novaclient import api_versions
from novaclient import extension
from novaclient.tests.unit import utils
from novaclient.tests.unit.v2 import fakes
@@ -30,6 +31,17 @@ class MigrationsTest(utils.TestCase):
cs.assert_called('GET', '/os-migrations')
for m in ml:
self.assertIsInstance(m, migrations.Migration)
+ self.assertRaises(AttributeError, getattr, m, "migration_type")
+
+ def test_list_migrations_v223(self):
+ cs = fakes.FakeClient(extensions=extensions,
+ api_version=api_versions.APIVersion("2.23"))
+ ml = cs.migrations.list()
+ self.assert_request_id(ml, fakes.FAKE_REQUEST_ID_LIST)
+ cs.assert_called('GET', '/os-migrations')
+ for m in ml:
+ self.assertIsInstance(m, migrations.Migration)
+ self.assertEqual(m.migration_type, 'live-migration')
def test_list_migrations_with_filters(self):
ml = cs.migrations.list('host1', 'finished', 'child1')
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index d3d1e405..85f4b74b 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -23,8 +23,10 @@ import six
from six.moves.urllib import parse
import novaclient
+from novaclient import api_versions
from novaclient import client as base_client
from novaclient import exceptions
+from novaclient.i18n import _
from novaclient.tests.unit import fakes
from novaclient.tests.unit import utils
from novaclient.v2 import client
@@ -58,7 +60,8 @@ class FakeClient(fakes.FakeClient, client.Client):
'project_id', 'auth_url',
extensions=kwargs.get('extensions'),
direct_use=False)
- self.api_version = api_version
+ self.api_version = api_version or api_versions.APIVersion("2.1")
+ kwargs["api_version"] = self.api_version
self.client = FakeHTTPClient(**kwargs)
@@ -91,6 +94,7 @@ class FakeHTTPClient(base_client.HTTPClient):
self.http_log_debug = 'http_log_debug'
self.last_request_id = None
self.management_url = self.get_endpoint()
+ self.api_version = kwargs.get("api_version")
def _cs_request(self, url, method, **kwargs):
# Check that certain things are called correctly
@@ -2367,21 +2371,26 @@ class FakeHTTPClient(base_client.HTTPClient):
return self.get_os_cells_capacities()
def get_os_migrations(self, **kw):
- migrations = {'migrations': [
- {
- "created_at": "2012-10-29T13:42:02.000000",
- "dest_compute": "compute2",
- "dest_host": "1.2.3.4",
- "dest_node": "node2",
- "id": 1234,
- "instance_uuid": "instance_id_123",
- "new_instance_type_id": 2,
- "old_instance_type_id": 1,
- "source_compute": "compute1",
- "source_node": "node1",
- "status": "Done",
- "updated_at": "2012-10-29T13:42:02.000000"
- }]}
+ migration = {
+ "created_at": "2012-10-29T13:42:02.000000",
+ "dest_compute": "compute2",
+ "dest_host": "1.2.3.4",
+ "dest_node": "node2",
+ "id": 1234,
+ "instance_uuid": "instance_id_123",
+ "new_instance_type_id": 2,
+ "old_instance_type_id": 1,
+ "source_compute": "compute1",
+ "source_node": "node1",
+ "status": "Done",
+ "updated_at": "2012-10-29T13:42:02.000000"
+ }
+
+ if self.api_version >= api_versions.APIVersion("2.23"):
+ migration.update({"migration_type": "live-migration"})
+
+ migrations = {'migrations': [migration]}
+
return (200, FAKE_RESPONSE_HEADERS, migrations)
def post_os_server_external_events(self, **kw):
@@ -2435,6 +2444,57 @@ class FakeHTTPClient(base_client.HTTPClient):
def post_servers_1234_migrations_1_action(self, body):
return (202, {}, None)
+ def get_servers_1234_migrations_1(self, **kw):
+ # TODO(Shaohe Feng) this condition check can be a decorator
+ if self.api_version < api_versions.APIVersion("2.23"):
+ raise exceptions.UnsupportedVersion(_("Unsupport version %s")
+ % self.api_version)
+ migration = {"migration": {
+ "created_at": "2016-01-29T13:42:02.000000",
+ "dest_compute": "compute2",
+ "dest_host": "1.2.3.4",
+ "dest_node": "node2",
+ "id": 1,
+ "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe",
+ "source_compute": "compute1",
+ "source_node": "node1",
+ "status": "running",
+ "memory_total_bytes": 123456,
+ "memory_processed_bytes": 12345,
+ "memory_remaining_bytes": 120000,
+ "disk_total_bytes": 234567,
+ "disk_processed_bytes": 23456,
+ "disk_remaining_bytes": 230000,
+ "updated_at": "2016-01-29T13:42:02.000000"
+ }}
+ return (200, FAKE_RESPONSE_HEADERS, migration)
+
+ def get_servers_1234_migrations(self, **kw):
+ # TODO(Shaohe Feng) this condition check can be a decorator
+ if self.api_version < api_versions.APIVersion("2.23"):
+ raise exceptions.UnsupportedVersion(_("Unsupport version %s")
+ % self.api_version)
+ migrations = {'migrations': [
+ {
+ "created_at": "2016-01-29T13:42:02.000000",
+ "dest_compute": "compute2",
+ "dest_host": "1.2.3.4",
+ "dest_node": "node2",
+ "id": 1,
+ "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe",
+ "source_compute": "compute1",
+ "source_node": "node1",
+ "status": "running",
+ "memory_total_bytes": 123456,
+ "memory_processed_bytes": 12345,
+ "memory_remaining_bytes": 120000,
+ "disk_total_bytes": 234567,
+ "disk_processed_bytes": 23456,
+ "disk_remaining_bytes": 230000,
+ "updated_at": "2016-01-29T13:42:02.000000"
+ }]}
+ return (200, FAKE_RESPONSE_HEADERS, migrations)
+
class FakeSessionClient(fakes.FakeClient, client.Client):
@@ -2443,6 +2503,7 @@ class FakeSessionClient(fakes.FakeClient, client.Client):
'project_id', 'auth_url',
extensions=kwargs.get('extensions'),
api_version=api_version, direct_use=False)
+ kwargs['api_version'] = api_version
self.client = FakeSessionMockClient(**kwargs)
@@ -2461,7 +2522,7 @@ class FakeSessionMockClient(base_client.SessionClient, FakeHTTPClient):
self.interface = None
self.region_name = None
self.version = None
-
+ self.api_version = kwargs.get('api_version')
self.auth.get_auth_ref.return_value.project_id = 'tenant_id'
def request(self, url, method, **kwargs):
diff --git a/novaclient/tests/unit/v2/test_server_migrations.py b/novaclient/tests/unit/v2/test_server_migrations.py
index 12c5a269..e4a2b4ba 100644
--- a/novaclient/tests/unit/v2/test_server_migrations.py
+++ b/novaclient/tests/unit/v2/test_server_migrations.py
@@ -14,9 +14,12 @@
# under the License.
from novaclient import api_versions
+from novaclient import base
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
+from novaclient.tests.unit.v2 import fakes
+from novaclient.v2 import server_migrations
class ServerMigrationsTest(utils.FixturedTestCase):
@@ -31,3 +34,49 @@ class ServerMigrationsTest(utils.FixturedTestCase):
body = {'force_complete': None}
self.cs.server_migrations.live_migrate_force_complete(1234, 1)
self.assert_called('POST', '/servers/1234/migrations/1/action', body)
+
+
+class ServerMigrationsTestV223(ServerMigrationsTest):
+
+ migration = {
+ "created_at": "2016-01-29T13:42:02.000000",
+ "dest_compute": "compute2",
+ "dest_host": "1.2.3.4",
+ "dest_node": "node2",
+ "id": 1,
+ "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe",
+ "source_compute": "compute1",
+ "source_node": "node1",
+ "status": "running",
+ "memory_total_bytes": 123456,
+ "memory_processed_bytes": 12345,
+ "memory_remaining_bytes": 120000,
+ "disk_total_bytes": 234567,
+ "disk_processed_bytes": 23456,
+ "disk_remaining_bytes": 230000,
+ "updated_at": "2016-01-29T13:42:02.000000"
+ }
+
+ def setUp(self):
+ super(ServerMigrationsTestV223, self).setUp()
+ self.cs.api_version = api_versions.APIVersion("2.23")
+
+ def test_list_migrations(self):
+ ml = self.cs.server_migrations.list(1234)
+
+ self.assertIsInstance(ml, base.ListWithMeta)
+ self.assert_request_id(ml, fakes.FAKE_REQUEST_ID_LIST)
+ for k in self.migration:
+ self.assertEqual(self.migration[k], getattr(ml[0], k))
+
+ self.assert_called('GET', '/servers/1234/migrations')
+
+ def test_get_migration(self):
+ migration = self.cs.server_migrations.get(1234, 1)
+
+ self.assertIsInstance(migration, server_migrations.ServerMigration)
+ for k in migration._info:
+ self.assertEqual(self.migration[k], migration._info[k])
+ self.assert_request_id(migration, fakes.FAKE_REQUEST_ID_LIST)
+
+ self.assert_called('GET', '/servers/1234/migrations/1')
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index cb30ce40..7d1502eb 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -1687,6 +1687,16 @@ class ShellTest(utils.TestCase):
self.assert_called('POST', '/servers/1234/migrations/1/action',
{'force_complete': None})
+ def test_list_migrations(self):
+ self.run_command('server-migration-list sample-server',
+ api_version='2.23')
+ self.assert_called('GET', '/servers/1234/migrations')
+
+ def test_get_migration(self):
+ self.run_command('server-migration-show sample-server 1',
+ api_version='2.23')
+ self.assert_called('GET', '/servers/1234/migrations/1')
+
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)
@@ -2501,6 +2511,10 @@ class ShellTest(utils.TestCase):
self.run_command('migration-list')
self.assert_called('GET', '/os-migrations')
+ def test_migration_list_v223(self):
+ self.run_command('migration-list', api_version="2.23")
+ self.assert_called('GET', '/os-migrations')
+
def test_migration_list_with_filters(self):
self.run_command('migration-list --host host1 --cell_name child1 '
'--status finished')
diff --git a/novaclient/v2/contrib/migrations.py b/novaclient/v2/contrib/migrations.py
index 15959818..6af81318 100644
--- a/novaclient/v2/contrib/migrations.py
+++ b/novaclient/v2/contrib/migrations.py
@@ -16,6 +16,7 @@ migration interface
from six.moves.urllib import parse
+from novaclient import api_versions
from novaclient import base
from novaclient.i18n import _
from novaclient.openstack.common import cliutils
@@ -71,11 +72,11 @@ class MigrationManager(base.ManagerWithFind):
help=_('Fetch migrations for the given cell_name.'))
def do_migration_list(cs, args):
"""Print a list of migrations."""
- _print_migrations(cs.migrations.list(args.host, args.status,
- args.cell_name))
+ migrations = cs.migrations.list(args.host, args.status, args.cell_name)
+ _print_migrations(cs, migrations)
-def _print_migrations(migrations):
+def _print_migrations(cs, migrations):
fields = ['Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
'Dest Host', 'Status', 'Instance UUID', 'Old Flavor',
'New Flavor', 'Created At', 'Updated At']
@@ -86,6 +87,14 @@ def _print_migrations(migrations):
def new_flavor(migration):
return migration.new_instance_type_id
+ def migration_type(migration):
+ return migration.migration_type
+
formatters = {'Old Flavor': old_flavor, 'New Flavor': new_flavor}
+ if cs.api_version >= api_versions.APIVersion("2.23"):
+ fields.insert(0, "Id")
+ fields.append("Type")
+ formatters.update({"Type": migration_type})
+
utils.print_list(migrations, fields, formatters)
diff --git a/novaclient/v2/server_migrations.py b/novaclient/v2/server_migrations.py
index 476c0a80..68ee94c9 100644
--- a/novaclient/v2/server_migrations.py
+++ b/novaclient/v2/server_migrations.py
@@ -22,7 +22,7 @@ class ServerMigration(base.Resource):
return "<ServerMigration>"
-class ServerMigrationsManager(base.Manager):
+class ServerMigrationsManager(base.ManagerWithFind):
resource_class = ServerMigration
@api_versions.wraps("2.22")
@@ -40,3 +40,28 @@ class ServerMigrationsManager(base.Manager):
base.getid(migration)),
body=body)
return self.convert_into_with_meta(body, resp)
+
+ @api_versions.wraps("2.23")
+ def get(self, server, migration):
+ """
+ Get a migration of a specified server
+
+ :param server: The :class:`Server` (or its ID)
+ :param migration: Migration id that will be gotten.
+ :returns: An instance of
+ novaclient.v2.server_migrations.ServerMigration
+ """
+ return self._get('/servers/%s/migrations/%s' %
+ (base.getid(server), base.getid(migration)),
+ 'migration')
+
+ @api_versions.wraps("2.23")
+ def list(self, server):
+ """
+ Get a migrations list of a specified server
+
+ :param server: The :class:`Server` (or its ID)
+ :returns: An instance of novaclient.base.ListWithMeta
+ """
+ return self._list(
+ '/servers/%s/migrations' % base.getid(server), "migrations")
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index 9693fc71..1dc728f8 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -3847,6 +3847,42 @@ def do_live_migration_force_complete(cs, args):
cs.server_migrations.live_migrate_force_complete(server, args.migration)
+@api_versions.wraps("2.23")
+@cliutils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
+def do_server_migration_list(cs, args):
+ """Get the migrations list of specified server."""
+ server = _find_server(cs, args.server)
+ migrations = cs.server_migrations.list(server)
+
+ fields = ['Id', 'Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status', 'Server UUID',
+ 'Created At', 'Updated At']
+
+ format_name = ["Total Memory Bytes", "Processed Memory Bytes",
+ "Remaining Memory Bytes", "Total Disk Bytes",
+ "Processed Disk Bytes", "Remaining Disk Bytes"]
+
+ format_key = ["memory_total_bytes", "memory_processed_bytes",
+ "memory_remaining_bytes", "disk_total_bytes",
+ "disk_processed_bytes", "disk_remaining_bytes"]
+
+ formatters = map(lambda field: utils._make_field_formatter(field)[1],
+ format_key)
+ formatters = dict(zip(format_name, formatters))
+
+ utils.print_list(migrations, fields + format_name, formatters)
+
+
+@api_versions.wraps("2.23")
+@cliutils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
+@cliutils.arg('migration', metavar='<migration>', help=_('ID of migration.'))
+def do_server_migration_show(cs, args):
+ """Get the migration of specified server."""
+ server = _find_server(cs, args.server)
+ migration = cs.server_migrations.get(server, args.migration)
+ utils.print_dict(migration._info)
+
+
@cliutils.arg(
'--all-tenants',
action='store_const',