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 json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import uuid
|
|
||||||
|
|
||||||
from cliff import columns as cliff_columns
|
from cliff import columns as cliff_columns
|
||||||
import iso8601
|
import iso8601
|
||||||
@ -2812,468 +2811,6 @@ revert to release the new server and restart the old one.""")
|
|||||||
raise SystemExit
|
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):
|
class PauseServer(command.Command):
|
||||||
_description = _("Pause server(s)")
|
_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.compute.v2 import server
|
||||||
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
|
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.image.v2 import fakes as image_fakes
|
||||||
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
|
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
|
||||||
from openstackclient.tests.unit import utils
|
from openstackclient.tests.unit import utils
|
||||||
@ -5559,990 +5558,6 @@ class TestServerMigrate(TestServer):
|
|||||||
self.assertNotCalled(self.servers_mock.live_migrate)
|
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):
|
class TestServerPause(TestServer):
|
||||||
|
|
||||||
def setUp(self):
|
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 = openstackclient.compute.v2.server:MigrateServer
|
||||||
server_migrate_confirm = openstackclient.compute.v2.server:MigrateConfirm
|
server_migrate_confirm = openstackclient.compute.v2.server:MigrateConfirm
|
||||||
server_migrate_revert = openstackclient.compute.v2.server:MigrateRevert
|
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_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_revert = openstackclient.compute.v2.server:RevertMigration
|
||||||
server_migration_show = openstackclient.compute.v2.server:ShowMigration
|
|
||||||
server_pause = openstackclient.compute.v2.server:PauseServer
|
server_pause = openstackclient.compute.v2.server:PauseServer
|
||||||
server_reboot = openstackclient.compute.v2.server:RebootServer
|
server_reboot = openstackclient.compute.v2.server:RebootServer
|
||||||
server_rebuild = openstackclient.compute.v2.server:RebuildServer
|
server_rebuild = openstackclient.compute.v2.server:RebuildServer
|
||||||
@ -157,6 +153,11 @@ openstack.compute.v2 =
|
|||||||
|
|
||||||
server_image_create = openstackclient.compute.v2.server_image:CreateServerImage
|
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_list = openstackclient.compute.v2.server_volume:ListServerVolume
|
||||||
server_volume_update = openstackclient.compute.v2.server_volume:UpdateServerVolume
|
server_volume_update = openstackclient.compute.v2.server_volume:UpdateServerVolume
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user