summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-10-12 16:01:52 +0000
committerGerrit Code Review <review@openstack.org>2020-10-12 16:01:52 +0000
commitad2ac13c97ab51c00a69f67b8cd5027328408bc0 (patch)
tree1e0e76201f3c5454e3f92e8804d6e8f8c2c82829 /openstackclient
parenta48c05b90a376ce33e2f0a2d321b8c851a6ef0b0 (diff)
parentb77c28d2954a2c5861a3a6a1df29d8de448f7c08 (diff)
downloadpython-openstackclient-ad2ac13c97ab51c00a69f67b8cd5027328408bc0.tar.gz
Merge "Add server migration list CLI"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/compute/v2/server.py161
-rw-r--r--openstackclient/tests/unit/compute/v2/fakes.py90
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py484
3 files changed, 735 insertions, 0 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index e5a7a328..eecf4211 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -1814,6 +1814,167 @@ revert to release the new server and restart the old one.""")
raise SystemExit
+class ListMigration(command.Command):
+ _description = _("""List server migrations.""")
+
+ def get_parser(self, prog_name):
+ parser = super(ListMigration, self).get_parser(prog_name)
+ parser.add_argument(
+ "--server",
+ metavar="<server>",
+ dest='server',
+ default=None,
+ help=_('Server to show migration details (name or ID).')
+ )
+ parser.add_argument(
+ "--host",
+ metavar="<host>",
+ default=None,
+ help=_('Fetch migrations for the given host.')
+ )
+ parser.add_argument(
+ "--status",
+ metavar="<status>",
+ default=None,
+ help=_('Fetch migrations for the given status.')
+ )
+ parser.add_argument(
+ "--marker",
+ metavar="<marker>",
+ dest='marker',
+ default=None,
+ help=_("The last migration of the previous page; displays list "
+ "of migrations after 'marker'. Note that the marker is "
+ "the migration UUID. (Supported with "
+ "``--os-compute-api-version`` 2.59 or greater.)")
+ )
+ parser.add_argument(
+ "--limit",
+ metavar="<limit>",
+ dest='limit',
+ type=int,
+ default=None,
+ help=_("Maximum number of migrations to display. Note that there "
+ "is a configurable max limit on the server, and the limit "
+ "that is used will be the minimum of what is requested "
+ "here and what is configured in the server. "
+ "(Supported with ``--os-compute-api-version`` 2.59 "
+ "or greater.)")
+ )
+ parser.add_argument(
+ '--changes-since',
+ dest='changes_since',
+ metavar='<changes-since>',
+ default=None,
+ help=_("List only migrations changed later or equal to a certain "
+ "point of time. The provided time should be an ISO 8061 "
+ "formatted time, e.g. ``2016-03-04T06:27:59Z``. "
+ "(Supported with ``--os-compute-api-version`` 2.59 "
+ "or greater.)")
+ )
+ parser.add_argument(
+ '--changes-before',
+ dest='changes_before',
+ metavar='<changes-before>',
+ default=None,
+ help=_("List only migrations changed earlier or equal to a "
+ "certain point of time. The provided time should be an ISO "
+ "8061 formatted time, e.g. ``2016-03-04T06:27:59Z``. "
+ "(Supported with ``--os-compute-api-version`` 2.66 or "
+ "greater.)")
+ )
+ parser.add_argument(
+ '--project',
+ metavar='<project>',
+ dest='project_id',
+ default=None,
+ help=_("Filter the migrations by the given project ID. "
+ "(Supported with ``--os-compute-api-version`` 2.80 "
+ "or greater.)"),
+ )
+ parser.add_argument(
+ '--user',
+ metavar='<user>',
+ dest='user_id',
+ default=None,
+ help=_("Filter the migrations by the given user ID. "
+ "(Supported with ``--os-compute-api-version`` 2.80 "
+ "or greater.)"),
+ )
+ return parser
+
+ def print_migrations(self, parsed_args, compute_client, migrations):
+ columns = ['Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status',
+ 'Server UUID', 'Old Flavor', 'New Flavor',
+ 'Created At', 'Updated At']
+
+ # Insert migrations UUID after ID
+ if compute_client.api_version >= api_versions.APIVersion("2.59"):
+ columns.insert(0, "UUID")
+
+ # TODO(brinzhang): It also suppports filter migrations by type
+ # since 2.1. https://review.opendev.org/#/c/675117 supported
+ # filtering the migrations by 'migration_type' and 'source_compute'
+ # in novaclient, that will be added in OSC by follow-up.
+ if compute_client.api_version >= api_versions.APIVersion("2.23"):
+ columns.insert(0, "Id")
+ columns.insert(len(columns) - 2, "Type")
+
+ if compute_client.api_version >= api_versions.APIVersion("2.80"):
+ if parsed_args.project_id:
+ columns.insert(len(columns) - 2, "Project")
+ if parsed_args.user_id:
+ columns.insert(len(columns) - 2, "User")
+
+ columns_header = columns
+ return (columns_header, (utils.get_item_properties(
+ mig, columns) for mig in migrations))
+
+ def take_action(self, parsed_args):
+ compute_client = self.app.client_manager.compute
+
+ search_opts = {
+ "host": parsed_args.host,
+ "server": parsed_args.server,
+ "status": parsed_args.status,
+ }
+
+ if (parsed_args.marker or parsed_args.limit or
+ parsed_args.changes_since):
+ if compute_client.api_version < api_versions.APIVersion("2.59"):
+ msg = _("marker, limit and/or changes_since is not supported "
+ "for --os-compute-api-version less than 2.59")
+ raise exceptions.CommandError(msg)
+ if parsed_args.marker:
+ search_opts['marker'] = parsed_args.marker
+ if parsed_args.limit:
+ search_opts['limit'] = parsed_args.limit
+ if parsed_args.changes_since:
+ search_opts['changes_since'] = parsed_args.changes_since
+
+ if parsed_args.changes_before:
+ if compute_client.api_version < api_versions.APIVersion("2.66"):
+ msg = _("changes_before is not supported for "
+ "--os-compute-api-version less than 2.66")
+ raise exceptions.CommandError(msg)
+ search_opts['changes_before'] = parsed_args.changes_before
+
+ if parsed_args.project_id or parsed_args.user_id:
+ if compute_client.api_version < api_versions.APIVersion("2.80"):
+ msg = _("Project and/or user is not supported for "
+ "--os-compute-api-version less than 2.80")
+ raise exceptions.CommandError(msg)
+ if parsed_args.project_id:
+ search_opts['project_id'] = parsed_args.project_id
+ if parsed_args.user_id:
+ search_opts['user_id'] = parsed_args.user_id
+
+ migrations = compute_client.migrations.list(**search_opts)
+
+ return self.print_migrations(parsed_args, compute_client, migrations)
+
+
class PauseServer(command.Command):
_description = _("Pause server(s)")
diff --git a/openstackclient/tests/unit/compute/v2/fakes.py b/openstackclient/tests/unit/compute/v2/fakes.py
index 31430984..6aeb5da7 100644
--- a/openstackclient/tests/unit/compute/v2/fakes.py
+++ b/openstackclient/tests/unit/compute/v2/fakes.py
@@ -14,6 +14,7 @@
#
import copy
+import random
from unittest import mock
import uuid
@@ -198,6 +199,9 @@ class FakeComputev2Client(object):
self.instance_action = mock.Mock()
self.instance_action.resource_class = fakes.FakeResource(None, {})
+ self.migrations = mock.Mock()
+ self.migrations.resource_class = fakes.FakeResource(None, {})
+
self.auth_token = kwargs['token']
self.management_url = kwargs['endpoint']
@@ -1570,3 +1574,89 @@ class FakeRateLimit(object):
self.remain = remain
self.unit = unit
self.next_available = next_available
+
+
+class FakeServerMigration(object):
+ """Fake one or more server migrations."""
+
+ @staticmethod
+ def create_one_server_migration(attrs=None, methods=None):
+ """Create a fake server migration.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :param Dictionary methods:
+ A dictionary with all methods
+ :return:
+ A FakeResource object, with id, type, and so on
+ """
+ attrs = attrs or {}
+ methods = methods or {}
+
+ # Set default attributes.
+ migration_info = {
+ "dest_host": "10.0.2.15",
+ "status": "migrating",
+ "type": "migration",
+ "updated_at": "2017-01-31T08:03:25.000000",
+ "created_at": "2017-01-31T08:03:21.000000",
+ "dest_compute": "compute-" + uuid.uuid4().hex,
+ "id": random.randint(1, 999),
+ "source_node": "node-" + uuid.uuid4().hex,
+ "server": uuid.uuid4().hex,
+ "dest_node": "node-" + uuid.uuid4().hex,
+ "source_compute": "compute-" + uuid.uuid4().hex,
+ "uuid": uuid.uuid4().hex,
+ "old_instance_type_id": uuid.uuid4().hex,
+ "new_instance_type_id": uuid.uuid4().hex,
+ "project": uuid.uuid4().hex,
+ "user": uuid.uuid4().hex
+ }
+
+ # Overwrite default attributes.
+ migration_info.update(attrs)
+
+ migration = fakes.FakeResource(info=copy.deepcopy(migration_info),
+ methods=methods,
+ loaded=True)
+ return migration
+
+ @staticmethod
+ def create_server_migrations(attrs=None, methods=None, count=2):
+ """Create multiple fake server migrations.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :param Dictionary methods:
+ A dictionary with all methods
+ :param int count:
+ The number of server migrations to fake
+ :return:
+ A list of FakeResource objects faking the server migrations
+ """
+ migrations = []
+ for i in range(0, count):
+ migrations.append(
+ FakeServerMigration.create_one_server_migration(
+ attrs, methods))
+
+ return migrations
+
+ @staticmethod
+ def get_server_migrations(migrations=None, count=2):
+ """Get an iterable MagicMock object with a list of faked migrations.
+
+ If server migrations list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List migrations:
+ A list of FakeResource objects faking server migrations
+ :param int count:
+ The number of server migrations to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ server migrations
+ """
+ if migrations is None:
+ migrations = FakeServerMigration.create_server_migrations(count)
+ return mock.Mock(side_effect=migrations)
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index 59282b4a..c7bc88a2 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -3582,6 +3582,490 @@ class TestServerMigrate(TestServer):
self.assertNotCalled(self.servers_mock.live_migrate)
+class TestServerMigration(TestServer):
+
+ def setUp(self):
+ super(TestServerMigration, self).setUp()
+
+ # Get a shortcut to the compute client ServerManager Mock
+ self.servers_mock = self.app.client_manager.compute.servers
+ self.servers_mock.reset_mock()
+
+ self.migrations_mock = (
+ self.app.client_manager.compute.migrations)
+ self.migrations_mock.reset_mock()
+
+ self.server = self.setup_servers_mock(1)[0]
+
+ def setup_servers_mock(self, count):
+ servers = compute_fakes.FakeServer.create_servers(count=count)
+
+ # This is the return value for utils.find_resource()
+ self.servers_mock.get = compute_fakes.FakeServer.get_servers(servers)
+ return servers
+
+ def setup_server_migrations_mock(self, count):
+ return compute_fakes.FakeServerMigration.create_server_migrations(
+ count=count)
+
+
+class TestListMigration(TestServerMigration):
+ """Test fetch all migrations."""
+
+ MIGRATION_COLUMNS = [
+ 'Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status', 'Server UUID',
+ 'Old Flavor', 'New Flavor', 'Created At', 'Updated At'
+ ]
+
+ def setUp(self):
+ super(TestListMigration, self).setUp()
+
+ self.cmd = server.ListMigration(self.app, None)
+ self.migrations = self.setup_server_migrations_mock(3)
+ self.migrations_mock.list.return_value = self.migrations
+ self.setup_server_migrations_data(self.migrations)
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.20')
+
+ def setup_server_migrations_data(self, migrations):
+ self.data = (common_utils.get_item_properties(
+ s, self.MIGRATION_COLUMNS) for s in migrations)
+
+ def test_server_migraton_list(self):
+ arglist = [
+ '--status', 'migrating'
+ ]
+ verifylist = [
+ ('status', 'migrating')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'host': None,
+ 'server': None,
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
+
+class TestListMigrationV223(TestListMigration):
+ """Test fetch all migrations. """
+
+ MIGRATION_COLUMNS = [
+ 'Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status', 'Server UUID',
+ 'Old Flavor', 'New Flavor', 'Created At', 'Updated At'
+ ]
+
+ def setUp(self):
+ super(TestListMigrationV223, self).setUp()
+ self.cmd = server.ListMigration(self.app, None)
+ self.migrations = self.setup_server_migrations_mock(3)
+ self.migrations_mock.list.return_value = self.migrations
+ self.setup_server_migrations_data(self.migrations)
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.23')
+
+ def test_server_migraton_list(self):
+ arglist = [
+ '--status', 'migrating'
+ ]
+ verifylist = [
+ ('status', 'migrating')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'host': None,
+ 'server': None,
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.MIGRATION_COLUMNS.insert(0, "Id")
+ self.MIGRATION_COLUMNS.insert(
+ len(self.MIGRATION_COLUMNS) - 2, 'Type')
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
+
+class TestListMigrationV259(TestListMigration):
+ """Test fetch all migrations. """
+
+ MIGRATION_COLUMNS = [
+ 'Id', 'UUID', 'Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status', 'Server UUID',
+ 'Old Flavor', 'New Flavor', 'Type', 'Created At', 'Updated At'
+ ]
+
+ def setUp(self):
+ super(TestListMigrationV259, self).setUp()
+ self.cmd = server.ListMigration(self.app, None)
+ self.migrations = self.setup_server_migrations_mock(3)
+ self.migrations_mock.list.return_value = self.migrations
+ self.setup_server_migrations_data(self.migrations)
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ def test_server_migraton_list(self):
+ arglist = [
+ '--status', 'migrating',
+ '--limit', '1',
+ '--marker', 'test_kp',
+ '--changes-since', '2019-08-09T08:03:25Z'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('marker', 'test_kp'),
+ ('changes_since', '2019-08-09T08:03:25Z')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'limit': 1,
+ 'marker': 'test_kp',
+ 'host': None,
+ 'server': None,
+ 'changes_since': '2019-08-09T08:03:25Z',
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
+ def test_server_migraton_list_with_limit_pre_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.58')
+ arglist = [
+ '--status', 'migrating',
+ '--limit', '1'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_server_migraton_list_with_marker_pre_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.58')
+ arglist = [
+ '--status', 'migrating',
+ '--marker', 'test_kp'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('marker', 'test_kp')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_server_migraton_list_with_changes_since_pre_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.58')
+ arglist = [
+ '--status', 'migrating',
+ '--changes-since', '2019-08-09T08:03:25Z'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_since', '2019-08-09T08:03:25Z')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+
+class TestListMigrationV266(TestListMigration):
+ """Test fetch all migrations by changes-before. """
+
+ MIGRATION_COLUMNS = [
+ 'Id', 'UUID', 'Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status', 'Server UUID',
+ 'Old Flavor', 'New Flavor', 'Type', 'Created At', 'Updated At'
+ ]
+
+ def setUp(self):
+ super(TestListMigrationV266, self).setUp()
+ self.cmd = server.ListMigration(self.app, None)
+ self.migrations = self.setup_server_migrations_mock(3)
+ self.migrations_mock.list.return_value = self.migrations
+ self.setup_server_migrations_data(self.migrations)
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.66')
+
+ def test_server_migraton_list_with_changes_before(self):
+ arglist = [
+ '--status', 'migrating',
+ '--limit', '1',
+ '--marker', 'test_kp',
+ '--changes-since', '2019-08-07T08:03:25Z',
+ '--changes-before', '2019-08-09T08:03:25Z'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('marker', 'test_kp'),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'limit': 1,
+ 'marker': 'test_kp',
+ 'host': None,
+ 'server': None,
+ 'changes_since': '2019-08-07T08:03:25Z',
+ 'changes_before': '2019-08-09T08:03:25Z',
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
+ def test_server_migraton_list_with_changes_before_pre_v266(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.65')
+ arglist = [
+ '--status', 'migrating',
+ '--changes-before', '2019-08-09T08:03:25Z'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_before', '2019-08-09T08:03:25Z')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+
+class TestListMigrationV280(TestListMigration):
+ """Test fetch all migrations by user-id and/or project-id. """
+
+ MIGRATION_COLUMNS = [
+ 'Id', 'UUID', 'Source Node', 'Dest Node', 'Source Compute',
+ 'Dest Compute', 'Dest Host', 'Status', 'Server UUID',
+ 'Old Flavor', 'New Flavor', 'Type', 'Created At', 'Updated At'
+ ]
+
+ def setUp(self):
+ super(TestListMigrationV280, self).setUp()
+ self.cmd = server.ListMigration(self.app, None)
+ self.migrations = self.setup_server_migrations_mock(3)
+ self.migrations_mock.list.return_value = self.migrations
+ self.setup_server_migrations_data(self.migrations)
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.80')
+
+ def test_server_migraton_list_with_project(self):
+ arglist = [
+ '--status', 'migrating',
+ '--limit', '1',
+ '--marker', 'test_kp',
+ '--changes-since', '2019-08-07T08:03:25Z',
+ '--changes-before', '2019-08-09T08:03:25Z',
+ '--project', '0c2accde-644a-45fa-8c10-e76debc7fbc3'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('marker', 'test_kp'),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project_id', '0c2accde-644a-45fa-8c10-e76debc7fbc3')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'limit': 1,
+ 'marker': 'test_kp',
+ 'host': None,
+ 'server': None,
+ 'project_id': '0c2accde-644a-45fa-8c10-e76debc7fbc3',
+ 'changes_since': '2019-08-07T08:03:25Z',
+ 'changes_before': "2019-08-09T08:03:25Z",
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.MIGRATION_COLUMNS.insert(
+ len(self.MIGRATION_COLUMNS) - 2, "Project")
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+ # Clean up global variables MIGRATION_COLUMNS
+ self.MIGRATION_COLUMNS.remove('Project')
+
+ def test_get_migrations_with_project_pre_v280(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.79')
+ arglist = [
+ '--status', 'migrating',
+ '--changes-before', '2019-08-09T08:03:25Z',
+ '--project', '0c2accde-644a-45fa-8c10-e76debc7fbc3'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project_id', '0c2accde-644a-45fa-8c10-e76debc7fbc3')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_server_migraton_list_with_user(self):
+ arglist = [
+ '--status', 'migrating',
+ '--limit', '1',
+ '--marker', 'test_kp',
+ '--changes-since', '2019-08-07T08:03:25Z',
+ '--changes-before', '2019-08-09T08:03:25Z',
+ '--user', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('marker', 'test_kp'),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('user_id', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'limit': 1,
+ 'marker': 'test_kp',
+ 'host': None,
+ 'server': None,
+ 'user_id': 'dd214878-ca12-40fb-b035-fa7d2c1e86d6',
+ 'changes_since': '2019-08-07T08:03:25Z',
+ 'changes_before': "2019-08-09T08:03:25Z",
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.MIGRATION_COLUMNS.insert(
+ len(self.MIGRATION_COLUMNS) - 2, "User")
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+ # Clean up global variables MIGRATION_COLUMNS
+ self.MIGRATION_COLUMNS.remove('User')
+
+ def test_get_migrations_with_user_pre_v280(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.79')
+ arglist = [
+ '--status', 'migrating',
+ '--changes-before', '2019-08-09T08:03:25Z',
+ '--user', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('user_id', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_server_migraton_list_with_project_and_user(self):
+ arglist = [
+ '--status', 'migrating',
+ '--limit', '1',
+ '--changes-since', '2019-08-07T08:03:25Z',
+ '--changes-before', '2019-08-09T08:03:25Z',
+ '--project', '0c2accde-644a-45fa-8c10-e76debc7fbc3',
+ '--user', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project_id', '0c2accde-644a-45fa-8c10-e76debc7fbc3'),
+ ('user_id', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': 'migrating',
+ 'limit': 1,
+ 'host': None,
+ 'server': None,
+ 'project_id': '0c2accde-644a-45fa-8c10-e76debc7fbc3',
+ 'user_id': 'dd214878-ca12-40fb-b035-fa7d2c1e86d6',
+ 'changes_since': '2019-08-07T08:03:25Z',
+ 'changes_before': "2019-08-09T08:03:25Z",
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.MIGRATION_COLUMNS.insert(
+ len(self.MIGRATION_COLUMNS) - 2, "Project")
+ self.MIGRATION_COLUMNS.insert(
+ len(self.MIGRATION_COLUMNS) - 2, "User")
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+ # Clean up global variables MIGRATION_COLUMNS
+ self.MIGRATION_COLUMNS.remove('Project')
+ self.MIGRATION_COLUMNS.remove('User')
+
+ def test_get_migrations_with_project_and_user_pre_v280(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.79')
+ arglist = [
+ '--status', 'migrating',
+ '--changes-before', '2019-08-09T08:03:25Z',
+ '--project', '0c2accde-644a-45fa-8c10-e76debc7fbc3',
+ '--user', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6'
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project_id', '0c2accde-644a-45fa-8c10-e76debc7fbc3'),
+ ('user_id', 'dd214878-ca12-40fb-b035-fa7d2c1e86d6')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+
class TestServerPause(TestServer):
def setUp(self):