Correct REST API response fields for /os-migrations API
The compute APIs are unfortunately inconsistent with regard to the response parameters for migrations. * GET /servers/{server_id}/migrations returns server_uuid * GET /os-migrations returns instance_uuid Because the 'Server UUID' column is being specified for parsing the response from GET /os-migrations, it is always showing as an empty string to users. There are a few other mismatches between the column names and the REST API response fields [1]: * 'Old Flavor' vs 'old_instance_type_id' * 'New Flavor' vs 'new_instance_type_id' * 'Type' vs 'migration_type' This adds a new list containing the REST API response field names to pass to utils.get_item_properties so that the responses are correctly parsed and the client output contains the response data instead of empty strings. Story: 2009078 Task: 42890 [1] https://docs.openstack.org/api-ref/compute/?expanded=list-migrations-detail#list-migrations Change-Id: I8aab60619e0225047f6a1c31e44917ca8fcc799e
This commit is contained in:
parent
59256becc9
commit
ed87f7949e
@ -2781,28 +2781,41 @@ class ListMigration(command.Lister):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def print_migrations(self, parsed_args, compute_client, migrations):
|
def print_migrations(self, parsed_args, compute_client, migrations):
|
||||||
columns = [
|
column_headers = [
|
||||||
'Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
|
'Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
|
||||||
'Dest Host', 'Status', 'Server UUID', 'Old Flavor', 'New Flavor',
|
'Dest Host', 'Status', 'Server UUID', 'Old Flavor', 'New Flavor',
|
||||||
'Created At', 'Updated At',
|
'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
|
# Insert migrations UUID after ID
|
||||||
if compute_client.api_version >= api_versions.APIVersion("2.59"):
|
if compute_client.api_version >= api_versions.APIVersion("2.59"):
|
||||||
columns.insert(0, "UUID")
|
column_headers.insert(0, "UUID")
|
||||||
|
columns.insert(0, "uuid")
|
||||||
|
|
||||||
if compute_client.api_version >= api_versions.APIVersion("2.23"):
|
if compute_client.api_version >= api_versions.APIVersion("2.23"):
|
||||||
columns.insert(0, "Id")
|
column_headers.insert(0, "Id")
|
||||||
columns.insert(len(columns) - 2, "Type")
|
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 compute_client.api_version >= api_versions.APIVersion("2.80"):
|
||||||
if parsed_args.project:
|
if parsed_args.project:
|
||||||
columns.insert(len(columns) - 2, "Project")
|
column_headers.insert(len(column_headers) - 2, "Project")
|
||||||
|
columns.insert(len(columns) - 2, "project_id")
|
||||||
if parsed_args.user:
|
if parsed_args.user:
|
||||||
columns.insert(len(columns) - 2, "User")
|
column_headers.insert(len(column_headers) - 2, "User")
|
||||||
|
columns.insert(len(columns) - 2, "user_id")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
columns,
|
column_headers,
|
||||||
(utils.get_item_properties(mig, columns) for mig in migrations),
|
(utils.get_item_properties(mig, columns) for mig in migrations),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1587,20 +1587,20 @@ class FakeMigration(object):
|
|||||||
migration_info = {
|
migration_info = {
|
||||||
"dest_host": "10.0.2.15",
|
"dest_host": "10.0.2.15",
|
||||||
"status": "migrating",
|
"status": "migrating",
|
||||||
"type": "migration",
|
"migration_type": "migration",
|
||||||
"updated_at": "2017-01-31T08:03:25.000000",
|
"updated_at": "2017-01-31T08:03:25.000000",
|
||||||
"created_at": "2017-01-31T08:03:21.000000",
|
"created_at": "2017-01-31T08:03:21.000000",
|
||||||
"dest_compute": "compute-" + uuid.uuid4().hex,
|
"dest_compute": "compute-" + uuid.uuid4().hex,
|
||||||
"id": random.randint(1, 999),
|
"id": random.randint(1, 999),
|
||||||
"source_node": "node-" + uuid.uuid4().hex,
|
"source_node": "node-" + uuid.uuid4().hex,
|
||||||
"server": uuid.uuid4().hex,
|
"instance_uuid": uuid.uuid4().hex,
|
||||||
"dest_node": "node-" + uuid.uuid4().hex,
|
"dest_node": "node-" + uuid.uuid4().hex,
|
||||||
"source_compute": "compute-" + uuid.uuid4().hex,
|
"source_compute": "compute-" + uuid.uuid4().hex,
|
||||||
"uuid": uuid.uuid4().hex,
|
"uuid": uuid.uuid4().hex,
|
||||||
"old_instance_type_id": uuid.uuid4().hex,
|
"old_instance_type_id": uuid.uuid4().hex,
|
||||||
"new_instance_type_id": uuid.uuid4().hex,
|
"new_instance_type_id": uuid.uuid4().hex,
|
||||||
"project": uuid.uuid4().hex,
|
"project_id": uuid.uuid4().hex,
|
||||||
"user": uuid.uuid4().hex
|
"user_id": uuid.uuid4().hex
|
||||||
}
|
}
|
||||||
|
|
||||||
# Overwrite default attributes.
|
# Overwrite default attributes.
|
||||||
|
@ -4909,6 +4909,13 @@ class TestListMigration(TestServer):
|
|||||||
'Old Flavor', 'New Flavor', 'Created At', 'Updated At'
|
'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):
|
def setUp(self):
|
||||||
super(TestListMigration, self).setUp()
|
super(TestListMigration, self).setUp()
|
||||||
|
|
||||||
@ -4920,7 +4927,7 @@ class TestListMigration(TestServer):
|
|||||||
self.migrations_mock.list.return_value = self.migrations
|
self.migrations_mock.list.return_value = self.migrations
|
||||||
|
|
||||||
self.data = (common_utils.get_item_properties(
|
self.data = (common_utils.get_item_properties(
|
||||||
s, self.MIGRATION_COLUMNS) for s in self.migrations)
|
s, self.MIGRATION_FIELDS) for s in self.migrations)
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
self.cmd = server.ListMigration(self.app, None)
|
self.cmd = server.ListMigration(self.app, None)
|
||||||
@ -4982,6 +4989,13 @@ class TestListMigrationV223(TestListMigration):
|
|||||||
'Type', 'Created At', 'Updated At'
|
'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):
|
def setUp(self):
|
||||||
super(TestListMigrationV223, self).setUp()
|
super(TestListMigrationV223, self).setUp()
|
||||||
|
|
||||||
@ -5019,6 +5033,14 @@ class TestListMigrationV259(TestListMigration):
|
|||||||
'Old Flavor', 'New Flavor', 'Type', 'Created At', 'Updated At'
|
'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):
|
def setUp(self):
|
||||||
super(TestListMigrationV259, self).setUp()
|
super(TestListMigrationV259, self).setUp()
|
||||||
|
|
||||||
@ -5125,6 +5147,14 @@ class TestListMigrationV266(TestListMigration):
|
|||||||
'Old Flavor', 'New Flavor', 'Type', 'Created At', 'Updated At'
|
'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):
|
def setUp(self):
|
||||||
super(TestListMigrationV266, self).setUp()
|
super(TestListMigrationV266, self).setUp()
|
||||||
|
|
||||||
@ -5194,6 +5224,14 @@ class TestListMigrationV280(TestListMigration):
|
|||||||
'Old Flavor', 'New Flavor', 'Type', 'Created At', 'Updated At'
|
'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()
|
project = identity_fakes.FakeProject.create_one_project()
|
||||||
user = identity_fakes.FakeUser.create_one_user()
|
user = identity_fakes.FakeUser.create_one_user()
|
||||||
|
|
||||||
@ -5247,10 +5285,14 @@ class TestListMigrationV280(TestListMigration):
|
|||||||
|
|
||||||
self.MIGRATION_COLUMNS.insert(
|
self.MIGRATION_COLUMNS.insert(
|
||||||
len(self.MIGRATION_COLUMNS) - 2, "Project")
|
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(self.MIGRATION_COLUMNS, columns)
|
||||||
self.assertEqual(tuple(self.data), tuple(data))
|
self.assertEqual(tuple(self.data), tuple(data))
|
||||||
# Clean up global variables MIGRATION_COLUMNS
|
# Clean up global variables MIGRATION_COLUMNS
|
||||||
self.MIGRATION_COLUMNS.remove('Project')
|
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):
|
def test_get_migrations_with_project_pre_v280(self):
|
||||||
self.app.client_manager.compute.api_version = api_versions.APIVersion(
|
self.app.client_manager.compute.api_version = api_versions.APIVersion(
|
||||||
@ -5309,10 +5351,14 @@ class TestListMigrationV280(TestListMigration):
|
|||||||
|
|
||||||
self.MIGRATION_COLUMNS.insert(
|
self.MIGRATION_COLUMNS.insert(
|
||||||
len(self.MIGRATION_COLUMNS) - 2, "User")
|
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(self.MIGRATION_COLUMNS, columns)
|
||||||
self.assertEqual(tuple(self.data), tuple(data))
|
self.assertEqual(tuple(self.data), tuple(data))
|
||||||
# Clean up global variables MIGRATION_COLUMNS
|
# Clean up global variables MIGRATION_COLUMNS
|
||||||
self.MIGRATION_COLUMNS.remove('User')
|
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):
|
def test_get_migrations_with_user_pre_v280(self):
|
||||||
self.app.client_manager.compute.api_version = api_versions.APIVersion(
|
self.app.client_manager.compute.api_version = api_versions.APIVersion(
|
||||||
@ -5371,13 +5417,19 @@ class TestListMigrationV280(TestListMigration):
|
|||||||
|
|
||||||
self.MIGRATION_COLUMNS.insert(
|
self.MIGRATION_COLUMNS.insert(
|
||||||
len(self.MIGRATION_COLUMNS) - 2, "Project")
|
len(self.MIGRATION_COLUMNS) - 2, "Project")
|
||||||
|
self.MIGRATION_FIELDS.insert(
|
||||||
|
len(self.MIGRATION_FIELDS) - 2, "project_id")
|
||||||
self.MIGRATION_COLUMNS.insert(
|
self.MIGRATION_COLUMNS.insert(
|
||||||
len(self.MIGRATION_COLUMNS) - 2, "User")
|
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(self.MIGRATION_COLUMNS, columns)
|
||||||
self.assertEqual(tuple(self.data), tuple(data))
|
self.assertEqual(tuple(self.data), tuple(data))
|
||||||
# Clean up global variables MIGRATION_COLUMNS
|
# Clean up global variables MIGRATION_COLUMNS
|
||||||
self.MIGRATION_COLUMNS.remove('Project')
|
self.MIGRATION_COLUMNS.remove('Project')
|
||||||
|
self.MIGRATION_FIELDS.remove('project_id')
|
||||||
self.MIGRATION_COLUMNS.remove('User')
|
self.MIGRATION_COLUMNS.remove('User')
|
||||||
|
self.MIGRATION_FIELDS.remove('user_id')
|
||||||
|
|
||||||
def test_get_migrations_with_project_and_user_pre_v280(self):
|
def test_get_migrations_with_project_and_user_pre_v280(self):
|
||||||
self.app.client_manager.compute.api_version = api_versions.APIVersion(
|
self.app.client_manager.compute.api_version = api_versions.APIVersion(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user