compute: Move server migrations commands to their own file
The 'openstackclient.compute.v2.server' module is getting rather large. The server migration commands don't need to be in there. Move them. Change-Id: I8b2600cfd9f8e37d3093c52c7222d85e84e7fc89 Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
parent
cffec4517f
commit
c9b84106c3
@ -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)")
|
||||
|
||||
|
485
openstackclient/compute/v2/server_migration.py
Normal file
485
openstackclient/compute/v2/server_migration.py
Normal file
@ -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,
|
||||
)
|
@ -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):
|
||||
|
1028
openstackclient/tests/unit/compute/v2/test_server_migration.py
Normal file
1028
openstackclient/tests/unit/compute/v2/test_server_migration.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user