summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/contributor/humaninterfaceguide.rst4
-rw-r--r--openstackclient/image/v2/image.py58
-rw-r--r--openstackclient/network/v2/network_qos_rule_type.py25
-rw-r--r--openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py29
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py5
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py34
-rw-r--r--releasenotes/notes/network-qos-rule-type-filters-47f4911a02011501.yaml8
7 files changed, 138 insertions, 25 deletions
diff --git a/doc/source/contributor/humaninterfaceguide.rst b/doc/source/contributor/humaninterfaceguide.rst
index 5987b86f..db6d7987 100644
--- a/doc/source/contributor/humaninterfaceguide.rst
+++ b/doc/source/contributor/humaninterfaceguide.rst
@@ -246,7 +246,7 @@ Objects and Actions
Commands consist of an object, described by one or more words, followed by an
action. ::
- <object> <action> [<name-or-id>]
+ <object> <action>
For example:
@@ -411,7 +411,7 @@ For example:
* ``server show <name-or-id>`` (compute servers have names or IDs and can be
referenced by both)
* ``consumer show <id>`` (identity consumers only have IDs, not names)
-* ``server show --toplogy <name-or-id>`` (additional information should be
+* ``server show --topology <name-or-id>`` (additional information should be
provided as options)
``list``
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 21b962f1..ed99c174 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -33,7 +33,7 @@ from osc_lib import utils
from openstackclient.common import progressbar
from openstackclient.i18n import _
-from openstackclient.identity import common
+from openstackclient.identity import common as identity_common
if os.name == "nt":
import msvcrt
@@ -177,21 +177,22 @@ class AddProjectToImage(command.ShowOne):
metavar="<project>",
help=_("Project to associate with image (ID)"),
)
- common.add_project_domain_option_to_parser(parser)
+ identity_common.add_project_domain_option_to_parser(parser)
return parser
def take_action(self, parsed_args):
image_client = self.app.client_manager.image
identity_client = self.app.client_manager.identity
- project_id = common.find_project(
+ project_id = identity_common.find_project(
identity_client,
parsed_args.project,
parsed_args.project_domain,
).id
image = image_client.find_image(
- parsed_args.image, ignore_missing=False
+ parsed_args.image,
+ ignore_missing=False,
)
obj = image_client.add_member(
@@ -397,7 +398,7 @@ class CreateImage(command.ShowOne):
"Force the use of glance image import instead of direct upload"
),
)
- common.add_project_domain_option_to_parser(parser)
+ identity_common.add_project_domain_option_to_parser(parser)
for deadopt in self.deadopts:
parser.add_argument(
"--%s" % deadopt,
@@ -450,7 +451,7 @@ class CreateImage(command.ShowOne):
kwargs['visibility'] = parsed_args.visibility
if parsed_args.project:
- kwargs['owner_id'] = common.find_project(
+ kwargs['owner_id'] = identity_common.find_project(
identity_client,
parsed_args.project,
parsed_args.project_domain,
@@ -664,7 +665,8 @@ class DeleteImage(command.Command):
for image in parsed_args.images:
try:
image_obj = image_client.find_image(
- image, ignore_missing=False
+ image,
+ ignore_missing=False,
)
image_client.delete_image(image_obj.id)
except Exception as e:
@@ -765,7 +767,7 @@ class ListImage(command.Lister):
metavar='<project>',
help=_("Search by project (admin only) (name or ID)"),
)
- common.add_project_domain_option_to_parser(parser)
+ identity_common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--tag',
metavar='<tag>',
@@ -835,7 +837,10 @@ class ListImage(command.Lister):
if parsed_args.limit:
kwargs['limit'] = parsed_args.limit
if parsed_args.marker:
- kwargs['marker'] = image_client.find_image(parsed_args.marker).id
+ kwargs['marker'] = image_client.find_image(
+ parsed_args.marker,
+ ignore_missing=False,
+ ).id
if parsed_args.name:
kwargs['name'] = parsed_args.name
if parsed_args.status:
@@ -846,7 +851,7 @@ class ListImage(command.Lister):
kwargs['tag'] = parsed_args.tag
project_id = None
if parsed_args.project:
- project_id = common.find_project(
+ project_id = identity_common.find_project(
identity_client,
parsed_args.project,
parsed_args.project_domain,
@@ -925,14 +930,17 @@ class ListImageProjects(command.Lister):
metavar="<image>",
help=_("Image (name or ID)"),
)
- common.add_project_domain_option_to_parser(parser)
+ identity_common.add_project_domain_option_to_parser(parser)
return parser
def take_action(self, parsed_args):
image_client = self.app.client_manager.image
columns = ("Image ID", "Member ID", "Status")
- image_id = image_client.find_image(parsed_args.image).id
+ image_id = image_client.find_image(
+ parsed_args.image,
+ ignore_missing=False,
+ ).id
data = image_client.members(image=image_id)
@@ -963,19 +971,22 @@ class RemoveProjectImage(command.Command):
metavar="<project>",
help=_("Project to disassociate with image (name or ID)"),
)
- common.add_project_domain_option_to_parser(parser)
+ identity_common.add_project_domain_option_to_parser(parser)
return parser
def take_action(self, parsed_args):
image_client = self.app.client_manager.image
identity_client = self.app.client_manager.identity
- project_id = common.find_project(
- identity_client, parsed_args.project, parsed_args.project_domain
+ project_id = identity_common.find_project(
+ identity_client,
+ parsed_args.project,
+ parsed_args.project_domain,
).id
image = image_client.find_image(
- parsed_args.image, ignore_missing=False
+ parsed_args.image,
+ ignore_missing=False,
)
image_client.remove_member(member=project_id, image=image.id)
@@ -1001,7 +1012,10 @@ class SaveImage(command.Command):
def take_action(self, parsed_args):
image_client = self.app.client_manager.image
- image = image_client.find_image(parsed_args.image)
+ image = image_client.find_image(
+ parsed_args.image,
+ ignore_missing=False,
+ )
output_file = parsed_args.filename
if output_file is None:
@@ -1176,7 +1190,7 @@ class SetImage(command.Command):
metavar="<project>",
help=_("Set an alternate project on this image (name or ID)"),
)
- common.add_project_domain_option_to_parser(parser)
+ identity_common.add_project_domain_option_to_parser(parser)
for deadopt in self.deadopts:
parser.add_argument(
"--%s" % deadopt,
@@ -1248,7 +1262,7 @@ class SetImage(command.Command):
)
project_id = None
if parsed_args.project:
- project_id = common.find_project(
+ project_id = identity_common.find_project(
identity_client,
parsed_args.project,
parsed_args.project_domain,
@@ -1369,7 +1383,8 @@ class ShowImage(command.ShowOne):
image_client = self.app.client_manager.image
image = image_client.find_image(
- parsed_args.image, ignore_missing=False
+ parsed_args.image,
+ ignore_missing=False,
)
info = _format_image(image, parsed_args.human_readable)
@@ -1413,7 +1428,8 @@ class UnsetImage(command.Command):
def take_action(self, parsed_args):
image_client = self.app.client_manager.image
image = image_client.find_image(
- parsed_args.image, ignore_missing=False
+ parsed_args.image,
+ ignore_missing=False,
)
kwargs = {}
diff --git a/openstackclient/network/v2/network_qos_rule_type.py b/openstackclient/network/v2/network_qos_rule_type.py
index 9af22876..3f4f6a19 100644
--- a/openstackclient/network/v2/network_qos_rule_type.py
+++ b/openstackclient/network/v2/network_qos_rule_type.py
@@ -32,6 +32,23 @@ def _get_columns(item):
class ListNetworkQosRuleType(command.Lister):
_description = _("List QoS rule types")
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ supported = parser.add_mutually_exclusive_group()
+ supported.add_argument(
+ '--all-supported',
+ action='store_true',
+ help=_("List all the QoS rule types supported by any loaded "
+ "mechanism drivers (the union of all sets of supported "
+ "rules)")
+ )
+ supported.add_argument(
+ '--all-rules',
+ action='store_true',
+ help=_("List all QoS rule types implemented in Neutron QoS driver")
+ )
+ return parser
+
def take_action(self, parsed_args):
client = self.app.client_manager.network
columns = (
@@ -40,7 +57,13 @@ class ListNetworkQosRuleType(command.Lister):
column_headers = (
'Type',
)
- data = client.qos_rule_types()
+
+ args = {}
+ if parsed_args.all_supported:
+ args['all_supported'] = True
+ elif parsed_args.all_rules:
+ args['all_rules'] = True
+ data = client.qos_rule_types(**args)
return (column_headers,
(utils.get_item_properties(
diff --git a/openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py b/openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py
index 6b719cbe..4ead65cc 100644
--- a/openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py
+++ b/openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py
@@ -21,6 +21,13 @@ class NetworkQosRuleTypeTests(common.NetworkTests):
AVAILABLE_RULE_TYPES = ['dscp_marking',
'bandwidth_limit']
+ # NOTE(ralonsoh): this list was updated in Yoga (February 2022)
+ ALL_AVAILABLE_RULE_TYPES = ['dscp_marking',
+ 'bandwidth_limit',
+ 'minimum_bandwidth',
+ 'packet_rate_limit',
+ 'minimum_packet_rate',
+ ]
def setUp(self):
super(NetworkQosRuleTypeTests, self).setUp()
@@ -36,6 +43,28 @@ class NetworkQosRuleTypeTests(common.NetworkTests):
for rule_type in self.AVAILABLE_RULE_TYPES:
self.assertIn(rule_type, [x['Type'] for x in cmd_output])
+ def test_qos_rule_type_list_all_supported(self):
+ if not self.is_extension_enabled('qos-rule-type-filter'):
+ self.skipTest('No "qos-rule-type-filter" extension present')
+
+ cmd_output = self.openstack(
+ 'network qos rule type list --all-supported -f json',
+ parse_output=True
+ )
+ for rule_type in self.AVAILABLE_RULE_TYPES:
+ self.assertIn(rule_type, [x['Type'] for x in cmd_output])
+
+ def test_qos_rule_type_list_all_rules(self):
+ if not self.is_extension_enabled('qos-rule-type-filter'):
+ self.skipTest('No "qos-rule-type-filter" extension present')
+
+ cmd_output = self.openstack(
+ 'network qos rule type list --all-rules -f json',
+ parse_output=True
+ )
+ for rule_type in self.ALL_AVAILABLE_RULE_TYPES:
+ self.assertIn(rule_type, [x['Type'] for x in cmd_output])
+
def test_qos_rule_type_details(self):
for rule_type in self.AVAILABLE_RULE_TYPES:
cmd_output = self.openstack(
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index 010c4a9d..dccdabf0 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -905,7 +905,10 @@ class TestImageList(TestImage):
marker=self._image.id,
)
- self.client.find_image.assert_called_with('graven')
+ self.client.find_image.assert_called_with(
+ 'graven',
+ ignore_missing=False,
+ )
def test_image_list_name_option(self):
arglist = [
diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py b/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py
index 08a83fab..3aae822e 100644
--- a/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py
+++ b/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py
@@ -115,3 +115,37 @@ class TestListNetworkQosRuleType(TestNetworkQosRuleType):
self.network.qos_rule_types.assert_called_once_with(**{})
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
+
+ def test_qos_rule_type_list_all_supported(self):
+ arglist = [
+ '--all-supported'
+ ]
+ verifylist = [
+ ('all_supported', True),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.qos_rule_types.assert_called_once_with(
+ **{'all_supported': True}
+ )
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_qos_rule_type_list_all_rules(self):
+ arglist = [
+ '--all-rules'
+ ]
+ verifylist = [
+ ('all_rules', True),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.qos_rule_types.assert_called_once_with(
+ **{'all_rules': True}
+ )
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
diff --git a/releasenotes/notes/network-qos-rule-type-filters-47f4911a02011501.yaml b/releasenotes/notes/network-qos-rule-type-filters-47f4911a02011501.yaml
new file mode 100644
index 00000000..d0503f59
--- /dev/null
+++ b/releasenotes/notes/network-qos-rule-type-filters-47f4911a02011501.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Added two new filter flags to ``openstack network qos rule type list``:
+ ``--all-supported``, to return any QoS rule type supported by at least
+ one loaded driver; ``--all-rules``, to return all QoS rule types
+ supported by the current version of Neutron server, regardless of the
+ loaded drivers.