summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openstackclient/compute/v2/server.py463
-rw-r--r--openstackclient/compute/v2/server_migration.py485
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py985
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server_migration.py1028
-rw-r--r--setup.cfg9
5 files changed, 1518 insertions, 1452 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index 5da1984d..47c9c826 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -21,7 +21,6 @@ import io
import json
import logging
import os
-import uuid
from cliff import columns as cliff_columns
import iso8601
@@ -2812,468 +2811,6 @@ revert to release the new server and restart the old one.""")
raise SystemExit
-class ListMigration(command.Lister):
- _description = _("""List server migrations""")
-
- def get_parser(self, prog_name):
- parser = super(ListMigration, self).get_parser(prog_name)
- parser.add_argument(
- '--server',
- metavar='<server>',
- help=_(
- 'Filter migrations by server (name or ID)'
- )
- )
- parser.add_argument(
- '--host',
- metavar='<host>',
- help=_(
- 'Filter migrations by source or destination host'
- ),
- )
- parser.add_argument(
- '--status',
- metavar='<status>',
- help=_('Filter migrations by status')
- )
- parser.add_argument(
- '--type',
- metavar='<type>',
- choices=[
- 'evacuation', 'live-migration', 'cold-migration', 'resize',
- ],
- help=_('Filter migrations by type'),
- )
- parser.add_argument(
- '--marker',
- metavar='<marker>',
- 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 above)"
- ),
- )
- parser.add_argument(
- '--limit',
- metavar='<limit>',
- type=int,
- 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 above)"
- ),
- )
- parser.add_argument(
- '--changes-since',
- dest='changes_since',
- metavar='<changes-since>',
- 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 above)"
- ),
- )
- parser.add_argument(
- '--changes-before',
- dest='changes_before',
- metavar='<changes-before>',
- 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 above)"
- ),
- )
- parser.add_argument(
- '--project',
- metavar='<project>',
- help=_(
- "Filter migrations by project (name or ID) "
- "(supported with --os-compute-api-version 2.80 or above)"
- ),
- )
- identity_common.add_project_domain_option_to_parser(parser)
- parser.add_argument(
- '--user',
- metavar='<user>',
- help=_(
- "Filter migrations by user (name or ID) "
- "(supported with --os-compute-api-version 2.80 or above)"
- ),
- )
- identity_common.add_user_domain_option_to_parser(parser)
- return parser
-
- def print_migrations(self, parsed_args, compute_client, migrations):
- column_headers = [
- 'Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
- 'Dest Host', 'Status', 'Server UUID', 'Old Flavor', 'New Flavor',
- 'Created At', 'Updated At',
- ]
-
- # Response fields coming back from the REST API are not always exactly
- # the same as the column header names.
- columns = [
- 'source_node', 'dest_node', 'source_compute', 'dest_compute',
- 'dest_host', 'status', 'instance_uuid', 'old_instance_type_id',
- 'new_instance_type_id', 'created_at', 'updated_at',
- ]
-
- # Insert migrations UUID after ID
- if compute_client.api_version >= api_versions.APIVersion("2.59"):
- column_headers.insert(0, "UUID")
- columns.insert(0, "uuid")
-
- if compute_client.api_version >= api_versions.APIVersion("2.23"):
- column_headers.insert(0, "Id")
- columns.insert(0, "id")
- column_headers.insert(len(column_headers) - 2, "Type")
- columns.insert(len(columns) - 2, "migration_type")
-
- if compute_client.api_version >= api_versions.APIVersion("2.80"):
- if parsed_args.project:
- column_headers.insert(len(column_headers) - 2, "Project")
- columns.insert(len(columns) - 2, "project_id")
- if parsed_args.user:
- column_headers.insert(len(column_headers) - 2, "User")
- columns.insert(len(columns) - 2, "user_id")
-
- return (
- column_headers,
- (utils.get_item_properties(mig, columns) for mig in migrations),
- )
-
- def take_action(self, parsed_args):
- compute_client = self.app.client_manager.compute
- identity_client = self.app.client_manager.identity
-
- search_opts = {
- 'host': parsed_args.host,
- 'status': parsed_args.status,
- }
-
- if parsed_args.server:
- search_opts['instance_uuid'] = utils.find_resource(
- compute_client.servers,
- parsed_args.server,
- ).id
-
- if parsed_args.type:
- migration_type = parsed_args.type
- # we're using an alias because the default value is confusing
- if migration_type == 'cold-migration':
- migration_type = 'migration'
- search_opts['migration_type'] = migration_type
-
- if parsed_args.marker:
- if compute_client.api_version < api_versions.APIVersion('2.59'):
- msg = _(
- '--os-compute-api-version 2.59 or greater is required to '
- 'support the --marker option'
- )
- raise exceptions.CommandError(msg)
- search_opts['marker'] = parsed_args.marker
-
- if parsed_args.limit:
- if compute_client.api_version < api_versions.APIVersion('2.59'):
- msg = _(
- '--os-compute-api-version 2.59 or greater is required to '
- 'support the --limit option'
- )
- raise exceptions.CommandError(msg)
- search_opts['limit'] = parsed_args.limit
-
- if parsed_args.changes_since:
- if compute_client.api_version < api_versions.APIVersion('2.59'):
- msg = _(
- '--os-compute-api-version 2.59 or greater is required to '
- 'support the --changes-since option'
- )
- raise exceptions.CommandError(msg)
- search_opts['changes_since'] = parsed_args.changes_since
-
- if parsed_args.changes_before:
- if compute_client.api_version < api_versions.APIVersion('2.66'):
- msg = _(
- '--os-compute-api-version 2.66 or greater is required to '
- 'support the --changes-before option'
- )
- raise exceptions.CommandError(msg)
- search_opts['changes_before'] = parsed_args.changes_before
-
- if parsed_args.project:
- if compute_client.api_version < api_versions.APIVersion('2.80'):
- msg = _(
- '--os-compute-api-version 2.80 or greater is required to '
- 'support the --project option'
- )
- raise exceptions.CommandError(msg)
-
- search_opts['project_id'] = identity_common.find_project(
- identity_client,
- parsed_args.project,
- parsed_args.project_domain,
- ).id
-
- if parsed_args.user:
- if compute_client.api_version < api_versions.APIVersion('2.80'):
- msg = _(
- '--os-compute-api-version 2.80 or greater is required to '
- 'support the --user option'
- )
- raise exceptions.CommandError(msg)
-
- search_opts['user_id'] = identity_common.find_user(
- identity_client,
- parsed_args.user,
- parsed_args.user_domain,
- ).id
-
- migrations = compute_client.migrations.list(**search_opts)
-
- return self.print_migrations(parsed_args, compute_client, migrations)
-
-
-def _get_migration_by_uuid(compute_client, server_id, migration_uuid):
- for migration in compute_client.server_migrations.list(server_id):
- if migration.uuid == migration_uuid:
- return migration
- break
- else:
- msg = _(
- 'In-progress live migration %s is not found for server %s.'
- )
- raise exceptions.CommandError(msg % (migration_uuid, server_id))
-
-
-class ShowMigration(command.ShowOne):
- """Show an in-progress live migration for a given server.
-
- Note that it is not possible to show cold migrations or completed
- live-migrations. Use 'openstack server migration list' to get details for
- these.
- """
-
- def get_parser(self, prog_name):
- parser = super().get_parser(prog_name)
- parser.add_argument(
- 'server',
- metavar='<server>',
- help=_('Server (name or ID)'),
- )
- parser.add_argument(
- 'migration',
- metavar='<migration>',
- help=_("Migration (ID)"),
- )
- return parser
-
- def take_action(self, parsed_args):
- compute_client = self.app.client_manager.compute
-
- if compute_client.api_version < api_versions.APIVersion('2.24'):
- msg = _(
- '--os-compute-api-version 2.24 or greater is required to '
- 'support the server migration show command'
- )
- raise exceptions.CommandError(msg)
-
- if not parsed_args.migration.isdigit():
- try:
- uuid.UUID(parsed_args.migration)
- except ValueError:
- msg = _(
- 'The <migration> argument must be an ID or UUID'
- )
- raise exceptions.CommandError(msg)
-
- if compute_client.api_version < api_versions.APIVersion('2.59'):
- msg = _(
- '--os-compute-api-version 2.59 or greater is required to '
- 'retrieve server migrations by UUID'
- )
- raise exceptions.CommandError(msg)
-
- server = utils.find_resource(
- compute_client.servers,
- parsed_args.server,
- )
-
- # the nova API doesn't currently allow retrieval by UUID but it's a
- # reasonably common operation so emulate this behavior by listing
- # migrations - the responses are identical
- if not parsed_args.migration.isdigit():
- server_migration = _get_migration_by_uuid(
- compute_client, server.id, parsed_args.migration,
- )
- else:
- server_migration = compute_client.server_migrations.get(
- server.id, parsed_args.migration,
- )
-
- columns = (
- 'ID',
- 'Server UUID',
- 'Status',
- 'Source Compute',
- 'Source Node',
- 'Dest Compute',
- 'Dest Host',
- 'Dest Node',
- 'Memory Total Bytes',
- 'Memory Processed Bytes',
- 'Memory Remaining Bytes',
- 'Disk Total Bytes',
- 'Disk Processed Bytes',
- 'Disk Remaining Bytes',
- 'Created At',
- 'Updated At',
- )
-
- if compute_client.api_version >= api_versions.APIVersion('2.59'):
- columns += ('UUID',)
-
- if compute_client.api_version >= api_versions.APIVersion('2.80'):
- columns += ('User ID', 'Project ID')
-
- data = utils.get_item_properties(server_migration, columns)
- return columns, data
-
-
-class AbortMigration(command.Command):
- """Cancel an ongoing live migration.
-
- This command requires ``--os-compute-api-version`` 2.24 or greater.
- """
-
- def get_parser(self, prog_name):
- parser = super(AbortMigration, self).get_parser(prog_name)
- parser.add_argument(
- 'server',
- metavar='<server>',
- help=_('Server (name or ID)'),
- )
- parser.add_argument(
- 'migration',
- metavar='<migration>',
- help=_("Migration (ID)"),
- )
- return parser
-
- def take_action(self, parsed_args):
- compute_client = self.app.client_manager.compute
-
- if compute_client.api_version < api_versions.APIVersion('2.24'):
- msg = _(
- '--os-compute-api-version 2.24 or greater is required to '
- 'support the server migration abort command'
- )
- raise exceptions.CommandError(msg)
-
- if not parsed_args.migration.isdigit():
- try:
- uuid.UUID(parsed_args.migration)
- except ValueError:
- msg = _(
- 'The <migration> argument must be an ID or UUID'
- )
- raise exceptions.CommandError(msg)
-
- if compute_client.api_version < api_versions.APIVersion('2.59'):
- msg = _(
- '--os-compute-api-version 2.59 or greater is required to '
- 'abort server migrations by UUID'
- )
- raise exceptions.CommandError(msg)
-
- server = utils.find_resource(
- compute_client.servers,
- parsed_args.server,
- )
-
- # the nova API doesn't currently allow retrieval by UUID but it's a
- # reasonably common operation so emulate this behavior by listing
- # migrations - the responses are identical
- migration_id = parsed_args.migration
- if not parsed_args.migration.isdigit():
- migration_id = _get_migration_by_uuid(
- compute_client, server.id, parsed_args.migration,
- ).id
-
- compute_client.server_migrations.live_migration_abort(
- server.id, migration_id,
- )
-
-
-class ForceCompleteMigration(command.Command):
- """Force an ongoing live migration to complete.
-
- This command requires ``--os-compute-api-version`` 2.22 or greater.
- """
-
- def get_parser(self, prog_name):
- parser = super(ForceCompleteMigration, self).get_parser(prog_name)
- parser.add_argument(
- 'server',
- metavar='<server>',
- help=_('Server (name or ID)'),
- )
- parser.add_argument(
- 'migration',
- metavar='<migration>',
- help=_('Migration (ID)')
- )
- return parser
-
- def take_action(self, parsed_args):
- compute_client = self.app.client_manager.compute
-
- if compute_client.api_version < api_versions.APIVersion('2.22'):
- msg = _(
- '--os-compute-api-version 2.22 or greater is required to '
- 'support the server migration force complete command'
- )
- raise exceptions.CommandError(msg)
-
- if not parsed_args.migration.isdigit():
- try:
- uuid.UUID(parsed_args.migration)
- except ValueError:
- msg = _(
- 'The <migration> argument must be an ID or UUID'
- )
- raise exceptions.CommandError(msg)
-
- if compute_client.api_version < api_versions.APIVersion('2.59'):
- msg = _(
- '--os-compute-api-version 2.59 or greater is required to '
- 'abort server migrations by UUID'
- )
- raise exceptions.CommandError(msg)
-
- server = utils.find_resource(
- compute_client.servers,
- parsed_args.server,
- )
-
- # the nova API doesn't currently allow retrieval by UUID but it's a
- # reasonably common operation so emulate this behavior by listing
- # migrations - the responses are identical
- migration_id = parsed_args.migration
- if not parsed_args.migration.isdigit():
- migration_id = _get_migration_by_uuid(
- compute_client, server.id, parsed_args.migration,
- ).id
-
- compute_client.server_migrations.live_migrate_force_complete(
- server.id, migration_id,
- )
-
-
class PauseServer(command.Command):
_description = _("Pause server(s)")
diff --git a/openstackclient/compute/v2/server_migration.py b/openstackclient/compute/v2/server_migration.py
new file mode 100644
index 00000000..919b67bd
--- /dev/null
+++ b/openstackclient/compute/v2/server_migration.py
@@ -0,0 +1,485 @@
+# 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.
+
+"""Compute v2 Server Migration action implementations"""
+
+import uuid
+
+from novaclient import api_versions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
+from openstackclient.i18n import _
+from openstackclient.identity import common as identity_common
+
+
+class ListMigration(command.Lister):
+ _description = _("""List server migrations""")
+
+ def get_parser(self, prog_name):
+ parser = super(ListMigration, self).get_parser(prog_name)
+ parser.add_argument(
+ '--server',
+ metavar='<server>',
+ help=_(
+ 'Filter migrations by server (name or ID)'
+ )
+ )
+ parser.add_argument(
+ '--host',
+ metavar='<host>',
+ help=_(
+ 'Filter migrations by source or destination host'
+ ),
+ )
+ parser.add_argument(
+ '--status',
+ metavar='<status>',
+ help=_('Filter migrations by status')
+ )
+ parser.add_argument(
+ '--type',
+ metavar='<type>',
+ choices=[
+ 'evacuation', 'live-migration', 'cold-migration', 'resize',
+ ],
+ help=_('Filter migrations by type'),
+ )
+ parser.add_argument(
+ '--marker',
+ metavar='<marker>',
+ 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 above)"
+ ),
+ )
+ parser.add_argument(
+ '--limit',
+ metavar='<limit>',
+ type=int,
+ 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 above)"
+ ),
+ )
+ parser.add_argument(
+ '--changes-since',
+ dest='changes_since',
+ metavar='<changes-since>',
+ 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 above)"
+ ),
+ )
+ parser.add_argument(
+ '--changes-before',
+ dest='changes_before',
+ metavar='<changes-before>',
+ 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 above)"
+ ),
+ )
+ parser.add_argument(
+ '--project',
+ metavar='<project>',
+ help=_(
+ "Filter migrations by project (name or ID) "
+ "(supported with --os-compute-api-version 2.80 or above)"
+ ),
+ )
+ identity_common.add_project_domain_option_to_parser(parser)
+ parser.add_argument(
+ '--user',
+ metavar='<user>',
+ help=_(
+ "Filter migrations by user (name or ID) "
+ "(supported with --os-compute-api-version 2.80 or above)"
+ ),
+ )
+ identity_common.add_user_domain_option_to_parser(parser)
+ return parser
+
+ def print_migrations(self, parsed_args, compute_client, migrations):
+ column_headers = [
+ 'Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
+ 'Dest Host', 'Status', 'Server UUID', 'Old Flavor', 'New Flavor',
+ 'Created At', 'Updated At',
+ ]
+
+ # Response fields coming back from the REST API are not always exactly
+ # the same as the column header names.
+ columns = [
+ 'source_node', 'dest_node', 'source_compute', 'dest_compute',
+ 'dest_host', 'status', 'instance_uuid', 'old_instance_type_id',
+ 'new_instance_type_id', 'created_at', 'updated_at',
+ ]
+
+ # Insert migrations UUID after ID
+ if compute_client.api_version >= api_versions.APIVersion("2.59"):
+ column_headers.insert(0, "UUID")
+ columns.insert(0, "uuid")
+
+ if compute_client.api_version >= api_versions.APIVersion("2.23"):
+ column_headers.insert(0, "Id")
+ columns.insert(0, "id")
+ column_headers.insert(len(column_headers) - 2, "Type")
+ columns.insert(len(columns) - 2, "migration_type")
+
+ if compute_client.api_version >= api_versions.APIVersion("2.80"):
+ if parsed_args.project:
+ column_headers.insert(len(column_headers) - 2, "Project")
+ columns.insert(len(columns) - 2, "project_id")
+ if parsed_args.user:
+ column_headers.insert(len(column_headers) - 2, "User")
+ columns.insert(len(columns) - 2, "user_id")
+
+ return (
+ column_headers,
+ (utils.get_item_properties(mig, columns) for mig in migrations),
+ )
+
+ def take_action(self, parsed_args):
+ compute_client = self.app.client_manager.compute
+ identity_client = self.app.client_manager.identity
+
+ search_opts = {
+ 'host': parsed_args.host,
+ 'status': parsed_args.status,
+ }
+
+ if parsed_args.server:
+ search_opts['instance_uuid'] = utils.find_resource(
+ compute_client.servers,
+ parsed_args.server,
+ ).id
+
+ if parsed_args.type:
+ migration_type = parsed_args.type
+ # we're using an alias because the default value is confusing
+ if migration_type == 'cold-migration':
+ migration_type = 'migration'
+ search_opts['migration_type'] = migration_type
+
+ if parsed_args.marker:
+ if compute_client.api_version < api_versions.APIVersion('2.59'):
+ msg = _(
+ '--os-compute-api-version 2.59 or greater is required to '
+ 'support the --marker option'
+ )
+ raise exceptions.CommandError(msg)
+ search_opts['marker'] = parsed_args.marker
+
+ if parsed_args.limit:
+ if compute_client.api_version < api_versions.APIVersion('2.59'):
+ msg = _(
+ '--os-compute-api-version 2.59 or greater is required to '
+ 'support the --limit option'
+ )
+ raise exceptions.CommandError(msg)
+ search_opts['limit'] = parsed_args.limit
+
+ if parsed_args.changes_since:
+ if compute_client.api_version < api_versions.APIVersion('2.59'):
+ msg = _(
+ '--os-compute-api-version 2.59 or greater is required to '
+ 'support the --changes-since option'
+ )
+ raise exceptions.CommandError(msg)
+ search_opts['changes_since'] = parsed_args.changes_since
+
+ if parsed_args.changes_before:
+ if compute_client.api_version < api_versions.APIVersion('2.66'):
+ msg = _(
+ '--os-compute-api-version 2.66 or greater is required to '
+ 'support the --changes-before option'
+ )
+ raise exceptions.CommandError(msg)
+ search_opts['changes_before'] = parsed_args.changes_before
+
+ if parsed_args.project:
+ if compute_client.api_version < api_versions.APIVersion('2.80'):
+ msg = _(
+ '--os-compute-api-version 2.80 or greater is required to '
+ 'support the --project option'
+ )
+ raise exceptions.CommandError(msg)
+
+ search_opts['project_id'] = identity_common.find_project(
+ identity_client,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+
+ if parsed_args.user:
+ if compute_client.api_version < api_versions.APIVersion('2.80'):
+ msg = _(
+ '--os-compute-api-version 2.80 or greater is required to '
+ 'support the --user option'
+ )
+ raise exceptions.CommandError(msg)
+
+ search_opts['user_id'] = identity_common.find_user(
+ identity_client,
+ parsed_args.user,
+ parsed_args.user_domain,
+ ).id
+
+ migrations = compute_client.migrations.list(**search_opts)
+
+ return self.print_migrations(parsed_args, compute_client, migrations)
+
+
+def _get_migration_by_uuid(compute_client, server_id, migration_uuid):
+ for migration in compute_client.server_migrations.list(server_id):
+ if migration.uuid == migration_uuid:
+ return migration
+ break
+ else:
+ msg = _(
+ 'In-progress live migration %s is not found for server %s.'
+ )
+ raise exceptions.CommandError(msg % (migration_uuid, server_id))
+
+
+class ShowMigration(command.ShowOne):
+ """Show an in-progress live migration for a given server.
+
+ Note that it is not possible to show cold migrations or completed
+ live-migrations. Use 'openstack server migration list' to get details for
+ these.
+ """
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ 'server',
+ metavar='<server>',
+ help=_('Server (name or ID)'),
+ )
+ parser.add_argument(
+ 'migration',
+ metavar='<migration>',
+ help=_("Migration (ID)"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ compute_client = self.app.client_manager.compute
+
+ if compute_client.api_version < api_versions.APIVersion('2.24'):
+ msg = _(
+ '--os-compute-api-version 2.24 or greater is required to '
+ 'support the server migration show command'
+ )
+ raise exceptions.CommandError(msg)
+
+ if not parsed_args.migration.isdigit():
+ try:
+ uuid.UUID(parsed_args.migration)
+ except ValueError:
+ msg = _(
+ 'The <migration> argument must be an ID or UUID'
+ )
+ raise exceptions.CommandError(msg)
+
+ if compute_client.api_version < api_versions.APIVersion('2.59'):
+ msg = _(
+ '--os-compute-api-version 2.59 or greater is required to '
+ 'retrieve server migrations by UUID'
+ )
+ raise exceptions.CommandError(msg)
+
+ server = utils.find_resource(
+ compute_client.servers,
+ parsed_args.server,
+ )
+
+ # the nova API doesn't currently allow retrieval by UUID but it's a
+ # reasonably common operation so emulate this behavior by listing
+ # migrations - the responses are identical
+ if not parsed_args.migration.isdigit():
+ server_migration = _get_migration_by_uuid(
+ compute_client, server.id, parsed_args.migration,
+ )
+ else:
+ server_migration = compute_client.server_migrations.get(
+ server.id, parsed_args.migration,
+ )
+
+ columns = (
+ 'ID',
+ 'Server UUID',
+ 'Status',
+ 'Source Compute',
+ 'Source Node',
+ 'Dest Compute',
+ 'Dest Host',
+ 'Dest Node',
+ 'Memory Total Bytes',
+ 'Memory Processed Bytes',
+ 'Memory Remaining Bytes',
+ 'Disk Total Bytes',
+ 'Disk Processed Bytes',
+ 'Disk Remaining Bytes',
+ 'Created At',
+ 'Updated At',
+ )
+
+ if compute_client.api_version >= api_versions.APIVersion('2.59'):
+ columns += ('UUID',)
+
+ if compute_client.api_version >= api_versions.APIVersion('2.80'):
+ columns += ('User ID', 'Project ID')
+
+ data = utils.get_item_properties(server_migration, columns)
+ return columns, data
+
+
+class AbortMigration(command.Command):
+ """Cancel an ongoing live migration.
+
+ This command requires ``--os-compute-api-version`` 2.24 or greater.
+ """
+
+ def get_parser(self, prog_name):
+ parser = super(AbortMigration, self).get_parser(prog_name)
+ parser.add_argument(
+ 'server',
+ metavar='<server>',
+ help=_('Server (name or ID)'),
+ )
+ parser.add_argument(
+ 'migration',
+ metavar='<migration>',
+ help=_("Migration (ID)"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ compute_client = self.app.client_manager.compute
+
+ if compute_client.api_version < api_versions.APIVersion('2.24'):
+ msg = _(
+ '--os-compute-api-version 2.24 or greater is required to '
+ 'support the server migration abort command'
+ )
+ raise exceptions.CommandError(msg)
+
+ if not parsed_args.migration.isdigit():
+ try:
+ uuid.UUID(parsed_args.migration)
+ except ValueError:
+ msg = _(
+ 'The <migration> argument must be an ID or UUID'
+ )
+ raise exceptions.CommandError(msg)
+
+ if compute_client.api_version < api_versions.APIVersion('2.59'):
+ msg = _(
+ '--os-compute-api-version 2.59 or greater is required to '
+ 'abort server migrations by UUID'
+ )
+ raise exceptions.CommandError(msg)
+
+ server = utils.find_resource(
+ compute_client.servers,
+ parsed_args.server,
+ )
+
+ # the nova API doesn't currently allow retrieval by UUID but it's a
+ # reasonably common operation so emulate this behavior by listing
+ # migrations - the responses are identical
+ migration_id = parsed_args.migration
+ if not parsed_args.migration.isdigit():
+ migration_id = _get_migration_by_uuid(
+ compute_client, server.id, parsed_args.migration,
+ ).id
+
+ compute_client.server_migrations.live_migration_abort(
+ server.id, migration_id,
+ )
+
+
+class ForceCompleteMigration(command.Command):
+ """Force an ongoing live migration to complete.
+
+ This command requires ``--os-compute-api-version`` 2.22 or greater.
+ """
+
+ def get_parser(self, prog_name):
+ parser = super(ForceCompleteMigration, self).get_parser(prog_name)
+ parser.add_argument(
+ 'server',
+ metavar='<server>',
+ help=_('Server (name or ID)'),
+ )
+ parser.add_argument(
+ 'migration',
+ metavar='<migration>',
+ help=_('Migration (ID)')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ compute_client = self.app.client_manager.compute
+
+ if compute_client.api_version < api_versions.APIVersion('2.22'):
+ msg = _(
+ '--os-compute-api-version 2.22 or greater is required to '
+ 'support the server migration force complete command'
+ )
+ raise exceptions.CommandError(msg)
+
+ if not parsed_args.migration.isdigit():
+ try:
+ uuid.UUID(parsed_args.migration)
+ except ValueError:
+ msg = _(
+ 'The <migration> argument must be an ID or UUID'
+ )
+ raise exceptions.CommandError(msg)
+
+ if compute_client.api_version < api_versions.APIVersion('2.59'):
+ msg = _(
+ '--os-compute-api-version 2.59 or greater is required to '
+ 'abort server migrations by UUID'
+ )
+ raise exceptions.CommandError(msg)
+
+ server = utils.find_resource(
+ compute_client.servers,
+ parsed_args.server,
+ )
+
+ # the nova API doesn't currently allow retrieval by UUID but it's a
+ # reasonably common operation so emulate this behavior by listing
+ # migrations - the responses are identical
+ migration_id = parsed_args.migration
+ if not parsed_args.migration.isdigit():
+ migration_id = _get_migration_by_uuid(
+ compute_client, server.id, parsed_args.migration,
+ ).id
+
+ compute_client.server_migrations.live_migrate_force_complete(
+ server.id, migration_id,
+ )
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index e1002d28..18878109 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -31,7 +31,6 @@ from osc_lib import utils as common_utils
from openstackclient.compute.v2 import server
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
-from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
from openstackclient.tests.unit.image.v2 import fakes as image_fakes
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
from openstackclient.tests.unit import utils
@@ -5559,990 +5558,6 @@ class TestServerMigrate(TestServer):
self.assertNotCalled(self.servers_mock.live_migrate)
-class TestListMigration(TestServer):
- """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'
- ]
-
- # These are the fields that come back in the response from the REST API.
- MIGRATION_FIELDS = [
- 'source_node', 'dest_node', 'source_compute', 'dest_compute',
- 'dest_host', 'status', 'instance_uuid', 'old_instance_type_id',
- 'new_instance_type_id', 'created_at', 'updated_at'
- ]
-
- def setUp(self):
- super(TestListMigration, self).setUp()
-
- self.server = compute_fakes.FakeServer.create_one_server()
- self.servers_mock.get.return_value = self.server
-
- self.migrations = compute_fakes.FakeMigration.create_migrations(
- count=3)
- self.migrations_mock.list.return_value = self.migrations
-
- self.data = (common_utils.get_item_properties(
- s, self.MIGRATION_FIELDS) for s in self.migrations)
-
- # Get the command object to test
- self.cmd = server.ListMigration(self.app, None)
-
- def test_server_migration_list_no_options(self):
- arglist = []
- verifylist = []
-
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- columns, data = self.cmd.take_action(parsed_args)
-
- # Set expected values
- kwargs = {
- 'status': None,
- 'host': None,
- }
-
- self.migrations_mock.list.assert_called_with(**kwargs)
-
- self.assertEqual(self.MIGRATION_COLUMNS, columns)
- self.assertEqual(tuple(self.data), tuple(data))
-
- def test_server_migration_list(self):
- arglist = [
- '--server', 'server1',
- '--host', 'host1',
- '--status', 'migrating',
- '--type', 'cold-migration',
- ]
- verifylist = [
- ('server', 'server1'),
- ('host', 'host1'),
- ('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': 'host1',
- 'instance_uuid': self.server.id,
- 'migration_type': 'migration',
- }
-
- self.servers_mock.get.assert_called_with('server1')
- 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 = [
- 'Id', 'Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
- 'Dest Host', 'Status', 'Server UUID', 'Old Flavor', 'New Flavor',
- 'Type', 'Created At', 'Updated At'
- ]
-
- # These are the fields that come back in the response from the REST API.
- MIGRATION_FIELDS = [
- 'id', 'source_node', 'dest_node', 'source_compute', 'dest_compute',
- 'dest_host', 'status', 'instance_uuid', 'old_instance_type_id',
- 'new_instance_type_id', 'migration_type', 'created_at', 'updated_at'
- ]
-
- def setUp(self):
- super(TestListMigrationV223, self).setUp()
-
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.23')
-
- def test_server_migration_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,
- }
-
- self.migrations_mock.list.assert_called_with(**kwargs)
-
- 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'
- ]
-
- # These are the fields that come back in the response from the REST API.
- MIGRATION_FIELDS = [
- 'id', 'uuid', 'source_node', 'dest_node', 'source_compute',
- 'dest_compute', 'dest_host', 'status', 'instance_uuid',
- 'old_instance_type_id', 'new_instance_type_id', 'migration_type',
- 'created_at', 'updated_at'
- ]
-
- def setUp(self):
- super(TestListMigrationV259, self).setUp()
-
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
-
- def test_server_migration_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,
- '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_migration_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)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.59 or greater is required',
- str(ex))
-
- def test_server_migration_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)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.59 or greater is required',
- str(ex))
-
- def test_server_migration_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)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.59 or greater is required',
- str(ex))
-
-
-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'
- ]
-
- # These are the fields that come back in the response from the REST API.
- MIGRATION_FIELDS = [
- 'id', 'uuid', 'source_node', 'dest_node', 'source_compute',
- 'dest_compute', 'dest_host', 'status', 'instance_uuid',
- 'old_instance_type_id', 'new_instance_type_id', 'migration_type',
- 'created_at', 'updated_at'
- ]
-
- def setUp(self):
- super(TestListMigrationV266, self).setUp()
-
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.66')
-
- def test_server_migration_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,
- '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_migration_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)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.66 or greater is required',
- str(ex))
-
-
-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'
- ]
-
- # These are the fields that come back in the response from the REST API.
- MIGRATION_FIELDS = [
- 'id', 'uuid', 'source_node', 'dest_node', 'source_compute',
- 'dest_compute', 'dest_host', 'status', 'instance_uuid',
- 'old_instance_type_id', 'new_instance_type_id', 'migration_type',
- 'created_at', 'updated_at'
- ]
-
- project = identity_fakes.FakeProject.create_one_project()
- user = identity_fakes.FakeUser.create_one_user()
-
- def setUp(self):
- super(TestListMigrationV280, self).setUp()
-
- self.projects_mock = self.app.client_manager.identity.projects
- self.projects_mock.reset_mock()
-
- self.users_mock = self.app.client_manager.identity.users
- self.users_mock.reset_mock()
-
- self.projects_mock.get.return_value = self.project
- self.users_mock.get.return_value = self.user
-
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.80')
-
- def test_server_migration_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', self.project.id
- ]
- verifylist = [
- ('status', 'migrating'),
- ('limit', 1),
- ('marker', 'test_kp'),
- ('changes_since', '2019-08-07T08:03:25Z'),
- ('changes_before', '2019-08-09T08:03:25Z'),
- ('project', self.project.id)
- ]
- 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,
- 'project_id': self.project.id,
- '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_FIELDS.insert(
- len(self.MIGRATION_FIELDS) - 2, "project_id")
- self.assertEqual(self.MIGRATION_COLUMNS, columns)
- self.assertEqual(tuple(self.data), tuple(data))
- # Clean up global variables MIGRATION_COLUMNS
- self.MIGRATION_COLUMNS.remove('Project')
- # Clean up global variables MIGRATION_FIELDS
- self.MIGRATION_FIELDS.remove('project_id')
-
- 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', '0c2accde-644a-45fa-8c10-e76debc7fbc3')
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.80 or greater is required',
- str(ex))
-
- def test_server_migration_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', self.user.id,
- ]
- verifylist = [
- ('status', 'migrating'),
- ('limit', 1),
- ('marker', 'test_kp'),
- ('changes_since', '2019-08-07T08:03:25Z'),
- ('changes_before', '2019-08-09T08:03:25Z'),
- ('user', self.user.id),
- ]
- 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,
- 'user_id': self.user.id,
- '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.MIGRATION_FIELDS.insert(
- len(self.MIGRATION_FIELDS) - 2, "user_id")
- self.assertEqual(self.MIGRATION_COLUMNS, columns)
- self.assertEqual(tuple(self.data), tuple(data))
- # Clean up global variables MIGRATION_COLUMNS
- self.MIGRATION_COLUMNS.remove('User')
- # Clean up global variables MIGRATION_FIELDS
- self.MIGRATION_FIELDS.remove('user_id')
-
- 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', self.user.id,
- ]
- verifylist = [
- ('status', 'migrating'),
- ('changes_before', '2019-08-09T08:03:25Z'),
- ('user', self.user.id),
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.80 or greater is required',
- str(ex))
-
- def test_server_migration_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', self.project.id,
- '--user', self.user.id,
- ]
- verifylist = [
- ('status', 'migrating'),
- ('limit', 1),
- ('changes_since', '2019-08-07T08:03:25Z'),
- ('changes_before', '2019-08-09T08:03:25Z'),
- ('project', self.project.id),
- ('user', self.user.id),
- ]
- 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,
- 'project_id': self.project.id,
- 'user_id': self.user.id,
- '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_FIELDS.insert(
- len(self.MIGRATION_FIELDS) - 2, "project_id")
- self.MIGRATION_COLUMNS.insert(
- len(self.MIGRATION_COLUMNS) - 2, "User")
- self.MIGRATION_FIELDS.insert(
- len(self.MIGRATION_FIELDS) - 2, "user_id")
- 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_FIELDS.remove('project_id')
- self.MIGRATION_COLUMNS.remove('User')
- self.MIGRATION_FIELDS.remove('user_id')
-
- 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', self.project.id,
- '--user', self.user.id,
- ]
- verifylist = [
- ('status', 'migrating'),
- ('changes_before', '2019-08-09T08:03:25Z'),
- ('project', self.project.id),
- ('user', self.user.id)
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.80 or greater is required',
- str(ex))
-
-
-class TestServerMigrationShow(TestServer):
-
- def setUp(self):
- super().setUp()
-
- self.server = compute_fakes.FakeServer.create_one_server()
- self.servers_mock.get.return_value = self.server
-
- self.server_migration = compute_fakes.FakeServerMigration\
- .create_one_server_migration()
- self.server_migrations_mock.get.return_value = self.server_migration
-
- self.columns = (
- 'ID',
- 'Server UUID',
- 'Status',
- 'Source Compute',
- 'Source Node',
- 'Dest Compute',
- 'Dest Host',
- 'Dest Node',
- 'Memory Total Bytes',
- 'Memory Processed Bytes',
- 'Memory Remaining Bytes',
- 'Disk Total Bytes',
- 'Disk Processed Bytes',
- 'Disk Remaining Bytes',
- 'Created At',
- 'Updated At',
- )
-
- self.data = (
- self.server_migration.id,
- self.server_migration.server_uuid,
- self.server_migration.status,
- self.server_migration.source_compute,
- self.server_migration.source_node,
- self.server_migration.dest_compute,
- self.server_migration.dest_host,
- self.server_migration.dest_node,
- self.server_migration.memory_total_bytes,
- self.server_migration.memory_processed_bytes,
- self.server_migration.memory_remaining_bytes,
- self.server_migration.disk_total_bytes,
- self.server_migration.disk_processed_bytes,
- self.server_migration.disk_remaining_bytes,
- self.server_migration.created_at,
- self.server_migration.updated_at,
- )
-
- # Get the command object to test
- self.cmd = server.ShowMigration(self.app, None)
-
- def _test_server_migration_show(self):
- arglist = [
- self.server.id,
- '2', # arbitrary migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- columns, data = self.cmd.take_action(parsed_args)
-
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
-
- self.servers_mock.get.assert_called_with(self.server.id)
- self.server_migrations_mock.get.assert_called_with(
- self.server.id, '2',)
-
- def test_server_migration_show(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.24')
-
- self._test_server_migration_show()
-
- def test_server_migration_show_v259(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
-
- self.columns += ('UUID',)
- self.data += (self.server_migration.uuid,)
-
- self._test_server_migration_show()
-
- def test_server_migration_show_v280(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.80')
-
- self.columns += ('UUID', 'User ID', 'Project ID')
- self.data += (
- self.server_migration.uuid,
- self.server_migration.user_id,
- self.server_migration.project_id,
- )
-
- self._test_server_migration_show()
-
- def test_server_migration_show_pre_v224(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.23')
-
- arglist = [
- self.server.id,
- '2', # arbitrary migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.24 or greater is required',
- str(ex))
-
- def test_server_migration_show_by_uuid(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
- self.server_migrations_mock.list.return_value = [self.server_migration]
-
- self.columns += ('UUID',)
- self.data += (self.server_migration.uuid,)
-
- arglist = [
- self.server.id,
- self.server_migration.uuid, # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- columns, data = self.cmd.take_action(parsed_args)
-
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
-
- self.servers_mock.get.assert_called_with(self.server.id)
- self.server_migrations_mock.list.assert_called_with(self.server.id)
- self.server_migrations_mock.get.assert_not_called()
-
- def test_server_migration_show_by_uuid_no_matches(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
- self.server_migrations_mock.list.return_value = []
-
- arglist = [
- self.server.id,
- '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- 'In-progress live migration 69f95745-bfe3-4302-90f7-5b0022cba1ce',
- str(ex))
-
- def test_server_migration_show_by_uuid_pre_v259(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.58')
-
- arglist = [
- self.server.id,
- '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.59 or greater is required',
- str(ex))
-
- def test_server_migration_show_invalid_id(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.24')
-
- arglist = [
- self.server.id,
- 'foo', # invalid migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- 'The <migration> argument must be an ID or UUID',
- str(ex))
-
-
-class TestServerMigrationAbort(TestServer):
-
- def setUp(self):
- super(TestServerMigrationAbort, self).setUp()
-
- self.server = compute_fakes.FakeServer.create_one_server()
-
- # Return value for utils.find_resource for server.
- self.servers_mock.get.return_value = self.server
-
- # Get the command object to test
- self.cmd = server.AbortMigration(self.app, None)
-
- def test_migration_abort(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.24')
-
- arglist = [
- self.server.id,
- '2', # arbitrary migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- result = self.cmd.take_action(parsed_args)
-
- self.servers_mock.get.assert_called_with(self.server.id)
- self.server_migrations_mock.live_migration_abort.assert_called_with(
- self.server.id, '2',)
- self.assertIsNone(result)
-
- def test_migration_abort_pre_v224(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.23')
-
- arglist = [
- self.server.id,
- '2', # arbitrary migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.24 or greater is required',
- str(ex))
-
- def test_server_migration_abort_by_uuid(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
-
- self.server_migration = compute_fakes.FakeServerMigration\
- .create_one_server_migration()
- self.server_migrations_mock.list.return_value = [self.server_migration]
-
- arglist = [
- self.server.id,
- self.server_migration.uuid, # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- result = self.cmd.take_action(parsed_args)
-
- self.servers_mock.get.assert_called_with(self.server.id)
- self.server_migrations_mock.list.assert_called_with(self.server.id)
- self.server_migrations_mock.live_migration_abort.assert_called_with(
- self.server.id, self.server_migration.id)
- self.assertIsNone(result)
-
- def test_server_migration_abort_by_uuid_no_matches(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
-
- self.server_migrations_mock.list.return_value = []
-
- arglist = [
- self.server.id,
- '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- 'In-progress live migration 69f95745-bfe3-4302-90f7-5b0022cba1ce',
- str(ex))
-
- def test_server_migration_abort_by_uuid_pre_v259(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.58')
-
- arglist = [
- self.server.id,
- '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.59 or greater is required',
- str(ex))
-
-
-class TestServerMigrationForceComplete(TestServer):
-
- def setUp(self):
- super(TestServerMigrationForceComplete, self).setUp()
-
- self.server = compute_fakes.FakeServer.create_one_server()
-
- # Return value for utils.find_resource for server.
- self.servers_mock.get.return_value = self.server
-
- # Get the command object to test
- self.cmd = server.ForceCompleteMigration(self.app, None)
-
- def test_migration_force_complete(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.22')
-
- arglist = [
- self.server.id,
- '2', # arbitrary migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- result = self.cmd.take_action(parsed_args)
-
- self.servers_mock.get.assert_called_with(self.server.id)
- self.server_migrations_mock.live_migrate_force_complete\
- .assert_called_with(self.server.id, '2',)
- self.assertIsNone(result)
-
- def test_migration_force_complete_pre_v222(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.21')
-
- arglist = [
- self.server.id,
- '2', # arbitrary migration ID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.22 or greater is required',
- str(ex))
-
- def test_server_migration_force_complete_by_uuid(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
-
- self.server_migration = compute_fakes.FakeServerMigration\
- .create_one_server_migration()
- self.server_migrations_mock.list.return_value = [self.server_migration]
-
- arglist = [
- self.server.id,
- self.server_migration.uuid, # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- result = self.cmd.take_action(parsed_args)
-
- self.servers_mock.get.assert_called_with(self.server.id)
- self.server_migrations_mock.list.assert_called_with(self.server.id)
- self.server_migrations_mock.live_migrate_force_complete\
- .assert_called_with(self.server.id, self.server_migration.id)
- self.assertIsNone(result)
-
- def test_server_migration_force_complete_by_uuid_no_matches(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.59')
-
- self.server_migrations_mock.list.return_value = []
-
- arglist = [
- self.server.id,
- '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- 'In-progress live migration 69f95745-bfe3-4302-90f7-5b0022cba1ce',
- str(ex))
-
- def test_server_migration_force_complete_by_uuid_pre_v259(self):
- self.app.client_manager.compute.api_version = api_versions.APIVersion(
- '2.58')
-
- arglist = [
- self.server.id,
- '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
- ]
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- ex = self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args)
- self.assertIn(
- '--os-compute-api-version 2.59 or greater is required',
- str(ex))
-
-
class TestServerPause(TestServer):
def setUp(self):
diff --git a/openstackclient/tests/unit/compute/v2/test_server_migration.py b/openstackclient/tests/unit/compute/v2/test_server_migration.py
new file mode 100644
index 00000000..c4cbac47
--- /dev/null
+++ b/openstackclient/tests/unit/compute/v2/test_server_migration.py
@@ -0,0 +1,1028 @@
+# 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 unittest import mock
+
+from novaclient import api_versions
+from osc_lib import exceptions
+from osc_lib import utils as common_utils
+
+from openstackclient.compute.v2 import server_migration
+from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
+from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
+
+
+class TestServerMigration(compute_fakes.TestComputev2):
+
+ def setUp(self):
+ super().setUp()
+
+ # Get a shortcut to the compute client ServerManager Mock
+ self.servers_mock = self.app.client_manager.compute.servers
+ self.servers_mock.reset_mock()
+
+ # Get a shortcut to the compute client ServerMigrationsManager Mock
+ self.server_migrations_mock = \
+ self.app.client_manager.compute.server_migrations
+ self.server_migrations_mock.reset_mock()
+
+ # Get a shortcut to the compute client MigrationManager mock
+ self.migrations_mock = self.app.client_manager.compute.migrations
+ self.migrations_mock.reset_mock()
+
+ self.app.client_manager.sdk_connection = mock.Mock()
+ self.app.client_manager.sdk_connection.compute = mock.Mock()
+ self.sdk_client = self.app.client_manager.sdk_connection.compute
+
+
+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'
+ ]
+
+ # These are the fields that come back in the response from the REST API.
+ MIGRATION_FIELDS = [
+ 'source_node', 'dest_node', 'source_compute', 'dest_compute',
+ 'dest_host', 'status', 'instance_uuid', 'old_instance_type_id',
+ 'new_instance_type_id', 'created_at', 'updated_at'
+ ]
+
+ def setUp(self):
+ super().setUp()
+
+ self.server = compute_fakes.FakeServer.create_one_server()
+ self.servers_mock.get.return_value = self.server
+
+ self.migrations = compute_fakes.FakeMigration.create_migrations(
+ count=3)
+ self.migrations_mock.list.return_value = self.migrations
+
+ self.data = (common_utils.get_item_properties(
+ s, self.MIGRATION_FIELDS) for s in self.migrations)
+
+ # Get the command object to test
+ self.cmd = server_migration.ListMigration(self.app, None)
+
+ def test_server_migration_list_no_options(self):
+ arglist = []
+ verifylist = []
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'status': None,
+ 'host': None,
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
+ def test_server_migration_list(self):
+ arglist = [
+ '--server', 'server1',
+ '--host', 'host1',
+ '--status', 'migrating',
+ '--type', 'cold-migration',
+ ]
+ verifylist = [
+ ('server', 'server1'),
+ ('host', 'host1'),
+ ('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': 'host1',
+ 'instance_uuid': self.server.id,
+ 'migration_type': 'migration',
+ }
+
+ self.servers_mock.get.assert_called_with('server1')
+ 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 = [
+ 'Id', 'Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
+ 'Dest Host', 'Status', 'Server UUID', 'Old Flavor', 'New Flavor',
+ 'Type', 'Created At', 'Updated At'
+ ]
+
+ # These are the fields that come back in the response from the REST API.
+ MIGRATION_FIELDS = [
+ 'id', 'source_node', 'dest_node', 'source_compute', 'dest_compute',
+ 'dest_host', 'status', 'instance_uuid', 'old_instance_type_id',
+ 'new_instance_type_id', 'migration_type', 'created_at', 'updated_at'
+ ]
+
+ def setUp(self):
+ super().setUp()
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.23')
+
+ def test_server_migration_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,
+ }
+
+ self.migrations_mock.list.assert_called_with(**kwargs)
+
+ 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'
+ ]
+
+ # These are the fields that come back in the response from the REST API.
+ MIGRATION_FIELDS = [
+ 'id', 'uuid', 'source_node', 'dest_node', 'source_compute',
+ 'dest_compute', 'dest_host', 'status', 'instance_uuid',
+ 'old_instance_type_id', 'new_instance_type_id', 'migration_type',
+ 'created_at', 'updated_at'
+ ]
+
+ def setUp(self):
+ super().setUp()
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ def test_server_migration_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,
+ '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_migration_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)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.59 or greater is required',
+ str(ex))
+
+ def test_server_migration_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)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.59 or greater is required',
+ str(ex))
+
+ def test_server_migration_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)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.59 or greater is required',
+ str(ex))
+
+
+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'
+ ]
+
+ # These are the fields that come back in the response from the REST API.
+ MIGRATION_FIELDS = [
+ 'id', 'uuid', 'source_node', 'dest_node', 'source_compute',
+ 'dest_compute', 'dest_host', 'status', 'instance_uuid',
+ 'old_instance_type_id', 'new_instance_type_id', 'migration_type',
+ 'created_at', 'updated_at'
+ ]
+
+ def setUp(self):
+ super().setUp()
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.66')
+
+ def test_server_migration_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,
+ '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_migration_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)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.66 or greater is required',
+ str(ex))
+
+
+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'
+ ]
+
+ # These are the fields that come back in the response from the REST API.
+ MIGRATION_FIELDS = [
+ 'id', 'uuid', 'source_node', 'dest_node', 'source_compute',
+ 'dest_compute', 'dest_host', 'status', 'instance_uuid',
+ 'old_instance_type_id', 'new_instance_type_id', 'migration_type',
+ 'created_at', 'updated_at'
+ ]
+
+ project = identity_fakes.FakeProject.create_one_project()
+ user = identity_fakes.FakeUser.create_one_user()
+
+ def setUp(self):
+ super().setUp()
+
+ self.projects_mock = self.app.client_manager.identity.projects
+ self.projects_mock.reset_mock()
+
+ self.users_mock = self.app.client_manager.identity.users
+ self.users_mock.reset_mock()
+
+ self.projects_mock.get.return_value = self.project
+ self.users_mock.get.return_value = self.user
+
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.80')
+
+ def test_server_migration_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', self.project.id
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('marker', 'test_kp'),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project', self.project.id)
+ ]
+ 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,
+ 'project_id': self.project.id,
+ '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_FIELDS.insert(
+ len(self.MIGRATION_FIELDS) - 2, "project_id")
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+ # Clean up global variables MIGRATION_COLUMNS
+ self.MIGRATION_COLUMNS.remove('Project')
+ # Clean up global variables MIGRATION_FIELDS
+ self.MIGRATION_FIELDS.remove('project_id')
+
+ 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', '0c2accde-644a-45fa-8c10-e76debc7fbc3')
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.80 or greater is required',
+ str(ex))
+
+ def test_server_migration_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', self.user.id,
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('marker', 'test_kp'),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('user', self.user.id),
+ ]
+ 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,
+ 'user_id': self.user.id,
+ '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.MIGRATION_FIELDS.insert(
+ len(self.MIGRATION_FIELDS) - 2, "user_id")
+ self.assertEqual(self.MIGRATION_COLUMNS, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+ # Clean up global variables MIGRATION_COLUMNS
+ self.MIGRATION_COLUMNS.remove('User')
+ # Clean up global variables MIGRATION_FIELDS
+ self.MIGRATION_FIELDS.remove('user_id')
+
+ 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', self.user.id,
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('user', self.user.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.80 or greater is required',
+ str(ex))
+
+ def test_server_migration_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', self.project.id,
+ '--user', self.user.id,
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('limit', 1),
+ ('changes_since', '2019-08-07T08:03:25Z'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project', self.project.id),
+ ('user', self.user.id),
+ ]
+ 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,
+ 'project_id': self.project.id,
+ 'user_id': self.user.id,
+ '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_FIELDS.insert(
+ len(self.MIGRATION_FIELDS) - 2, "project_id")
+ self.MIGRATION_COLUMNS.insert(
+ len(self.MIGRATION_COLUMNS) - 2, "User")
+ self.MIGRATION_FIELDS.insert(
+ len(self.MIGRATION_FIELDS) - 2, "user_id")
+ 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_FIELDS.remove('project_id')
+ self.MIGRATION_COLUMNS.remove('User')
+ self.MIGRATION_FIELDS.remove('user_id')
+
+ 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', self.project.id,
+ '--user', self.user.id,
+ ]
+ verifylist = [
+ ('status', 'migrating'),
+ ('changes_before', '2019-08-09T08:03:25Z'),
+ ('project', self.project.id),
+ ('user', self.user.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.80 or greater is required',
+ str(ex))
+
+
+class TestServerMigrationShow(TestServerMigration):
+
+ def setUp(self):
+ super().setUp()
+
+ self.server = compute_fakes.FakeServer.create_one_server()
+ self.servers_mock.get.return_value = self.server
+
+ self.server_migration = compute_fakes.FakeServerMigration\
+ .create_one_server_migration()
+ self.server_migrations_mock.get.return_value = self.server_migration
+
+ self.columns = (
+ 'ID',
+ 'Server UUID',
+ 'Status',
+ 'Source Compute',
+ 'Source Node',
+ 'Dest Compute',
+ 'Dest Host',
+ 'Dest Node',
+ 'Memory Total Bytes',
+ 'Memory Processed Bytes',
+ 'Memory Remaining Bytes',
+ 'Disk Total Bytes',
+ 'Disk Processed Bytes',
+ 'Disk Remaining Bytes',
+ 'Created At',
+ 'Updated At',
+ )
+
+ self.data = (
+ self.server_migration.id,
+ self.server_migration.server_uuid,
+ self.server_migration.status,
+ self.server_migration.source_compute,
+ self.server_migration.source_node,
+ self.server_migration.dest_compute,
+ self.server_migration.dest_host,
+ self.server_migration.dest_node,
+ self.server_migration.memory_total_bytes,
+ self.server_migration.memory_processed_bytes,
+ self.server_migration.memory_remaining_bytes,
+ self.server_migration.disk_total_bytes,
+ self.server_migration.disk_processed_bytes,
+ self.server_migration.disk_remaining_bytes,
+ self.server_migration.created_at,
+ self.server_migration.updated_at,
+ )
+
+ # Get the command object to test
+ self.cmd = server_migration.ShowMigration(self.app, None)
+
+ def _test_server_migration_show(self):
+ arglist = [
+ self.server.id,
+ '2', # arbitrary migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server_migrations_mock.get.assert_called_with(
+ self.server.id, '2',)
+
+ def test_server_migration_show(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.24')
+
+ self._test_server_migration_show()
+
+ def test_server_migration_show_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ self.columns += ('UUID',)
+ self.data += (self.server_migration.uuid,)
+
+ self._test_server_migration_show()
+
+ def test_server_migration_show_v280(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.80')
+
+ self.columns += ('UUID', 'User ID', 'Project ID')
+ self.data += (
+ self.server_migration.uuid,
+ self.server_migration.user_id,
+ self.server_migration.project_id,
+ )
+
+ self._test_server_migration_show()
+
+ def test_server_migration_show_pre_v224(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.23')
+
+ arglist = [
+ self.server.id,
+ '2', # arbitrary migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.24 or greater is required',
+ str(ex))
+
+ def test_server_migration_show_by_uuid(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+ self.server_migrations_mock.list.return_value = [self.server_migration]
+
+ self.columns += ('UUID',)
+ self.data += (self.server_migration.uuid,)
+
+ arglist = [
+ self.server.id,
+ self.server_migration.uuid, # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server_migrations_mock.list.assert_called_with(self.server.id)
+ self.server_migrations_mock.get.assert_not_called()
+
+ def test_server_migration_show_by_uuid_no_matches(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+ self.server_migrations_mock.list.return_value = []
+
+ arglist = [
+ self.server.id,
+ '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ 'In-progress live migration 69f95745-bfe3-4302-90f7-5b0022cba1ce',
+ str(ex))
+
+ def test_server_migration_show_by_uuid_pre_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.58')
+
+ arglist = [
+ self.server.id,
+ '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.59 or greater is required',
+ str(ex))
+
+ def test_server_migration_show_invalid_id(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.24')
+
+ arglist = [
+ self.server.id,
+ 'foo', # invalid migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ 'The <migration> argument must be an ID or UUID',
+ str(ex))
+
+
+class TestServerMigrationAbort(TestServerMigration):
+
+ def setUp(self):
+ super().setUp()
+
+ self.server = compute_fakes.FakeServer.create_one_server()
+
+ # Return value for utils.find_resource for server.
+ self.servers_mock.get.return_value = self.server
+
+ # Get the command object to test
+ self.cmd = server_migration.AbortMigration(self.app, None)
+
+ def test_migration_abort(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.24')
+
+ arglist = [
+ self.server.id,
+ '2', # arbitrary migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server_migrations_mock.live_migration_abort.assert_called_with(
+ self.server.id, '2',)
+ self.assertIsNone(result)
+
+ def test_migration_abort_pre_v224(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.23')
+
+ arglist = [
+ self.server.id,
+ '2', # arbitrary migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.24 or greater is required',
+ str(ex))
+
+ def test_server_migration_abort_by_uuid(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ self.server_migration = compute_fakes.FakeServerMigration\
+ .create_one_server_migration()
+ self.server_migrations_mock.list.return_value = [self.server_migration]
+
+ arglist = [
+ self.server.id,
+ self.server_migration.uuid, # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server_migrations_mock.list.assert_called_with(self.server.id)
+ self.server_migrations_mock.live_migration_abort.assert_called_with(
+ self.server.id, self.server_migration.id)
+ self.assertIsNone(result)
+
+ def test_server_migration_abort_by_uuid_no_matches(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ self.server_migrations_mock.list.return_value = []
+
+ arglist = [
+ self.server.id,
+ '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ 'In-progress live migration 69f95745-bfe3-4302-90f7-5b0022cba1ce',
+ str(ex))
+
+ def test_server_migration_abort_by_uuid_pre_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.58')
+
+ arglist = [
+ self.server.id,
+ '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.59 or greater is required',
+ str(ex))
+
+
+class TestServerMigrationForceComplete(TestServerMigration):
+
+ def setUp(self):
+ super().setUp()
+
+ self.server = compute_fakes.FakeServer.create_one_server()
+
+ # Return value for utils.find_resource for server.
+ self.servers_mock.get.return_value = self.server
+
+ # Get the command object to test
+ self.cmd = server_migration.ForceCompleteMigration(self.app, None)
+
+ def test_migration_force_complete(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.22')
+
+ arglist = [
+ self.server.id,
+ '2', # arbitrary migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server_migrations_mock.live_migrate_force_complete\
+ .assert_called_with(self.server.id, '2',)
+ self.assertIsNone(result)
+
+ def test_migration_force_complete_pre_v222(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.21')
+
+ arglist = [
+ self.server.id,
+ '2', # arbitrary migration ID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.22 or greater is required',
+ str(ex))
+
+ def test_server_migration_force_complete_by_uuid(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ self.server_migration = compute_fakes.FakeServerMigration\
+ .create_one_server_migration()
+ self.server_migrations_mock.list.return_value = [self.server_migration]
+
+ arglist = [
+ self.server.id,
+ self.server_migration.uuid, # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server_migrations_mock.list.assert_called_with(self.server.id)
+ self.server_migrations_mock.live_migrate_force_complete\
+ .assert_called_with(self.server.id, self.server_migration.id)
+ self.assertIsNone(result)
+
+ def test_server_migration_force_complete_by_uuid_no_matches(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.59')
+
+ self.server_migrations_mock.list.return_value = []
+
+ arglist = [
+ self.server.id,
+ '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ 'In-progress live migration 69f95745-bfe3-4302-90f7-5b0022cba1ce',
+ str(ex))
+
+ def test_server_migration_force_complete_by_uuid_pre_v259(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.58')
+
+ arglist = [
+ self.server.id,
+ '69f95745-bfe3-4302-90f7-5b0022cba1ce', # arbitrary migration UUID
+ ]
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+ self.assertIn(
+ '--os-compute-api-version 2.59 or greater is required',
+ str(ex))
diff --git a/setup.cfg b/setup.cfg
index b4718b1f..79e805f0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -111,12 +111,8 @@ openstack.compute.v2 =
server_migrate = openstackclient.compute.v2.server:MigrateServer
server_migrate_confirm = openstackclient.compute.v2.server:MigrateConfirm
server_migrate_revert = openstackclient.compute.v2.server:MigrateRevert
- server_migration_abort = openstackclient.compute.v2.server:AbortMigration
server_migration_confirm = openstackclient.compute.v2.server:ConfirmMigration
- server_migration_force_complete = openstackclient.compute.v2.server:ForceCompleteMigration
- server_migration_list = openstackclient.compute.v2.server:ListMigration
server_migration_revert = openstackclient.compute.v2.server:RevertMigration
- server_migration_show = openstackclient.compute.v2.server:ShowMigration
server_pause = openstackclient.compute.v2.server:PauseServer
server_reboot = openstackclient.compute.v2.server:RebootServer
server_rebuild = openstackclient.compute.v2.server:RebuildServer
@@ -157,6 +153,11 @@ openstack.compute.v2 =
server_image_create = openstackclient.compute.v2.server_image:CreateServerImage
+ server_migration_abort = openstackclient.compute.v2.server_migration:AbortMigration
+ server_migration_force_complete = openstackclient.compute.v2.server_migration:ForceCompleteMigration
+ server_migration_list = openstackclient.compute.v2.server_migration:ListMigration
+ server_migration_show = openstackclient.compute.v2.server_migration:ShowMigration
+
server_volume_list = openstackclient.compute.v2.server_volume:ListServerVolume
server_volume_update = openstackclient.compute.v2.server_volume:UpdateServerVolume