summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/compute/v2/aggregate.py44
-rw-r--r--openstackclient/compute/v2/flavor.py21
-rw-r--r--openstackclient/compute/v2/hypervisor.py24
-rw-r--r--openstackclient/compute/v2/server.py83
-rw-r--r--openstackclient/compute/v2/server_group.py91
-rw-r--r--openstackclient/compute/v2/usage.py103
-rw-r--r--openstackclient/tests/functional/compute/v2/test_server_group.py12
-rw-r--r--openstackclient/tests/unit/compute/v2/test_aggregate.py20
-rw-r--r--openstackclient/tests/unit/compute/v2/test_flavor.py10
-rw-r--r--openstackclient/tests/unit/compute/v2/test_hypervisor.py45
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py71
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server_group.py79
-rw-r--r--openstackclient/tests/unit/compute/v2/test_usage.py42
13 files changed, 448 insertions, 197 deletions
diff --git a/openstackclient/compute/v2/aggregate.py b/openstackclient/compute/v2/aggregate.py
index 8b70f426..e39eb2d2 100644
--- a/openstackclient/compute/v2/aggregate.py
+++ b/openstackclient/compute/v2/aggregate.py
@@ -101,6 +101,7 @@ class CreateAggregate(command.ShowOne):
"--property",
metavar="<key=value>",
action=parseractions.KeyValueAction,
+ dest="properties",
help=_("Property to add to this aggregate "
"(repeat option to set multiple properties)")
)
@@ -116,10 +117,10 @@ class CreateAggregate(command.ShowOne):
aggregate = compute_client.create_aggregate(**attrs)
- if parsed_args.property:
+ if parsed_args.properties:
aggregate = compute_client.set_aggregate_metadata(
aggregate.id,
- parsed_args.property,
+ parsed_args.properties,
)
display_columns, columns = _get_aggregate_columns(aggregate)
@@ -269,12 +270,12 @@ class SetAggregate(command.Command):
"--property",
metavar="<key=value>",
action=parseractions.KeyValueAction,
+ dest="properties",
help=_("Property to set on <aggregate> "
"(repeat option to set multiple properties)")
)
parser.add_argument(
"--no-property",
- dest="no_property",
action="store_true",
help=_("Remove all properties from <aggregate> "
"(specify both --property and --no-property to "
@@ -296,21 +297,20 @@ class SetAggregate(command.Command):
if kwargs:
compute_client.update_aggregate(aggregate.id, **kwargs)
- set_property = {}
+ properties = {}
if parsed_args.no_property:
# NOTE(RuiChen): "availability_zone" can not be unset from
# properties. It is already excluded from show and create output.
- set_property.update({key: None
- for key in aggregate.metadata.keys()
- if key != 'availability_zone'})
- if parsed_args.property:
- set_property.update(parsed_args.property)
-
- if set_property:
- compute_client.set_aggregate_metadata(
- aggregate.id,
- set_property
- )
+ properties.update({
+ key: None for key in aggregate.metadata.keys()
+ if key != 'availability_zone'
+ })
+
+ if parsed_args.properties:
+ properties.update(parsed_args.properties)
+
+ if properties:
+ compute_client.set_aggregate_metadata(aggregate.id, properties)
class ShowAggregate(command.ShowOne):
@@ -354,7 +354,9 @@ class UnsetAggregate(command.Command):
parser.add_argument(
"--property",
metavar="<key>",
- action='append',
+ action="append",
+ default=[],
+ dest="properties",
help=_("Property to remove from aggregate "
"(repeat option to remove multiple properties)")
)
@@ -365,12 +367,10 @@ class UnsetAggregate(command.Command):
aggregate = compute_client.find_aggregate(
parsed_args.aggregate, ignore_missing=False)
- unset_property = {}
- if parsed_args.property:
- unset_property.update({key: None for key in parsed_args.property})
- if unset_property:
- compute_client.set_aggregate_metadata(
- aggregate, unset_property)
+ properties = {key: None for key in parsed_args.properties}
+
+ if properties:
+ compute_client.set_aggregate_metadata(aggregate.id, properties)
class CacheImageForAggregate(command.Command):
diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py
index fa98e131..a55aba2a 100644
--- a/openstackclient/compute/v2/flavor.py
+++ b/openstackclient/compute/v2/flavor.py
@@ -128,6 +128,7 @@ class CreateFlavor(command.ShowOne):
"--property",
metavar="<key=value>",
action=parseractions.KeyValueAction,
+ dest="properties",
help=_("Property to add for this flavor "
"(repeat option to set multiple properties)")
)
@@ -191,12 +192,12 @@ class CreateFlavor(command.ShowOne):
msg = _("Failed to add project %(project)s access to "
"flavor: %(e)s")
LOG.error(msg, {'project': parsed_args.project, 'e': e})
- if parsed_args.property:
+ if parsed_args.properties:
try:
flavor = compute_client.create_flavor_extra_specs(
- flavor, parsed_args.property)
+ flavor, parsed_args.properties)
except Exception as e:
- LOG.error(_("Failed to set flavor property: %s"), e)
+ LOG.error(_("Failed to set flavor properties: %s"), e)
display_columns, columns = _get_flavor_columns(flavor)
data = utils.get_dict_properties(flavor, columns,
@@ -398,6 +399,7 @@ class SetFlavor(command.Command):
"--property",
metavar="<key=value>",
action=parseractions.KeyValueAction,
+ dest="properties",
help=_("Property to add or modify for this flavor "
"(repeat option to set multiple properties)")
)
@@ -447,15 +449,15 @@ class SetFlavor(command.Command):
compute_client.delete_flavor_extra_specs_property(
flavor.id, key)
except Exception as e:
- LOG.error(_("Failed to clear flavor property: %s"), e)
+ LOG.error(_("Failed to clear flavor properties: %s"), e)
result += 1
- if parsed_args.property:
+ if parsed_args.properties:
try:
compute_client.create_flavor_extra_specs(
- flavor.id, parsed_args.property)
+ flavor.id, parsed_args.properties)
except Exception as e:
- LOG.error(_("Failed to set flavor property: %s"), e)
+ LOG.error(_("Failed to set flavor properties: %s"), e)
result += 1
if parsed_args.project:
@@ -537,6 +539,7 @@ class UnsetFlavor(command.Command):
"--property",
metavar="<key>",
action='append',
+ dest="properties",
help=_("Property to remove from flavor "
"(repeat option to unset multiple properties)")
)
@@ -563,8 +566,8 @@ class UnsetFlavor(command.Command):
raise exceptions.CommandError(_(e.message))
result = 0
- if parsed_args.property:
- for key in parsed_args.property:
+ if parsed_args.properties:
+ for key in parsed_args.properties:
try:
compute_client.delete_flavor_extra_specs_property(
flavor.id, key)
diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py
index 7f110028..8fdb6698 100644
--- a/openstackclient/compute/v2/hypervisor.py
+++ b/openstackclient/compute/v2/hypervisor.py
@@ -15,9 +15,12 @@
"""Hypervisor action implementations"""
+import json
import re
+from novaclient import api_versions
from novaclient import exceptions as nova_exceptions
+from osc_lib.cli import format_columns
from osc_lib.command import command
from osc_lib import utils
@@ -86,8 +89,8 @@ class ShowHypervisor(command.ShowOne):
if aggregates:
# Hypervisors in nova cells are prefixed by "<cell>@"
if "@" in hypervisor['service']['host']:
- cell, service_host = hypervisor['service']['host'].split('@',
- 1)
+ cell, service_host = hypervisor['service']['host'].split(
+ '@', 1)
else:
cell = None
service_host = hypervisor['service']['host']
@@ -125,4 +128,19 @@ class ShowHypervisor(command.ShowOne):
hypervisor["service_host"] = hypervisor["service"]["host"]
del hypervisor["service"]
- return zip(*sorted(hypervisor.items()))
+ if compute_client.api_version < api_versions.APIVersion('2.28'):
+ # microversion 2.28 transformed this to a JSON blob rather than a
+ # string; on earlier fields, do this manually
+ if hypervisor['cpu_info']:
+ hypervisor['cpu_info'] = json.loads(hypervisor['cpu_info'])
+ else:
+ hypervisor['cpu_info'] = {}
+
+ columns = tuple(sorted(hypervisor))
+ data = utils.get_dict_properties(
+ hypervisor, columns,
+ formatters={
+ 'cpu_info': format_columns.DictColumn,
+ })
+
+ return (columns, data)
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index 2d6a4b18..c49c1815 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -614,6 +614,7 @@ class CreateServer(command.ShowOne):
'--image-property',
metavar='<key=value>',
action=parseractions.KeyValueAction,
+ dest='image_properties',
help=_("Image property to be matched"),
)
disk_group.add_argument(
@@ -659,6 +660,7 @@ class CreateServer(command.ShowOne):
'--property',
metavar='<key=value>',
action=parseractions.KeyValueAction,
+ dest='properties',
help=_(
'Set a property on this server '
'(repeat option to set multiple values)'
@@ -886,8 +888,8 @@ class CreateServer(command.ShowOne):
image = image_client.find_image(
parsed_args.image, ignore_missing=False)
- if not image and parsed_args.image_property:
- def emit_duplicated_warning(img, image_property):
+ if not image and parsed_args.image_properties:
+ def emit_duplicated_warning(img):
img_uuid_list = [str(image.id) for image in img]
LOG.warning(
'Multiple matching images: %(img_uuid_list)s\n'
@@ -930,9 +932,9 @@ class CreateServer(command.ShowOne):
return images_matched
- images = _match_image(image_client, parsed_args.image_property)
+ images = _match_image(image_client, parsed_args.image_properties)
if len(images) > 1:
- emit_duplicated_warning(images, parsed_args.image_property)
+ emit_duplicated_warning(images, parsed_args.image_properties)
if images:
image = images[0]
else:
@@ -1195,7 +1197,7 @@ class CreateServer(command.ShowOne):
config_drive = parsed_args.config_drive
boot_kwargs = dict(
- meta=parsed_args.property,
+ meta=parsed_args.properties,
files=files,
reservation_id=None,
min_count=parsed_args.min,
@@ -2670,6 +2672,7 @@ class RebuildServer(command.ShowOne):
'--property',
metavar='<key=value>',
action=parseractions.KeyValueAction,
+ dest='properties',
help=_(
'Set a new property on the rebuilt server '
'(repeat option to set multiple values)'
@@ -2811,8 +2814,8 @@ class RebuildServer(command.ShowOne):
if parsed_args.preserve_ephemeral is not None:
kwargs['preserve_ephemeral'] = parsed_args.preserve_ephemeral
- if parsed_args.property:
- kwargs['meta'] = parsed_args.property
+ if parsed_args.properties:
+ kwargs['meta'] = parsed_args.properties
if parsed_args.description:
if compute_client.api_version < api_versions.APIVersion('2.19'):
@@ -3475,9 +3478,10 @@ class SetServer(command.Command):
help=_('Set new root password (interactive only)'),
)
parser.add_argument(
- "--property",
- metavar="<key=value>",
+ '--property',
+ metavar='<key=value>',
action=parseractions.KeyValueAction,
+ dest='properties',
help=_('Property to add/change for this server '
'(repeat option to set multiple properties)'),
)
@@ -3518,11 +3522,8 @@ class SetServer(command.Command):
if parsed_args.name:
server.update(name=parsed_args.name)
- if parsed_args.property:
- compute_client.servers.set_meta(
- server,
- parsed_args.property,
- )
+ if parsed_args.properties:
+ compute_client.servers.set_meta(server, parsed_args.properties)
if parsed_args.state:
server.reset_state(state=parsed_args.state)
@@ -3580,7 +3581,8 @@ class ShelveServer(command.Command):
class ShowServer(command.ShowOne):
_description = _(
"Show server details. Specify ``--os-compute-api-version 2.47`` "
- "or higher to see the embedded flavor information for the server.")
+ "or higher to see the embedded flavor information for the server."
+ )
def get_parser(self, prog_name):
parser = super(ShowServer, self).get_parser(prog_name)
@@ -3589,18 +3591,29 @@ class ShowServer(command.ShowOne):
metavar='<server>',
help=_('Server (name or ID)'),
)
- parser.add_argument(
+ # TODO(stephenfin): This should be a separate command, not a flag
+ diagnostics_group = parser.add_mutually_exclusive_group()
+ diagnostics_group.add_argument(
'--diagnostics',
action='store_true',
default=False,
help=_('Display server diagnostics information'),
)
+ diagnostics_group.add_argument(
+ '--topology',
+ action='store_true',
+ default=False,
+ help=_(
+ 'Include topology information in the output '
+ '(supported by --os-compute-api-version 2.78 or above)'
+ ),
+ )
return parser
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
- server = utils.find_resource(compute_client.servers,
- parsed_args.server)
+ server = utils.find_resource(
+ compute_client.servers, parsed_args.server)
if parsed_args.diagnostics:
(resp, data) = server.diagnostics()
@@ -3609,10 +3622,26 @@ class ShowServer(command.ShowOne):
"Error retrieving diagnostics data\n"
))
return ({}, {})
- else:
- data = _prep_server_detail(compute_client,
- self.app.client_manager.image, server,
- refresh=False)
+ return zip(*sorted(data.items()))
+
+ topology = None
+ if parsed_args.topology:
+ if compute_client.api_version < api_versions.APIVersion('2.78'):
+ msg = _(
+ '--os-compute-api-version 2.78 or greater is required to '
+ 'support the --topology option'
+ )
+ raise exceptions.CommandError(msg)
+
+ topology = server.topology()
+
+ data = _prep_server_detail(
+ compute_client, self.app.client_manager.image, server,
+ refresh=False)
+
+ if topology:
+ data['topology'] = format_columns.DictColumn(topology)
+
return zip(*sorted(data.items()))
@@ -3909,6 +3938,7 @@ class UnsetServer(command.Command):
metavar='<key>',
action='append',
default=[],
+ dest='properties',
help=_('Property key to remove from server '
'(repeat option to remove multiple values)'),
)
@@ -3928,7 +3958,7 @@ class UnsetServer(command.Command):
help=_(
'Tag to remove from the server. '
'Specify multiple times to remove multiple tags. '
- '(supported by --os-compute-api-version 2.26 or later'
+ '(supported by --os-compute-api-version 2.26 or above)'
),
)
return parser
@@ -3940,11 +3970,8 @@ class UnsetServer(command.Command):
parsed_args.server,
)
- if parsed_args.property:
- compute_client.servers.delete_meta(
- server,
- parsed_args.property,
- )
+ if parsed_args.properties:
+ compute_client.servers.delete_meta(server, parsed_args.properties)
if parsed_args.description:
if compute_client.api_version < api_versions.APIVersion("2.19"):
diff --git a/openstackclient/compute/v2/server_group.py b/openstackclient/compute/v2/server_group.py
index a3363244..783fdbfe 100644
--- a/openstackclient/compute/v2/server_group.py
+++ b/openstackclient/compute/v2/server_group.py
@@ -18,6 +18,8 @@
import logging
from novaclient import api_versions
+from osc_lib.cli import format_columns
+from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@@ -29,8 +31,9 @@ LOG = logging.getLogger(__name__)
_formatters = {
- 'policies': utils.format_list,
- 'members': utils.format_list,
+ 'members': format_columns.ListColumn,
+ 'policies': format_columns.ListColumn,
+ 'rules': format_columns.DictColumn,
}
@@ -67,7 +70,19 @@ class CreateServerGroup(command.ShowOne):
"Add a policy to <name> "
"Specify --os-compute-api-version 2.15 or higher for the "
"'soft-affinity' or 'soft-anti-affinity' policy."
- )
+ ),
+ )
+ parser.add_argument(
+ '--rule',
+ metavar='<key=value>',
+ action=parseractions.KeyValueAction,
+ default={},
+ dest='rules',
+ help=_(
+ "A rule for the policy. Currently, only the "
+ "'max_server_per_host' rule is supported for the "
+ "'anti-affinity' policy."
+ ),
)
return parser
@@ -83,18 +98,30 @@ class CreateServerGroup(command.ShowOne):
)
raise exceptions.CommandError(msg % parsed_args.policy)
- policy_arg = {'policies': [parsed_args.policy]}
- if compute_client.api_version >= api_versions.APIVersion("2.64"):
- policy_arg = {'policy': parsed_args.policy}
+ if parsed_args.rules:
+ if compute_client.api_version < api_versions.APIVersion('2.64'):
+ msg = _(
+ '--os-compute-api-version 2.64 or greater is required to '
+ 'support the --rule option'
+ )
+ raise exceptions.CommandError(msg)
+
+ if compute_client.api_version < api_versions.APIVersion('2.64'):
+ kwargs = {'policies': [parsed_args.policy]}
+ else:
+ kwargs = {
+ 'policy': parsed_args.policy,
+ 'rules': parsed_args.rules or None,
+ }
server_group = compute_client.server_groups.create(
- name=parsed_args.name, **policy_arg)
+ name=parsed_args.name, **kwargs)
info.update(server_group._info)
columns = _get_columns(info)
- data = utils.get_dict_properties(info, columns,
- formatters=_formatters)
+ data = utils.get_dict_properties(
+ info, columns, formatters=_formatters)
return columns, data
@@ -160,30 +187,36 @@ class ListServerGroup(command.Lister):
if compute_client.api_version >= api_versions.APIVersion("2.64"):
policy_key = 'Policy'
+ columns = (
+ 'id',
+ 'name',
+ policy_key.lower(),
+ )
+ column_headers = (
+ 'ID',
+ 'Name',
+ policy_key,
+ )
if parsed_args.long:
- column_headers = columns = (
- 'ID',
- 'Name',
- policy_key,
+ columns += (
+ 'members',
+ 'project_id',
+ 'user_id',
+ )
+ column_headers += (
'Members',
'Project Id',
'User Id',
)
- else:
- column_headers = columns = (
- 'ID',
- 'Name',
- policy_key,
- )
- return (column_headers,
- (utils.get_item_properties(
- s, columns,
- formatters={
- 'Policies': utils.format_list,
- 'Members': utils.format_list,
- }
- ) for s in data))
+ return (
+ column_headers,
+ (
+ utils.get_item_properties(
+ s, columns, formatters=_formatters,
+ ) for s in data
+ ),
+ )
class ShowServerGroup(command.ShowOne):
@@ -205,6 +238,6 @@ class ShowServerGroup(command.ShowOne):
info = {}
info.update(group._info)
columns = _get_columns(info)
- data = utils.get_dict_properties(info, columns,
- formatters=_formatters)
+ data = utils.get_dict_properties(
+ info, columns, formatters=_formatters)
return columns, data
diff --git a/openstackclient/compute/v2/usage.py b/openstackclient/compute/v2/usage.py
index 307c238a..69fa04e8 100644
--- a/openstackclient/compute/v2/usage.py
+++ b/openstackclient/compute/v2/usage.py
@@ -17,7 +17,9 @@
import collections
import datetime
+import functools
+from cliff import columns as cliff_columns
from novaclient import api_versions
from osc_lib.command import command
from osc_lib import utils
@@ -25,6 +27,57 @@ from osc_lib import utils
from openstackclient.i18n import _
+# TODO(stephenfin): This exists in a couple of places and should be moved to a
+# common module
+class ProjectColumn(cliff_columns.FormattableColumn):
+ """Formattable column for project column.
+
+ Unlike the parent FormattableColumn class, the initializer of the class
+ takes project_cache as the second argument.
+ ``osc_lib.utils.get_item_properties`` instantiates ``FormattableColumn``
+ objects with a single parameter, the column value, so you need to pass a
+ partially initialized class like ``functools.partial(ProjectColumn,
+ project_cache)`` to use this.
+ """
+
+ def __init__(self, value, project_cache=None):
+ super().__init__(value)
+ self.project_cache = project_cache or {}
+
+ def human_readable(self):
+ project = self._value
+ if not project:
+ return ''
+
+ if project in self.project_cache.keys():
+ return self.project_cache[project].name
+
+ return project
+
+
+class CountColumn(cliff_columns.FormattableColumn):
+
+ def human_readable(self):
+ return len(self._value)
+
+
+class FloatColumn(cliff_columns.FormattableColumn):
+
+ def human_readable(self):
+ return float("%.2f" % self._value)
+
+
+def _formatters(project_cache):
+ return {
+ 'tenant_id': functools.partial(
+ ProjectColumn, project_cache=project_cache),
+ 'server_usages': CountColumn,
+ 'total_memory_mb_usage': FloatColumn,
+ 'total_vcpus_usage': FloatColumn,
+ 'total_local_gb_usage': FloatColumn,
+ }
+
+
def _get_usage_marker(usage):
marker = None
if hasattr(usage, 'server_usages') and usage.server_usages:
@@ -147,17 +200,15 @@ class ListUsage(command.Lister):
"end": end.strftime(dateformat),
})
- return (column_headers,
- (utils.get_item_properties(
+ return (
+ column_headers,
+ (
+ utils.get_item_properties(
s, columns,
- formatters={
- 'tenant_id': _format_project,
- 'server_usages': lambda x: len(x),
- 'total_memory_mb_usage': lambda x: float("%.2f" % x),
- 'total_vcpus_usage': lambda x: float("%.2f" % x),
- 'total_local_gb_usage': lambda x: float("%.2f" % x),
- },
- ) for s in usage_list))
+ formatters=_formatters(project_cache),
+ ) for s in usage_list
+ ),
+ )
class ShowUsage(command.ShowOne):
@@ -222,17 +273,21 @@ class ShowUsage(command.ShowOne):
"project": project,
})
- info = {}
- info['Servers'] = (
- len(usage.server_usages)
- if hasattr(usage, "server_usages") else None)
- info['RAM MB-Hours'] = (
- float("%.2f" % usage.total_memory_mb_usage)
- if hasattr(usage, "total_memory_mb_usage") else None)
- info['CPU Hours'] = (
- float("%.2f" % usage.total_vcpus_usage)
- if hasattr(usage, "total_vcpus_usage") else None)
- info['Disk GB-Hours'] = (
- float("%.2f" % usage.total_local_gb_usage)
- if hasattr(usage, "total_local_gb_usage") else None)
- return zip(*sorted(info.items()))
+ columns = (
+ "tenant_id",
+ "server_usages",
+ "total_memory_mb_usage",
+ "total_vcpus_usage",
+ "total_local_gb_usage"
+ )
+ column_headers = (
+ "Project",
+ "Servers",
+ "RAM MB-Hours",
+ "CPU Hours",
+ "Disk GB-Hours"
+ )
+
+ data = utils.get_item_properties(
+ usage, columns, formatters=_formatters(None))
+ return column_headers, data
diff --git a/openstackclient/tests/functional/compute/v2/test_server_group.py b/openstackclient/tests/functional/compute/v2/test_server_group.py
index 44ecda1d..3dff3dcd 100644
--- a/openstackclient/tests/functional/compute/v2/test_server_group.py
+++ b/openstackclient/tests/functional/compute/v2/test_server_group.py
@@ -33,7 +33,7 @@ class ServerGroupTests(base.TestCase):
cmd_output['name']
)
self.assertEqual(
- 'affinity',
+ ['affinity'],
cmd_output['policies']
)
@@ -47,7 +47,7 @@ class ServerGroupTests(base.TestCase):
cmd_output['name']
)
self.assertEqual(
- 'anti-affinity',
+ ['anti-affinity'],
cmd_output['policies']
)
@@ -74,7 +74,7 @@ class ServerGroupTests(base.TestCase):
cmd_output['name']
)
self.assertEqual(
- 'affinity',
+ ['affinity'],
cmd_output['policies']
)
@@ -91,7 +91,7 @@ class ServerGroupTests(base.TestCase):
cmd_output['name']
)
self.assertEqual(
- 'anti-affinity',
+ ['anti-affinity'],
cmd_output['policies']
)
@@ -102,5 +102,5 @@ class ServerGroupTests(base.TestCase):
self.assertIn(name1, names)
self.assertIn(name2, names)
policies = [x["Policies"] for x in cmd_output]
- self.assertIn('affinity', policies)
- self.assertIn('anti-affinity', policies)
+ self.assertIn(['affinity'], policies)
+ self.assertIn(['anti-affinity'], policies)
diff --git a/openstackclient/tests/unit/compute/v2/test_aggregate.py b/openstackclient/tests/unit/compute/v2/test_aggregate.py
index e12edd0f..8563f988 100644
--- a/openstackclient/tests/unit/compute/v2/test_aggregate.py
+++ b/openstackclient/tests/unit/compute/v2/test_aggregate.py
@@ -138,7 +138,7 @@ class TestAggregateCreate(TestAggregate):
'ag1',
]
verifylist = [
- ('property', {'key1': 'value1', 'key2': 'value2'}),
+ ('properties', {'key1': 'value1', 'key2': 'value2'}),
('name', 'ag1'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -146,7 +146,7 @@ class TestAggregateCreate(TestAggregate):
self.sdk_client.create_aggregate.assert_called_once_with(
name=parsed_args.name)
self.sdk_client.set_aggregate_metadata.assert_called_once_with(
- self.fake_ag.id, parsed_args.property)
+ self.fake_ag.id, parsed_args.properties)
self.assertEqual(self.columns, columns)
self.assertItemsEqual(self.data, data)
@@ -378,7 +378,7 @@ class TestAggregateSet(TestAggregate):
'ag1',
]
verifylist = [
- ('property', {'key1': 'value1', 'key2': 'value2'}),
+ ('properties', {'key1': 'value1', 'key2': 'value2'}),
('aggregate', 'ag1'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -388,7 +388,7 @@ class TestAggregateSet(TestAggregate):
parsed_args.aggregate, ignore_missing=False)
self.assertNotCalled(self.sdk_client.update_aggregate)
self.sdk_client.set_aggregate_metadata.assert_called_once_with(
- self.fake_ag.id, parsed_args.property)
+ self.fake_ag.id, parsed_args.properties)
self.assertIsNone(result)
def test_aggregate_set_with_no_property_and_property(self):
@@ -399,7 +399,7 @@ class TestAggregateSet(TestAggregate):
]
verifylist = [
('no_property', True),
- ('property', {'key2': 'value2'}),
+ ('properties', {'key2': 'value2'}),
('aggregate', 'ag1'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -509,14 +509,14 @@ class TestAggregateUnset(TestAggregate):
'ag1',
]
verifylist = [
- ('property', ['unset_key']),
+ ('properties', ['unset_key']),
('aggregate', 'ag1'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.sdk_client.set_aggregate_metadata.assert_called_once_with(
- self.fake_ag, {'unset_key': None})
+ self.fake_ag.id, {'unset_key': None})
self.assertIsNone(result)
def test_aggregate_unset_multiple_properties(self):
@@ -526,14 +526,14 @@ class TestAggregateUnset(TestAggregate):
'ag1',
]
verifylist = [
- ('property', ['unset_key1', 'unset_key2']),
+ ('properties', ['unset_key1', 'unset_key2']),
('aggregate', 'ag1'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.sdk_client.set_aggregate_metadata.assert_called_once_with(
- self.fake_ag, {'unset_key1': None, 'unset_key2': None})
+ self.fake_ag.id, {'unset_key1': None, 'unset_key2': None})
self.assertIsNone(result)
def test_aggregate_unset_no_option(self):
@@ -541,7 +541,7 @@ class TestAggregateUnset(TestAggregate):
'ag1',
]
verifylist = [
- ('property', None),
+ ('properties', []),
('aggregate', 'ag1'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
diff --git a/openstackclient/tests/unit/compute/v2/test_flavor.py b/openstackclient/tests/unit/compute/v2/test_flavor.py
index 8c1147fd..ee4479b0 100644
--- a/openstackclient/tests/unit/compute/v2/test_flavor.py
+++ b/openstackclient/tests/unit/compute/v2/test_flavor.py
@@ -160,7 +160,7 @@ class TestFlavorCreate(TestFlavor):
('rxtx_factor', self.flavor.rxtx_factor),
('public', True),
('description', self.flavor.description),
- ('property', {'property': 'value'}),
+ ('properties', {'property': 'value'}),
('name', self.flavor.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -232,7 +232,7 @@ class TestFlavorCreate(TestFlavor):
('public', False),
('description', 'description'),
('project', self.project.id),
- ('property', {'key1': 'value1', 'key2': 'value2'}),
+ ('properties', {'key1': 'value1', 'key2': 'value2'}),
('name', self.flavor.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -688,7 +688,7 @@ class TestFlavorSet(TestFlavor):
'baremetal'
]
verifylist = [
- ('property', {'FOO': '"B A R"'}),
+ ('properties', {'FOO': '"B A R"'}),
('flavor', 'baremetal')
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1017,7 +1017,7 @@ class TestFlavorUnset(TestFlavor):
'baremetal'
]
verifylist = [
- ('property', ['property']),
+ ('properties', ['property']),
('flavor', 'baremetal'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1039,7 +1039,7 @@ class TestFlavorUnset(TestFlavor):
'baremetal'
]
verifylist = [
- ('property', ['property1', 'property2']),
+ ('properties', ['property1', 'property2']),
('flavor', 'baremetal'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
diff --git a/openstackclient/tests/unit/compute/v2/test_hypervisor.py b/openstackclient/tests/unit/compute/v2/test_hypervisor.py
index 7200d04e..518109c6 100644
--- a/openstackclient/tests/unit/compute/v2/test_hypervisor.py
+++ b/openstackclient/tests/unit/compute/v2/test_hypervisor.py
@@ -14,8 +14,11 @@
#
import copy
+import json
+from novaclient import api_versions
from novaclient import exceptions as nova_exceptions
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from openstackclient.compute.v2 import hypervisor
@@ -247,7 +250,7 @@ class TestHypervisorShow(TestHypervisor):
)
self.data = (
[],
- {'aaa': 'aaa'},
+ format_columns.DictColumn({'aaa': 'aaa'}),
0,
50,
50,
@@ -278,6 +281,35 @@ class TestHypervisorShow(TestHypervisor):
self.cmd = hypervisor.ShowHypervisor(self.app, None)
def test_hypervisor_show(self):
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.28')
+
+ arglist = [
+ self.hypervisor.hypervisor_hostname,
+ ]
+ verifylist = [
+ ('hypervisor', self.hypervisor.hypervisor_hostname),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class ShowOne in cliff, abstract method take_action()
+ # returns a two-part tuple with a tuple of column names and a tuple of
+ # data to be shown.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.assertEqual(self.columns, columns)
+ self.assertItemsEqual(self.data, data)
+
+ def test_hypervisor_show_pre_v228(self):
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.27')
+
+ # before microversion 2.28, nova returned a stringified version of this
+ # field
+ self.hypervisor._info['cpu_info'] = json.dumps(
+ self.hypervisor._info['cpu_info'])
+ self.hypervisors_mock.get.return_value = self.hypervisor
+
arglist = [
self.hypervisor.hypervisor_hostname,
]
@@ -292,9 +324,12 @@ class TestHypervisorShow(TestHypervisor):
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemsEqual(self.data, data)
+
+ def test_hypervisor_show_uptime_not_implemented(self):
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.28')
- def test_hyprvisor_show_uptime_not_implemented(self):
arglist = [
self.hypervisor.hypervisor_hostname,
]
@@ -337,7 +372,7 @@ class TestHypervisorShow(TestHypervisor):
)
expected_data = (
[],
- {'aaa': 'aaa'},
+ format_columns.DictColumn({'aaa': 'aaa'}),
0,
50,
50,
@@ -361,4 +396,4 @@ class TestHypervisorShow(TestHypervisor):
)
self.assertEqual(expected_columns, columns)
- self.assertEqual(expected_data, data)
+ self.assertItemsEqual(expected_data, data)
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index 0eeb2cec..f046925a 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -1159,7 +1159,7 @@ class TestServerCreate(TestServer):
('image', 'image1'),
('flavor', 'flavor1'),
('key_name', 'keyname'),
- ('property', {'Beta': 'b'}),
+ ('properties', {'Beta': 'b'}),
('security_group', ['securitygroup']),
('hint', {'a': ['b', 'c']}),
('config_drive', True),
@@ -2227,7 +2227,7 @@ class TestServerCreate(TestServer):
self.new_server.name,
]
verifylist = [
- ('image_property', {'hypervisor_type': 'qemu'}),
+ ('image_properties', {'hypervisor_type': 'qemu'}),
('flavor', 'flavor1'),
('nic', ['none']),
('config_drive', False),
@@ -2282,7 +2282,7 @@ class TestServerCreate(TestServer):
self.new_server.name,
]
verifylist = [
- ('image_property', {'hypervisor_type': 'qemu',
+ ('image_properties', {'hypervisor_type': 'qemu',
'hw_disk_bus': 'ide'}),
('flavor', 'flavor1'),
('nic', ['none']),
@@ -2338,7 +2338,7 @@ class TestServerCreate(TestServer):
self.new_server.name,
]
verifylist = [
- ('image_property', {'hypervisor_type': 'qemu',
+ ('image_properties', {'hypervisor_type': 'qemu',
'hw_disk_bus': 'virtio'}),
('flavor', 'flavor1'),
('nic', ['none']),
@@ -2370,7 +2370,7 @@ class TestServerCreate(TestServer):
]
verifylist = [
- ('image_property',
+ ('image_properties',
{'owner_specified.openstack.object': 'image/cirros'}),
('flavor', 'flavor1'),
('nic', ['none']),
@@ -5109,10 +5109,10 @@ class TestServerRebuild(TestServer):
'--property', 'key1=value1',
'--property', 'key2=value2'
]
- expected_property = {'key1': 'value1', 'key2': 'value2'}
+ expected_properties = {'key1': 'value1', 'key2': 'value2'}
verifylist = [
('server', self.server.id),
- ('property', expected_property)
+ ('properties', expected_properties)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -5122,7 +5122,7 @@ class TestServerRebuild(TestServer):
self.servers_mock.get.assert_called_with(self.server.id)
self.get_image_mock.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
- self.image, None, meta=expected_property)
+ self.image, None, meta=expected_properties)
def test_rebuild_with_keypair_name(self):
self.app.client_manager.compute.api_version = \
@@ -6281,13 +6281,13 @@ class TestServerSet(TestServer):
'foo_vm',
]
verifylist = [
- ('property', {'key1': 'value1', 'key2': 'value2'}),
+ ('properties', {'key1': 'value1', 'key2': 'value2'}),
('server', 'foo_vm'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.servers_mock.set_meta.assert_called_once_with(
- self.fake_servers[0], parsed_args.property)
+ self.fake_servers[0], parsed_args.properties)
self.assertIsNone(result)
@mock.patch.object(getpass, 'getpass',
@@ -6421,6 +6421,10 @@ class TestServerShow(TestServer):
self.image = image_fakes.FakeImage.create_one_image()
self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
+ self.topology = {
+ 'nodes': [{'vcpu_set': [0, 1]}, {'vcpu_set': [2, 3]}],
+ 'pagesize_kb': None,
+ }
server_info = {
'image': {'id': self.image.id},
'flavor': {'id': self.flavor.id},
@@ -6434,6 +6438,7 @@ class TestServerShow(TestServer):
resp.status_code = 200
server_method = {
'diagnostics': (resp, {'test': 'test'}),
+ 'topology': self.topology,
}
self.server = compute_fakes.FakeServer.create_one_server(
attrs=server_info, methods=server_method)
@@ -6484,6 +6489,7 @@ class TestServerShow(TestServer):
]
verifylist = [
('diagnostics', False),
+ ('topology', False),
('server', self.server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -6501,6 +6507,7 @@ class TestServerShow(TestServer):
]
verifylist = [
('diagnostics', False),
+ ('topology', False),
('server', self.server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -6527,6 +6534,7 @@ class TestServerShow(TestServer):
]
verifylist = [
('diagnostics', True),
+ ('topology', False),
('server', self.server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -6536,6 +6544,47 @@ class TestServerShow(TestServer):
self.assertEqual(('test',), columns)
self.assertEqual(('test',), data)
+ def test_show_topology(self):
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.78')
+
+ arglist = [
+ '--topology',
+ self.server.name,
+ ]
+ verifylist = [
+ ('diagnostics', False),
+ ('topology', True),
+ ('server', self.server.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.columns += ('topology',)
+ self.data += (format_columns.DictColumn(self.topology),)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(self.data, data)
+
+ def test_show_topology_pre_v278(self):
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.77')
+
+ arglist = [
+ '--topology',
+ self.server.name,
+ ]
+ verifylist = [
+ ('diagnostics', False),
+ ('topology', True),
+ ('server', self.server.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(
+ exceptions.CommandError, self.cmd.take_action, parsed_args)
+
class TestServerStart(TestServer):
@@ -6666,7 +6715,7 @@ class TestServerUnset(TestServer):
'foo_vm',
]
verifylist = [
- ('property', ['key1', 'key2']),
+ ('properties', ['key1', 'key2']),
('server', 'foo_vm'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
diff --git a/openstackclient/tests/unit/compute/v2/test_server_group.py b/openstackclient/tests/unit/compute/v2/test_server_group.py
index bf0ea0ba..732c1881 100644
--- a/openstackclient/tests/unit/compute/v2/test_server_group.py
+++ b/openstackclient/tests/unit/compute/v2/test_server_group.py
@@ -16,6 +16,7 @@
from unittest import mock
from novaclient import api_versions
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -39,9 +40,9 @@ class TestServerGroup(compute_fakes.TestComputev2):
data = (
fake_server_group.id,
- utils.format_list(fake_server_group.members),
+ format_columns.ListColumn(fake_server_group.members),
fake_server_group.name,
- utils.format_list(fake_server_group.policies),
+ format_columns.ListColumn(fake_server_group.policies),
fake_server_group.project_id,
fake_server_group.user_id,
)
@@ -70,7 +71,7 @@ class TestServerGroupV264(TestServerGroup):
data = (
fake_server_group.id,
- utils.format_list(fake_server_group.members),
+ format_columns.ListColumn(fake_server_group.members),
fake_server_group.name,
fake_server_group.policy,
fake_server_group.project_id,
@@ -105,8 +106,8 @@ class TestServerGroupCreate(TestServerGroup):
policies=[parsed_args.policy],
)
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(self.data, data)
def test_server_group_create_with_soft_policies(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion(
@@ -127,8 +128,8 @@ class TestServerGroupCreate(TestServerGroup):
policies=[parsed_args.policy],
)
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(self.data, data)
def test_server_group_create_with_soft_policies_pre_v215(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion(
@@ -151,27 +152,54 @@ class TestServerGroupCreate(TestServerGroup):
'--os-compute-api-version 2.15 or greater is required',
str(ex))
- def test_server_group_create_v264(self):
+ def test_server_group_create_with_rules(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion(
'2.64')
arglist = [
'--policy', 'soft-anti-affinity',
+ '--rule', 'max_server_per_host=2',
'affinity_group',
]
verifylist = [
('policy', 'soft-anti-affinity'),
+ ('rules', {'max_server_per_host': '2'}),
('name', 'affinity_group'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.server_groups_mock.create.assert_called_once_with(
name=parsed_args.name,
- policy=parsed_args.policy,
+ policy=parsed_args.policy, # should be 'policy', not 'policies'
+ rules=parsed_args.rules,
)
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(self.data, data)
+
+ def test_server_group_create_with_rules_pre_v264(self):
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.63')
+
+ arglist = [
+ '--policy', 'soft-anti-affinity',
+ '--rule', 'max_server_per_host=2',
+ 'affinity_group',
+ ]
+ verifylist = [
+ ('policy', 'soft-anti-affinity'),
+ ('rules', {'max_server_per_host': '2'}),
+ ('name', 'affinity_group'),
+ ]
+ 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.64 or greater is required',
+ str(ex))
class TestServerGroupDelete(TestServerGroup):
@@ -275,14 +303,14 @@ class TestServerGroupList(TestServerGroup):
list_data = ((
TestServerGroup.fake_server_group.id,
TestServerGroup.fake_server_group.name,
- utils.format_list(TestServerGroup.fake_server_group.policies),
+ format_columns.ListColumn(TestServerGroup.fake_server_group.policies),
),)
list_data_long = ((
TestServerGroup.fake_server_group.id,
TestServerGroup.fake_server_group.name,
- utils.format_list(TestServerGroup.fake_server_group.policies),
- utils.format_list(TestServerGroup.fake_server_group.members),
+ format_columns.ListColumn(TestServerGroup.fake_server_group.policies),
+ format_columns.ListColumn(TestServerGroup.fake_server_group.members),
TestServerGroup.fake_server_group.project_id,
TestServerGroup.fake_server_group.user_id,
),)
@@ -303,8 +331,8 @@ class TestServerGroupList(TestServerGroup):
columns, data = self.cmd.take_action(parsed_args)
self.server_groups_mock.list.assert_called_once_with(False)
- self.assertEqual(self.list_columns, columns)
- self.assertEqual(self.list_data, tuple(data))
+ self.assertCountEqual(self.list_columns, columns)
+ self.assertCountEqual(self.list_data, tuple(data))
def test_server_group_list_with_all_projects_and_long(self):
arglist = [
@@ -319,8 +347,8 @@ class TestServerGroupList(TestServerGroup):
columns, data = self.cmd.take_action(parsed_args)
self.server_groups_mock.list.assert_called_once_with(True)
- self.assertEqual(self.list_columns_long, columns)
- self.assertEqual(self.list_data_long, tuple(data))
+ self.assertCountEqual(self.list_columns_long, columns)
+ self.assertCountEqual(self.list_data_long, tuple(data))
class TestServerGroupListV264(TestServerGroupV264):
@@ -350,7 +378,8 @@ class TestServerGroupListV264(TestServerGroupV264):
TestServerGroupV264.fake_server_group.id,
TestServerGroupV264.fake_server_group.name,
TestServerGroupV264.fake_server_group.policy,
- utils.format_list(TestServerGroupV264.fake_server_group.members),
+ format_columns.ListColumn(
+ TestServerGroupV264.fake_server_group.members),
TestServerGroupV264.fake_server_group.project_id,
TestServerGroupV264.fake_server_group.user_id,
),)
@@ -373,8 +402,8 @@ class TestServerGroupListV264(TestServerGroupV264):
columns, data = self.cmd.take_action(parsed_args)
self.server_groups_mock.list.assert_called_once_with(False)
- self.assertEqual(self.list_columns, columns)
- self.assertEqual(self.list_data, tuple(data))
+ self.assertCountEqual(self.list_columns, columns)
+ self.assertCountEqual(self.list_data, tuple(data))
def test_server_group_list_with_all_projects_and_long(self):
arglist = [
@@ -389,8 +418,8 @@ class TestServerGroupListV264(TestServerGroupV264):
columns, data = self.cmd.take_action(parsed_args)
self.server_groups_mock.list.assert_called_once_with(True)
- self.assertEqual(self.list_columns_long, columns)
- self.assertEqual(self.list_data_long, tuple(data))
+ self.assertCountEqual(self.list_columns_long, columns)
+ self.assertCountEqual(self.list_data_long, tuple(data))
class TestServerGroupShow(TestServerGroup):
@@ -412,5 +441,5 @@ class TestServerGroupShow(TestServerGroup):
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.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(self.data, data)
diff --git a/openstackclient/tests/unit/compute/v2/test_usage.py b/openstackclient/tests/unit/compute/v2/test_usage.py
index c0871025..bbccb9bd 100644
--- a/openstackclient/tests/unit/compute/v2/test_usage.py
+++ b/openstackclient/tests/unit/compute/v2/test_usage.py
@@ -16,7 +16,7 @@ from unittest import mock
from novaclient import api_versions
-from openstackclient.compute.v2 import usage
+from openstackclient.compute.v2 import usage as usage_cmds
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
@@ -49,11 +49,11 @@ class TestUsageList(TestUsage):
)
data = [(
- usages[0].tenant_id,
- len(usages[0].server_usages),
- float("%.2f" % usages[0].total_memory_mb_usage),
- float("%.2f" % usages[0].total_vcpus_usage),
- float("%.2f" % usages[0].total_local_gb_usage),
+ usage_cmds.ProjectColumn(usages[0].tenant_id),
+ usage_cmds.CountColumn(usages[0].server_usages),
+ usage_cmds.FloatColumn(usages[0].total_memory_mb_usage),
+ usage_cmds.FloatColumn(usages[0].total_vcpus_usage),
+ usage_cmds.FloatColumn(usages[0].total_local_gb_usage),
)]
def setUp(self):
@@ -63,7 +63,7 @@ class TestUsageList(TestUsage):
self.projects_mock.list.return_value = [self.project]
# Get the command object to test
- self.cmd = usage.ListUsage(self.app, None)
+ self.cmd = usage_cmds.ListUsage(self.app, None)
def test_usage_list_no_options(self):
@@ -79,8 +79,8 @@ class TestUsageList(TestUsage):
self.projects_mock.list.assert_called_with()
- self.assertEqual(self.columns, columns)
- self.assertEqual(tuple(self.data), tuple(data))
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(tuple(self.data), tuple(data))
def test_usage_list_with_options(self):
arglist = [
@@ -102,8 +102,8 @@ class TestUsageList(TestUsage):
datetime.datetime(2016, 12, 20, 0, 0),
detailed=True)
- self.assertEqual(self.columns, columns)
- self.assertEqual(tuple(self.data), tuple(data))
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(tuple(self.data), tuple(data))
def test_usage_list_with_pagination(self):
arglist = []
@@ -127,8 +127,8 @@ class TestUsageList(TestUsage):
mock.call(mock.ANY, mock.ANY, detailed=True,
marker=self.usages[0]['server_usages'][0]['instance_id'])
])
- self.assertEqual(self.columns, columns)
- self.assertEqual(tuple(self.data), tuple(data))
+ self.assertCountEqual(self.columns, columns)
+ self.assertCountEqual(tuple(self.data), tuple(data))
class TestUsageShow(TestUsage):
@@ -139,17 +139,19 @@ class TestUsageShow(TestUsage):
attrs={'tenant_id': project.name})
columns = (
+ 'Project',
+ 'Servers',
+ 'RAM MB-Hours',
'CPU Hours',
'Disk GB-Hours',
- 'RAM MB-Hours',
- 'Servers',
)
data = (
- float("%.2f" % usage.total_vcpus_usage),
- float("%.2f" % usage.total_local_gb_usage),
- float("%.2f" % usage.total_memory_mb_usage),
- len(usage.server_usages),
+ usage_cmds.ProjectColumn(usage.tenant_id),
+ usage_cmds.CountColumn(usage.server_usages),
+ usage_cmds.FloatColumn(usage.total_memory_mb_usage),
+ usage_cmds.FloatColumn(usage.total_vcpus_usage),
+ usage_cmds.FloatColumn(usage.total_local_gb_usage),
)
def setUp(self):
@@ -159,7 +161,7 @@ class TestUsageShow(TestUsage):
self.projects_mock.get.return_value = self.project
# Get the command object to test
- self.cmd = usage.ShowUsage(self.app, None)
+ self.cmd = usage_cmds.ShowUsage(self.app, None)
def test_usage_show_no_options(self):