python-openstackclient 10.0.0__py3-none-any.whl → 10.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openstackclient/common/availability_zone.py +1 -1
- openstackclient/common/module.py +21 -27
- openstackclient/common/pagination.py +42 -4
- openstackclient/common/project_cleanup.py +1 -2
- openstackclient/common/quota.py +9 -5
- openstackclient/compute/v2/flavor.py +3 -1
- openstackclient/compute/v2/hypervisor.py +2 -0
- openstackclient/compute/v2/keypair.py +6 -2
- openstackclient/compute/v2/server.py +21 -12
- openstackclient/compute/v2/server_event.py +8 -1
- openstackclient/compute/v2/server_group.py +2 -0
- openstackclient/compute/v2/server_migration.py +3 -0
- openstackclient/compute/v2/server_volume.py +3 -1
- openstackclient/compute/v2/service.py +3 -1
- openstackclient/compute/v2/usage.py +2 -2
- openstackclient/identity/common.py +5 -1
- openstackclient/identity/v3/access_rule.py +6 -0
- openstackclient/identity/v3/application_credential.py +10 -3
- openstackclient/identity/v3/credential.py +4 -2
- openstackclient/identity/v3/domain.py +4 -2
- openstackclient/identity/v3/endpoint.py +57 -45
- openstackclient/identity/v3/federation_protocol.py +7 -5
- openstackclient/identity/v3/group.py +11 -10
- openstackclient/identity/v3/identity_provider.py +4 -1
- openstackclient/identity/v3/limit.py +5 -2
- openstackclient/identity/v3/mapping.py +36 -19
- openstackclient/identity/v3/project.py +18 -5
- openstackclient/identity/v3/region.py +4 -2
- openstackclient/identity/v3/registered_limit.py +3 -2
- openstackclient/identity/v3/role.py +2 -1
- openstackclient/identity/v3/role_assignment.py +3 -2
- openstackclient/identity/v3/service.py +4 -2
- openstackclient/identity/v3/service_provider.py +4 -2
- openstackclient/identity/v3/trust.py +8 -5
- openstackclient/identity/v3/user.py +38 -11
- openstackclient/image/v2/cache.py +2 -2
- openstackclient/image/v2/image.py +15 -9
- openstackclient/image/v2/metadef_namespaces.py +11 -10
- openstackclient/image/v2/metadef_objects.py +5 -5
- openstackclient/image/v2/metadef_properties.py +7 -4
- openstackclient/image/v2/task.py +11 -22
- openstackclient/network/utils.py +0 -41
- openstackclient/network/v2/address_group.py +13 -1
- openstackclient/network/v2/address_scope.py +13 -8
- openstackclient/network/v2/bgpvpn/bgpvpn.py +33 -19
- openstackclient/network/v2/bgpvpn/network_association.py +25 -13
- openstackclient/network/v2/bgpvpn/port_association.py +35 -21
- openstackclient/network/v2/bgpvpn/router_association.py +27 -14
- openstackclient/network/v2/default_security_group_rule.py +14 -6
- openstackclient/network/v2/floating_ip.py +12 -4
- openstackclient/network/v2/floating_ip_port_forwarding.py +12 -2
- openstackclient/network/v2/fwaas/group.py +34 -1
- openstackclient/network/v2/fwaas/rule.py +39 -3
- openstackclient/network/v2/ip_availability.py +13 -4
- openstackclient/network/v2/l3_conntrack_helper.py +14 -1
- openstackclient/network/v2/local_ip.py +4 -1
- openstackclient/network/v2/local_ip_association.py +4 -1
- openstackclient/network/v2/ndp_proxy.py +4 -1
- openstackclient/network/v2/network.py +87 -20
- openstackclient/network/v2/network_agent.py +32 -10
- openstackclient/network/v2/network_auto_allocated_topology.py +6 -5
- openstackclient/network/v2/network_flavor.py +19 -6
- openstackclient/network/v2/network_flavor_profile.py +20 -6
- openstackclient/network/v2/network_meter.py +19 -6
- openstackclient/network/v2/network_meter_rule.py +20 -2
- openstackclient/network/v2/network_qos_policy.py +15 -7
- openstackclient/network/v2/network_qos_rule.py +16 -1
- openstackclient/network/v2/network_qos_rule_type.py +16 -5
- openstackclient/network/v2/network_rbac.py +12 -5
- openstackclient/network/v2/network_segment.py +13 -1
- openstackclient/network/v2/network_segment_range.py +15 -3
- openstackclient/network/v2/network_trunk.py +4 -1
- openstackclient/network/v2/port.py +88 -12
- openstackclient/network/v2/router.py +27 -16
- openstackclient/network/v2/security_group.py +18 -49
- openstackclient/network/v2/security_group_rule.py +18 -5
- openstackclient/network/v2/subnet.py +15 -7
- openstackclient/network/v2/subnet_pool.py +13 -8
- openstackclient/network/v2/taas/tap_flow.py +13 -3
- openstackclient/network/v2/taas/tap_mirror.py +7 -4
- openstackclient/network/v2/taas/tap_service.py +4 -1
- openstackclient/object/v1/container.py +3 -1
- openstackclient/object/v1/object.py +3 -1
- openstackclient/tests/functional/identity/v3/common.py +34 -0
- openstackclient/tests/functional/identity/v3/test_application_credential.py +1 -1
- openstackclient/tests/functional/identity/v3/test_mapping.py +81 -0
- openstackclient/tests/functional/volume/v3/test_volume_group.py +163 -0
- openstackclient/tests/unit/common/test_limits.py +1 -1
- openstackclient/tests/unit/common/test_module.py +77 -44
- openstackclient/tests/unit/common/test_quota.py +9 -0
- openstackclient/tests/unit/compute/v2/fakes.py +1 -57
- openstackclient/tests/unit/compute/v2/test_agent.py +4 -4
- openstackclient/tests/unit/compute/v2/test_aggregate.py +1 -1
- openstackclient/tests/unit/compute/v2/test_console.py +2 -2
- openstackclient/tests/unit/compute/v2/test_console_connection.py +1 -1
- openstackclient/tests/unit/compute/v2/test_flavor.py +1 -1
- openstackclient/tests/unit/compute/v2/test_host.py +3 -3
- openstackclient/tests/unit/compute/v2/test_hypervisor.py +2 -2
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -1
- openstackclient/tests/unit/compute/v2/test_keypair.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server.py +15 -15
- openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
- openstackclient/tests/unit/compute/v2/test_server_group.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_image.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
- openstackclient/tests/unit/compute/v2/test_server_share.py +4 -4
- openstackclient/tests/unit/compute/v2/test_server_volume.py +2 -2
- openstackclient/tests/unit/compute/v2/test_service.py +3 -3
- openstackclient/tests/unit/compute/v2/test_usage.py +1 -1
- openstackclient/tests/unit/identity/v2_0/fakes.py +3 -7
- openstackclient/tests/unit/identity/v2_0/test_endpoint.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_project.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_role.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_service.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_token.py +2 -2
- openstackclient/tests/unit/identity/v2_0/test_user.py +1 -1
- openstackclient/tests/unit/identity/v3/fakes.py +5 -38
- openstackclient/tests/unit/identity/v3/test_access_rule.py +3 -3
- openstackclient/tests/unit/identity/v3/test_application_credential.py +4 -4
- openstackclient/tests/unit/identity/v3/test_credential.py +5 -5
- openstackclient/tests/unit/identity/v3/test_domain.py +5 -5
- openstackclient/tests/unit/identity/v3/test_endpoint.py +6 -6
- openstackclient/tests/unit/identity/v3/test_endpoint_group.py +1 -1
- openstackclient/tests/unit/identity/v3/test_group.py +8 -8
- openstackclient/tests/unit/identity/v3/test_implied_role.py +1 -1
- openstackclient/tests/unit/identity/v3/test_limit.py +5 -5
- openstackclient/tests/unit/identity/v3/test_mappings.py +163 -79
- openstackclient/tests/unit/identity/v3/test_project.py +28 -5
- openstackclient/tests/unit/identity/v3/test_protocol.py +3 -3
- openstackclient/tests/unit/identity/v3/test_region.py +5 -5
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +5 -5
- openstackclient/tests/unit/identity/v3/test_role.py +8 -8
- openstackclient/tests/unit/identity/v3/test_role_assignment.py +1 -1
- openstackclient/tests/unit/identity/v3/test_service.py +5 -5
- openstackclient/tests/unit/identity/v3/test_token.py +2 -2
- openstackclient/tests/unit/identity/v3/test_trust.py +4 -4
- openstackclient/tests/unit/identity/v3/test_user.py +73 -6
- openstackclient/tests/unit/network/v2/fakes.py +5 -77
- openstackclient/tests/unit/network/v2/fwaas/test_group.py +28 -2
- openstackclient/tests/unit/network/v2/fwaas/test_rule.py +28 -3
- openstackclient/tests/unit/network/v2/test_address_group.py +24 -0
- openstackclient/tests/unit/network/v2/test_address_scope.py +24 -0
- openstackclient/tests/unit/network/v2/test_floating_ip.py +24 -0
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +24 -0
- openstackclient/tests/unit/network/v2/test_ip_availability.py +25 -0
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +29 -3
- openstackclient/tests/unit/network/v2/test_network.py +74 -12
- openstackclient/tests/unit/network/v2/test_network_agent.py +50 -1
- openstackclient/tests/unit/network/v2/test_network_flavor.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_meter.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_rbac.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_segment.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +24 -0
- openstackclient/tests/unit/network/v2/test_port.py +166 -0
- openstackclient/tests/unit/network/v2/test_router.py +28 -7
- openstackclient/tests/unit/network/v2/test_security_group.py +22 -0
- openstackclient/tests/unit/network/v2/test_security_group_rule.py +25 -0
- openstackclient/tests/unit/network/v2/test_subnet.py +28 -4
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +24 -0
- openstackclient/tests/unit/volume/v2/fakes.py +20 -140
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +5 -9
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +6 -0
- openstackclient/tests/unit/volume/v3/fakes.py +204 -100
- openstackclient/tests/unit/volume/v3/test_backup_record.py +114 -0
- openstackclient/tests/unit/volume/v3/test_consistency_group.py +720 -0
- openstackclient/tests/unit/volume/v3/test_consistency_group_snapshot.py +354 -0
- openstackclient/tests/unit/volume/v3/test_qos_specs.py +455 -0
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +2 -0
- openstackclient/tests/unit/volume/v3/test_volume_backend.py +158 -0
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +5 -9
- openstackclient/tests/unit/volume/v3/test_volume_group_type.py +65 -0
- openstackclient/tests/unit/volume/v3/test_volume_host.py +115 -0
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +6 -0
- openstackclient/volume/v2/volume.py +4 -2
- openstackclient/volume/v2/volume_backup.py +2 -3
- openstackclient/volume/v2/volume_snapshot.py +3 -4
- openstackclient/volume/v3/backup_record.py +94 -0
- openstackclient/volume/v3/consistency_group.py +400 -0
- openstackclient/volume/v3/consistency_group_snapshot.py +225 -0
- openstackclient/volume/v3/qos_specs.py +389 -0
- openstackclient/volume/v3/volume.py +4 -2
- openstackclient/volume/v3/volume_attachment.py +5 -1
- openstackclient/volume/v3/volume_backend.py +130 -0
- openstackclient/volume/v3/volume_backup.py +2 -3
- openstackclient/volume/v3/volume_group_snapshot.py +4 -6
- openstackclient/volume/v3/volume_group_type.py +1 -1
- openstackclient/volume/v3/volume_host.py +74 -0
- openstackclient/volume/v3/volume_message.py +3 -1
- openstackclient/volume/v3/volume_snapshot.py +2 -1
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/METADATA +3 -4
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/RECORD +202 -188
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/entry_points.txt +24 -24
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/AUTHORS +5 -0
- python_openstackclient-10.1.0.dist-info/pbr.json +1 -0
- python_openstackclient-10.0.0.dist-info/pbr.json +0 -1
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/LICENSE +0 -0
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/top_level.txt +0 -0
|
@@ -22,19 +22,22 @@ import itertools
|
|
|
22
22
|
import logging
|
|
23
23
|
from typing import Any
|
|
24
24
|
|
|
25
|
+
from openstack.network.v2 import network_segment_range as _segment_range
|
|
25
26
|
from osc_lib import exceptions
|
|
26
27
|
from osc_lib import utils
|
|
27
28
|
|
|
28
29
|
from openstackclient import command
|
|
30
|
+
from openstackclient.common import pagination
|
|
29
31
|
from openstackclient.i18n import _
|
|
30
32
|
from openstackclient.identity import common as identity_common
|
|
31
33
|
from openstackclient.network import common
|
|
32
34
|
|
|
33
|
-
|
|
34
35
|
LOG = logging.getLogger(__name__)
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
def _get_columns(
|
|
38
|
+
def _get_columns(
|
|
39
|
+
item: _segment_range.NetworkSegmentRange,
|
|
40
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
38
41
|
hidden_columns = ['location', 'tenant_id']
|
|
39
42
|
return utils.get_osc_show_columns_for_sdk_resource(
|
|
40
43
|
item, {}, hidden_columns
|
|
@@ -358,6 +361,7 @@ class ListNetworkSegmentRange(command.Lister):
|
|
|
358
361
|
'List only network segment ranges without available segments'
|
|
359
362
|
),
|
|
360
363
|
)
|
|
364
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
361
365
|
return parser
|
|
362
366
|
|
|
363
367
|
def take_action(
|
|
@@ -376,7 +380,15 @@ class ListNetworkSegmentRange(command.Lister):
|
|
|
376
380
|
) % {'e': e}
|
|
377
381
|
raise exceptions.CommandError(msg)
|
|
378
382
|
|
|
379
|
-
|
|
383
|
+
filters = {}
|
|
384
|
+
if parsed_args.marker is not None:
|
|
385
|
+
filters['marker'] = parsed_args.marker
|
|
386
|
+
if parsed_args.limit is not None:
|
|
387
|
+
filters['limit'] = parsed_args.limit
|
|
388
|
+
if parsed_args.max_items is not None:
|
|
389
|
+
filters['max_items'] = parsed_args.max_items
|
|
390
|
+
|
|
391
|
+
data = network_client.network_segment_ranges(**filters)
|
|
380
392
|
|
|
381
393
|
headers: tuple[str, ...] = (
|
|
382
394
|
'ID',
|
|
@@ -22,6 +22,7 @@ import logging
|
|
|
22
22
|
from typing import Any
|
|
23
23
|
|
|
24
24
|
from cliff import columns as cliff_columns
|
|
25
|
+
from openstack.network.v2 import trunk as _trunk
|
|
25
26
|
from osc_lib.cli import format_columns
|
|
26
27
|
from osc_lib.cli import identity as identity_utils
|
|
27
28
|
from osc_lib.cli import parseractions
|
|
@@ -367,7 +368,9 @@ _formatters = {
|
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
|
|
370
|
-
def _get_columns(
|
|
371
|
+
def _get_columns(
|
|
372
|
+
item: _trunk.Trunk,
|
|
373
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
371
374
|
hidden_columns = ['location', 'tenant_id']
|
|
372
375
|
return osc_utils.get_osc_show_columns_for_sdk_resource(
|
|
373
376
|
item, {}, hidden_columns
|
|
@@ -21,6 +21,7 @@ import logging
|
|
|
21
21
|
from typing import Any
|
|
22
22
|
|
|
23
23
|
from cliff import columns as cliff_columns
|
|
24
|
+
from openstack.network.v2 import port as _port
|
|
24
25
|
from osc_lib.cli import format_columns
|
|
25
26
|
from osc_lib.cli import parseractions
|
|
26
27
|
from osc_lib import exceptions
|
|
@@ -28,6 +29,7 @@ from osc_lib import utils
|
|
|
28
29
|
from osc_lib.utils import tags as _tag
|
|
29
30
|
|
|
30
31
|
from openstackclient import command
|
|
32
|
+
from openstackclient.common import pagination
|
|
31
33
|
from openstackclient.i18n import _
|
|
32
34
|
from openstackclient.identity import common as identity_common
|
|
33
35
|
from openstackclient.network import common
|
|
@@ -74,7 +76,9 @@ _list_formatters = copy.deepcopy(_formatters)
|
|
|
74
76
|
_list_formatters.update({'trunk_details': SubPortColumn})
|
|
75
77
|
|
|
76
78
|
|
|
77
|
-
def _get_columns(
|
|
79
|
+
def _get_columns(
|
|
80
|
+
item: _port.Port,
|
|
81
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
78
82
|
column_data_mapping = {
|
|
79
83
|
'admin_state_up': 'is_admin_state_up',
|
|
80
84
|
'allowed_address_pairs': 'allowed_address_pairs',
|
|
@@ -105,6 +109,8 @@ def _get_columns(item: Any) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
|
105
109
|
'port_security_enabled': 'is_port_security_enabled',
|
|
106
110
|
'project_id': 'project_id',
|
|
107
111
|
'propagate_uplink_status': 'propagate_uplink_status',
|
|
112
|
+
'pvlan_type': 'pvlan_type',
|
|
113
|
+
'pvlan_community': 'pvlan_community',
|
|
108
114
|
'resource_request': 'resource_request',
|
|
109
115
|
'revision_number': 'revision_number',
|
|
110
116
|
'qos_network_policy_id': 'qos_network_policy_id',
|
|
@@ -189,8 +195,6 @@ def _get_attrs(
|
|
|
189
195
|
if 'network' in parsed_args and parsed_args.network is not None:
|
|
190
196
|
attrs['network_id'] = parsed_args.network
|
|
191
197
|
if 'project' in parsed_args and parsed_args.project is not None:
|
|
192
|
-
# TODO(singhj): since 'project' logic is common among
|
|
193
|
-
# router, network, port etc., maybe move it to a common file.
|
|
194
198
|
identity_client = client_manager.identity
|
|
195
199
|
project_id = identity_common.find_project(
|
|
196
200
|
identity_client,
|
|
@@ -256,9 +260,48 @@ def _get_attrs(
|
|
|
256
260
|
if parsed_args.trusted:
|
|
257
261
|
attrs['trusted'] = True
|
|
258
262
|
|
|
263
|
+
if 'pvlan_type' in parsed_args and parsed_args.pvlan_type is not None:
|
|
264
|
+
attrs['pvlan_type'] = parsed_args.pvlan_type
|
|
265
|
+
if (
|
|
266
|
+
'pvlan_community' in parsed_args
|
|
267
|
+
and parsed_args.pvlan_community is not None
|
|
268
|
+
):
|
|
269
|
+
attrs['pvlan_community'] = parsed_args.pvlan_community
|
|
270
|
+
|
|
271
|
+
_validate_pvlan_port(attrs)
|
|
272
|
+
|
|
259
273
|
return attrs
|
|
260
274
|
|
|
261
275
|
|
|
276
|
+
def _validate_pvlan_port(attrs: dict[str, Any]) -> None:
|
|
277
|
+
if (attrs.get('pvlan_type') or attrs.get('pvlan_community')) and attrs.get(
|
|
278
|
+
'port_security_enabled'
|
|
279
|
+
) is False:
|
|
280
|
+
msg = _(
|
|
281
|
+
"PVLAN attributes cannot be set when port security is disabled."
|
|
282
|
+
)
|
|
283
|
+
raise exceptions.CommandError(msg)
|
|
284
|
+
|
|
285
|
+
if attrs.get('pvlan_type') == 'community' and not attrs.get(
|
|
286
|
+
'pvlan_community'
|
|
287
|
+
):
|
|
288
|
+
msg = _(
|
|
289
|
+
"--pvlan-community is required when --pvlan-type is 'community'."
|
|
290
|
+
)
|
|
291
|
+
raise exceptions.CommandError(msg)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _validate_pvlan_network_port(attrs: dict[str, Any], network: Any) -> None:
|
|
295
|
+
if not (attrs.get('pvlan_type') or attrs.get('pvlan_community')):
|
|
296
|
+
return
|
|
297
|
+
if not network.pvlan:
|
|
298
|
+
msg = _(
|
|
299
|
+
"PVLAN attributes cannot be set on a port whose "
|
|
300
|
+
"network does not have PVLAN enabled."
|
|
301
|
+
)
|
|
302
|
+
raise exceptions.CommandError(msg)
|
|
303
|
+
|
|
304
|
+
|
|
262
305
|
def _prepare_fixed_ips(
|
|
263
306
|
client_manager: Any, parsed_args: argparse.Namespace
|
|
264
307
|
) -> None:
|
|
@@ -445,10 +488,28 @@ def _add_updatable_args(
|
|
|
445
488
|
"which expect it in this dictionary (for example, Nova)."
|
|
446
489
|
),
|
|
447
490
|
)
|
|
491
|
+
parser.add_argument(
|
|
492
|
+
'--pvlan-type',
|
|
493
|
+
metavar='<type>',
|
|
494
|
+
choices=['promiscuous', 'isolated', 'community'],
|
|
495
|
+
dest='pvlan_type',
|
|
496
|
+
help=_(
|
|
497
|
+
"Set Private VLAN type for this port. Requires PVLAN service "
|
|
498
|
+
"plugin. Default: promiscuous."
|
|
499
|
+
),
|
|
500
|
+
)
|
|
501
|
+
parser.add_argument(
|
|
502
|
+
'--pvlan-community',
|
|
503
|
+
metavar='<community>',
|
|
504
|
+
dest='pvlan_community',
|
|
505
|
+
help=_(
|
|
506
|
+
"Set PVLAN community name for this port. "
|
|
507
|
+
"Only applies when pvlan-type is 'community'. "
|
|
508
|
+
"Requires PVLAN service plugin. Default: None."
|
|
509
|
+
),
|
|
510
|
+
)
|
|
448
511
|
|
|
449
512
|
|
|
450
|
-
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
|
451
|
-
# OSC minimum requirements include SDK 1.0.
|
|
452
513
|
def _convert_address_pairs(
|
|
453
514
|
parsed_args: argparse.Namespace,
|
|
454
515
|
) -> list[dict[str, Any]]:
|
|
@@ -732,6 +793,8 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
|
732
793
|
self._parse_extra_properties(parsed_args.extra_properties)
|
|
733
794
|
)
|
|
734
795
|
|
|
796
|
+
_validate_pvlan_network_port(attrs, network)
|
|
797
|
+
|
|
735
798
|
with common.check_missing_extension_if_error(network_client, attrs):
|
|
736
799
|
obj = network_client.create_port(**attrs)
|
|
737
800
|
|
|
@@ -785,8 +848,6 @@ class DeletePort(command.Command):
|
|
|
785
848
|
raise exceptions.CommandError(msg)
|
|
786
849
|
|
|
787
850
|
|
|
788
|
-
# TODO(abhiraut): Use only the SDK resource mapped attribute names once the
|
|
789
|
-
# OSC minimum requirements include SDK 1.0.
|
|
790
851
|
class ListPort(command.Lister):
|
|
791
852
|
_description = _("List ports")
|
|
792
853
|
|
|
@@ -886,6 +947,7 @@ class ListPort(command.Lister):
|
|
|
886
947
|
),
|
|
887
948
|
)
|
|
888
949
|
_tag.add_tag_filtering_option_to_parser(parser, _('ports'))
|
|
950
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
889
951
|
return parser
|
|
890
952
|
|
|
891
953
|
def take_action(
|
|
@@ -917,7 +979,6 @@ class ListPort(command.Lister):
|
|
|
917
979
|
column_headers.extend(
|
|
918
980
|
['Security Groups', 'Device Owner', 'Tags', 'Trunk subports']
|
|
919
981
|
)
|
|
920
|
-
|
|
921
982
|
if parsed_args.device_owner is not None:
|
|
922
983
|
filters['device_owner'] = parsed_args.device_owner
|
|
923
984
|
if parsed_args.device_id is not None:
|
|
@@ -960,6 +1021,12 @@ class ListPort(command.Lister):
|
|
|
960
1021
|
)
|
|
961
1022
|
if parsed_args.security_groups:
|
|
962
1023
|
filters['security_group_ids'] = parsed_args.security_groups
|
|
1024
|
+
if parsed_args.marker is not None:
|
|
1025
|
+
filters['marker'] = parsed_args.marker
|
|
1026
|
+
if parsed_args.limit is not None:
|
|
1027
|
+
filters['limit'] = parsed_args.limit
|
|
1028
|
+
if parsed_args.max_items is not None:
|
|
1029
|
+
filters['max_items'] = parsed_args.max_items
|
|
963
1030
|
|
|
964
1031
|
_tag.get_tag_filtering_args(parsed_args, filters)
|
|
965
1032
|
|
|
@@ -984,8 +1051,6 @@ class ListPort(command.Lister):
|
|
|
984
1051
|
)
|
|
985
1052
|
|
|
986
1053
|
|
|
987
|
-
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
|
988
|
-
# OSC minimum requirements include SDK 1.0.
|
|
989
1054
|
class SetPort(common.NeutronCommandWithExtraArgs):
|
|
990
1055
|
_description = _("Set port properties")
|
|
991
1056
|
|
|
@@ -1232,6 +1297,10 @@ class SetPort(common.NeutronCommandWithExtraArgs):
|
|
|
1232
1297
|
self._parse_extra_properties(parsed_args.extra_properties)
|
|
1233
1298
|
)
|
|
1234
1299
|
|
|
1300
|
+
if attrs.get('pvlan_type') or attrs.get('pvlan_community'):
|
|
1301
|
+
network = client.find_network(obj.network_id, ignore_missing=False)
|
|
1302
|
+
_validate_pvlan_network_port(attrs, network)
|
|
1303
|
+
|
|
1235
1304
|
if attrs:
|
|
1236
1305
|
with common.check_missing_extension_if_error(
|
|
1237
1306
|
self.app.client_manager.network, attrs
|
|
@@ -1262,8 +1331,6 @@ class ShowPort(command.ShowOne):
|
|
|
1262
1331
|
return (display_columns, data)
|
|
1263
1332
|
|
|
1264
1333
|
|
|
1265
|
-
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
|
1266
|
-
# OSC minimum requirements include SDK 1.0.
|
|
1267
1334
|
class UnsetPort(common.NeutronUnsetCommandWithExtraArgs):
|
|
1268
1335
|
_description = _("Unset port properties")
|
|
1269
1336
|
|
|
@@ -1355,6 +1422,13 @@ class UnsetPort(common.NeutronUnsetCommandWithExtraArgs):
|
|
|
1355
1422
|
default=False,
|
|
1356
1423
|
help=_("Clear device owner for the port."),
|
|
1357
1424
|
)
|
|
1425
|
+
parser.add_argument(
|
|
1426
|
+
'--pvlan-community',
|
|
1427
|
+
action='store_true',
|
|
1428
|
+
default=False,
|
|
1429
|
+
dest='pvlan_community',
|
|
1430
|
+
help=_("Clear PVLAN community name for the port."),
|
|
1431
|
+
)
|
|
1358
1432
|
_tag.add_tag_option_to_parser_for_unset(parser, _('port'))
|
|
1359
1433
|
parser.add_argument(
|
|
1360
1434
|
'port',
|
|
@@ -1425,6 +1499,8 @@ class UnsetPort(common.NeutronUnsetCommandWithExtraArgs):
|
|
|
1425
1499
|
attrs['device_id'] = ''
|
|
1426
1500
|
if parsed_args.device_owner:
|
|
1427
1501
|
attrs['device_owner'] = ''
|
|
1502
|
+
if parsed_args.pvlan_community:
|
|
1503
|
+
attrs['pvlan_community'] = None
|
|
1428
1504
|
|
|
1429
1505
|
attrs.update(
|
|
1430
1506
|
self._parse_extra_properties(parsed_args.extra_properties)
|
|
@@ -22,6 +22,7 @@ import logging
|
|
|
22
22
|
from typing import Any
|
|
23
23
|
|
|
24
24
|
from cliff import columns as cliff_columns
|
|
25
|
+
from openstack.network.v2 import router as _router
|
|
25
26
|
from osc_lib.cli import format_columns
|
|
26
27
|
from osc_lib.cli import parseractions
|
|
27
28
|
from osc_lib import exceptions
|
|
@@ -29,6 +30,7 @@ from osc_lib import utils
|
|
|
29
30
|
from osc_lib.utils import tags as _tag
|
|
30
31
|
|
|
31
32
|
from openstackclient import command
|
|
33
|
+
from openstackclient.common import pagination
|
|
32
34
|
from openstackclient.i18n import _
|
|
33
35
|
from openstackclient.identity import common as identity_common
|
|
34
36
|
from openstackclient.network import common
|
|
@@ -69,7 +71,9 @@ _formatters = {
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
def _get_columns(
|
|
74
|
+
def _get_columns(
|
|
75
|
+
item: _router.Router,
|
|
76
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
73
77
|
column_map = {
|
|
74
78
|
'is_ha': 'ha',
|
|
75
79
|
'is_distributed': 'distributed',
|
|
@@ -84,6 +88,8 @@ def _get_columns(item: Any) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
|
84
88
|
if item.is_distributed is None:
|
|
85
89
|
hidden_columns.append('is_distributed')
|
|
86
90
|
column_map.pop('is_distributed')
|
|
91
|
+
if not hasattr(item, 'evpn_vni'):
|
|
92
|
+
hidden_columns.append('evpn_vni')
|
|
87
93
|
return utils.get_osc_show_columns_for_sdk_resource(
|
|
88
94
|
item, column_map, hidden_columns
|
|
89
95
|
)
|
|
@@ -344,7 +350,7 @@ class AddPortToRouter(command.Command):
|
|
|
344
350
|
port = client.find_port(parsed_args.port, ignore_missing=False)
|
|
345
351
|
client.add_interface_to_router(
|
|
346
352
|
client.find_router(parsed_args.router, ignore_missing=False),
|
|
347
|
-
|
|
353
|
+
port=port.id,
|
|
348
354
|
)
|
|
349
355
|
|
|
350
356
|
|
|
@@ -370,7 +376,7 @@ class AddSubnetToRouter(command.Command):
|
|
|
370
376
|
subnet = client.find_subnet(parsed_args.subnet, ignore_missing=False)
|
|
371
377
|
client.add_interface_to_router(
|
|
372
378
|
client.find_router(parsed_args.router, ignore_missing=False),
|
|
373
|
-
|
|
379
|
+
subnet=subnet.id,
|
|
374
380
|
)
|
|
375
381
|
|
|
376
382
|
|
|
@@ -478,8 +484,6 @@ class RemoveExtraRoutesFromRouter(command.ShowOne):
|
|
|
478
484
|
return (display_columns, data)
|
|
479
485
|
|
|
480
486
|
|
|
481
|
-
# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
|
|
482
|
-
# OSC minimum requirements include SDK 1.0.
|
|
483
487
|
class CreateRouter(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
484
488
|
_description = _("Create a new router")
|
|
485
489
|
|
|
@@ -713,8 +717,6 @@ class DeleteRouter(command.Command):
|
|
|
713
717
|
raise exceptions.CommandError(msg)
|
|
714
718
|
|
|
715
719
|
|
|
716
|
-
# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
|
|
717
|
-
# OSC minimum requirements include SDK 1.0.
|
|
718
720
|
class ListRouter(command.Lister):
|
|
719
721
|
_description = _("List routers")
|
|
720
722
|
|
|
@@ -754,6 +756,7 @@ class ListRouter(command.Lister):
|
|
|
754
756
|
),
|
|
755
757
|
)
|
|
756
758
|
_tag.add_tag_filtering_option_to_parser(parser, _('routers'))
|
|
759
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
757
760
|
|
|
758
761
|
return parser
|
|
759
762
|
|
|
@@ -798,16 +801,26 @@ class ListRouter(command.Lister):
|
|
|
798
801
|
).id
|
|
799
802
|
args['project_id'] = project_id
|
|
800
803
|
|
|
804
|
+
if parsed_args.marker is not None:
|
|
805
|
+
args['marker'] = parsed_args.marker
|
|
806
|
+
if parsed_args.limit is not None:
|
|
807
|
+
args['limit'] = parsed_args.limit
|
|
808
|
+
if parsed_args.max_items is not None:
|
|
809
|
+
args['max_items'] = parsed_args.max_items
|
|
810
|
+
|
|
801
811
|
_tag.get_tag_filtering_args(parsed_args, args)
|
|
802
812
|
|
|
803
|
-
if parsed_args.agent is
|
|
813
|
+
if parsed_args.agent is None:
|
|
814
|
+
data = list(client.routers(**args))
|
|
815
|
+
else:
|
|
804
816
|
agent = client.get_agent(parsed_args.agent)
|
|
805
|
-
data = client.agent_hosted_routers(agent)
|
|
806
817
|
# NOTE: Networking API does not support filtering by parameters,
|
|
807
818
|
# so we need filtering in the client side.
|
|
808
|
-
data = [
|
|
809
|
-
|
|
810
|
-
|
|
819
|
+
data = [
|
|
820
|
+
d
|
|
821
|
+
for d in client.agent_hosted_routers(agent)
|
|
822
|
+
if self._filter_match(d, args)
|
|
823
|
+
]
|
|
811
824
|
|
|
812
825
|
# check if "HA" and "Distributed" columns should be displayed also
|
|
813
826
|
data = list(data)
|
|
@@ -887,7 +900,7 @@ class RemovePortFromRouter(command.Command):
|
|
|
887
900
|
port = client.find_port(parsed_args.port, ignore_missing=False)
|
|
888
901
|
client.remove_interface_from_router(
|
|
889
902
|
client.find_router(parsed_args.router, ignore_missing=False),
|
|
890
|
-
|
|
903
|
+
port=port.id,
|
|
891
904
|
)
|
|
892
905
|
|
|
893
906
|
|
|
@@ -915,12 +928,10 @@ class RemoveSubnetFromRouter(command.Command):
|
|
|
915
928
|
subnet = client.find_subnet(parsed_args.subnet, ignore_missing=False)
|
|
916
929
|
client.remove_interface_from_router(
|
|
917
930
|
client.find_router(parsed_args.router, ignore_missing=False),
|
|
918
|
-
|
|
931
|
+
subnet=subnet.id,
|
|
919
932
|
)
|
|
920
933
|
|
|
921
934
|
|
|
922
|
-
# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
|
|
923
|
-
# OSC minimum requirements include SDK 1.0.
|
|
924
935
|
class SetRouter(common.NeutronCommandWithExtraArgs):
|
|
925
936
|
_description = _("Set router properties")
|
|
926
937
|
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
10
10
|
# License for the specific language governing permissions and limitations
|
|
11
11
|
# under the License.
|
|
12
|
-
#
|
|
13
12
|
|
|
14
13
|
"""Security Group action implementations"""
|
|
15
14
|
|
|
@@ -19,15 +18,16 @@ import logging
|
|
|
19
18
|
from typing import Any, cast
|
|
20
19
|
|
|
21
20
|
from cliff import columns as cliff_columns
|
|
21
|
+
from openstack.network.v2 import security_group as _security_group
|
|
22
22
|
from osc_lib import exceptions
|
|
23
23
|
from osc_lib import utils
|
|
24
24
|
from osc_lib.utils import tags as _tag
|
|
25
25
|
|
|
26
26
|
from openstackclient import command
|
|
27
|
+
from openstackclient.common import pagination
|
|
27
28
|
from openstackclient.i18n import _
|
|
28
29
|
from openstackclient.identity import common as identity_common
|
|
29
30
|
from openstackclient.network import common
|
|
30
|
-
from openstackclient.network import utils as network_utils
|
|
31
31
|
|
|
32
32
|
LOG = logging.getLogger(__name__)
|
|
33
33
|
|
|
@@ -35,9 +35,8 @@ LOG = logging.getLogger(__name__)
|
|
|
35
35
|
def _format_network_security_group_rules(
|
|
36
36
|
sg_rules: list[dict[str, Any]],
|
|
37
37
|
) -> str:
|
|
38
|
-
# For readability
|
|
39
|
-
#
|
|
40
|
-
# or empty values.
|
|
38
|
+
# For readability, trim keys with caller known (e.g. security group and
|
|
39
|
+
# tenant ID) or empty values.
|
|
41
40
|
for sg_rule in sg_rules:
|
|
42
41
|
empty_keys = [k for k, v in sg_rule.items() if not v]
|
|
43
42
|
for key in empty_keys:
|
|
@@ -48,53 +47,19 @@ def _format_network_security_group_rules(
|
|
|
48
47
|
return utils.format_list_of_dicts(sg_rules) or ""
|
|
49
48
|
|
|
50
49
|
|
|
51
|
-
def _format_compute_security_group_rule(sg_rule: dict[str, Any]) -> str:
|
|
52
|
-
info = network_utils.transform_compute_security_group_rule(sg_rule)
|
|
53
|
-
# Trim parent security group ID since caller has this information.
|
|
54
|
-
info.pop('parent_group_id', None)
|
|
55
|
-
# Trim keys with empty string values.
|
|
56
|
-
keys_to_trim = [
|
|
57
|
-
'ip_protocol',
|
|
58
|
-
'ip_range',
|
|
59
|
-
'port_range',
|
|
60
|
-
'remote_security_group',
|
|
61
|
-
]
|
|
62
|
-
for key in keys_to_trim:
|
|
63
|
-
if key in info and not info[key]:
|
|
64
|
-
info.pop(key)
|
|
65
|
-
return utils.format_dict(info)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def _format_compute_security_group_rules(
|
|
69
|
-
sg_rules: list[dict[str, Any]],
|
|
70
|
-
) -> str:
|
|
71
|
-
rules = []
|
|
72
|
-
for sg_rule in sg_rules:
|
|
73
|
-
rules.append(_format_compute_security_group_rule(sg_rule))
|
|
74
|
-
return utils.format_list(rules, separator='\n') or ""
|
|
75
|
-
|
|
76
|
-
|
|
77
50
|
class NetworkSecurityGroupRulesColumn(cliff_columns.FormattableColumn[Any]):
|
|
78
51
|
def human_readable(self) -> str:
|
|
79
52
|
return _format_network_security_group_rules(self._value)
|
|
80
53
|
|
|
81
54
|
|
|
82
|
-
|
|
83
|
-
def human_readable(self) -> str:
|
|
84
|
-
return _format_compute_security_group_rules(self._value)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
_formatters_network = {
|
|
55
|
+
_formatters = {
|
|
88
56
|
'security_group_rules': NetworkSecurityGroupRulesColumn,
|
|
89
57
|
}
|
|
90
58
|
|
|
91
59
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def _get_columns(item: Any) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
60
|
+
def _get_columns(
|
|
61
|
+
item: _security_group.SecurityGroup,
|
|
62
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
98
63
|
# We still support Nova managed security groups, where we have tenant_id.
|
|
99
64
|
column_map = {
|
|
100
65
|
'security_group_rules': 'rules',
|
|
@@ -105,8 +70,6 @@ def _get_columns(item: Any) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
|
105
70
|
)
|
|
106
71
|
|
|
107
72
|
|
|
108
|
-
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
|
109
|
-
# OSC minimum requirements include SDK 1.0.
|
|
110
73
|
class CreateSecurityGroup(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
111
74
|
_description = _("Create a new security group")
|
|
112
75
|
|
|
@@ -178,7 +141,7 @@ class CreateSecurityGroup(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
|
178
141
|
_tag.update_tags_for_set(client, obj, parsed_args)
|
|
179
142
|
display_columns, property_columns = _get_columns(obj)
|
|
180
143
|
data = utils.get_item_properties(
|
|
181
|
-
obj, property_columns, formatters=
|
|
144
|
+
obj, property_columns, formatters=_formatters
|
|
182
145
|
)
|
|
183
146
|
return (display_columns, data)
|
|
184
147
|
|
|
@@ -223,8 +186,6 @@ class DeleteSecurityGroup(command.Command):
|
|
|
223
186
|
raise exceptions.CommandError(msg)
|
|
224
187
|
|
|
225
188
|
|
|
226
|
-
# TODO(rauta): Use the SDK resource mapped attribute names once
|
|
227
|
-
# the OSC minimum requirements include SDK 1.0.
|
|
228
189
|
class ListSecurityGroup(command.Lister):
|
|
229
190
|
_description = _("List security groups")
|
|
230
191
|
FIELDS_TO_RETRIEVE = [
|
|
@@ -265,6 +226,7 @@ class ListSecurityGroup(command.Lister):
|
|
|
265
226
|
)
|
|
266
227
|
|
|
267
228
|
_tag.add_tag_filtering_option_to_parser(parser, _('security group'))
|
|
229
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
268
230
|
return parser
|
|
269
231
|
|
|
270
232
|
def take_action(
|
|
@@ -272,6 +234,7 @@ class ListSecurityGroup(command.Lister):
|
|
|
272
234
|
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
273
235
|
client = self.app.client_manager.network
|
|
274
236
|
filters = {}
|
|
237
|
+
|
|
275
238
|
if parsed_args.project:
|
|
276
239
|
identity_client = self.app.client_manager.identity
|
|
277
240
|
project_id = identity_common.find_project(
|
|
@@ -283,6 +246,12 @@ class ListSecurityGroup(command.Lister):
|
|
|
283
246
|
|
|
284
247
|
if parsed_args.shared is not None:
|
|
285
248
|
filters['shared'] = parsed_args.shared
|
|
249
|
+
if parsed_args.marker is not None:
|
|
250
|
+
filters['marker'] = parsed_args.marker
|
|
251
|
+
if parsed_args.limit is not None:
|
|
252
|
+
filters['limit'] = parsed_args.limit
|
|
253
|
+
if parsed_args.max_items is not None:
|
|
254
|
+
filters['max_items'] = parsed_args.max_items
|
|
286
255
|
|
|
287
256
|
_tag.get_tag_filtering_args(parsed_args, filters)
|
|
288
257
|
data = client.security_groups(
|
|
@@ -398,7 +367,7 @@ class ShowSecurityGroup(command.ShowOne):
|
|
|
398
367
|
)
|
|
399
368
|
display_columns, property_columns = _get_columns(obj)
|
|
400
369
|
data = utils.get_item_properties(
|
|
401
|
-
obj, property_columns, formatters=
|
|
370
|
+
obj, property_columns, formatters=_formatters
|
|
402
371
|
)
|
|
403
372
|
return (display_columns, data)
|
|
404
373
|
|
|
@@ -18,11 +18,13 @@ from collections.abc import Iterable, Sequence
|
|
|
18
18
|
import logging
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
|
+
from openstack.network.v2 import security_group_rule as _security_group_rule
|
|
21
22
|
from osc_lib.cli import parseractions
|
|
22
23
|
from osc_lib import exceptions
|
|
23
24
|
from osc_lib import utils
|
|
24
25
|
|
|
25
26
|
from openstackclient import command
|
|
27
|
+
from openstackclient.common import pagination
|
|
26
28
|
from openstackclient.i18n import _
|
|
27
29
|
from openstackclient.identity import common as identity_common
|
|
28
30
|
from openstackclient.network import common
|
|
@@ -31,15 +33,15 @@ from openstackclient.network import utils as network_utils
|
|
|
31
33
|
LOG = logging.getLogger(__name__)
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
def _get_columns(
|
|
36
|
+
def _get_columns(
|
|
37
|
+
item: _security_group_rule.SecurityGroupRule,
|
|
38
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
35
39
|
hidden_columns = ['location', 'name', 'tenant_id', 'tags']
|
|
36
40
|
return utils.get_osc_show_columns_for_sdk_resource(
|
|
37
41
|
item, {}, hidden_columns
|
|
38
42
|
)
|
|
39
43
|
|
|
40
44
|
|
|
41
|
-
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
|
42
|
-
# OSC minimum requirements include SDK 1.0.
|
|
43
45
|
class CreateSecurityGroupRule(
|
|
44
46
|
command.ShowOne, common.NeutronCommandWithExtraArgs
|
|
45
47
|
):
|
|
@@ -281,13 +283,16 @@ class DeleteSecurityGroupRule(command.Command):
|
|
|
281
283
|
class ListSecurityGroupRule(command.Lister):
|
|
282
284
|
_description = _("List security group rules")
|
|
283
285
|
|
|
284
|
-
|
|
286
|
+
@staticmethod
|
|
287
|
+
def _format_network_security_group_rule(
|
|
288
|
+
rule: _security_group_rule.SecurityGroupRule,
|
|
289
|
+
) -> dict[str, object]:
|
|
285
290
|
"""Transform the SDK SecurityGroupRule object to a dict
|
|
286
291
|
|
|
287
292
|
The SDK object gets in the way of reformatting columns...
|
|
288
293
|
Create port_range column from port_range_min and port_range_max
|
|
289
294
|
"""
|
|
290
|
-
data
|
|
295
|
+
data = rule.to_dict()
|
|
291
296
|
data['port_range'] = network_utils.format_network_port_range(data)
|
|
292
297
|
data['remote_ip_prefix'] = network_utils.format_remote_ip_prefix(data)
|
|
293
298
|
return data
|
|
@@ -344,6 +349,7 @@ class ListSecurityGroupRule(command.Lister):
|
|
|
344
349
|
help=_("List only rules with the specified project (name or ID)"),
|
|
345
350
|
)
|
|
346
351
|
identity_common.add_project_domain_option_to_parser(parser)
|
|
352
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
347
353
|
return parser
|
|
348
354
|
|
|
349
355
|
def _get_column_headers(
|
|
@@ -413,6 +419,13 @@ class ListSecurityGroupRule(command.Lister):
|
|
|
413
419
|
).id
|
|
414
420
|
query['project_id'] = project_id
|
|
415
421
|
|
|
422
|
+
if parsed_args.marker is not None:
|
|
423
|
+
query['marker'] = parsed_args.marker
|
|
424
|
+
if parsed_args.limit is not None:
|
|
425
|
+
query['limit'] = parsed_args.limit
|
|
426
|
+
if parsed_args.max_items is not None:
|
|
427
|
+
query['max_items'] = parsed_args.max_items
|
|
428
|
+
|
|
416
429
|
rules = [
|
|
417
430
|
self._format_network_security_group_rule(r)
|
|
418
431
|
for r in client.security_group_rules(**query)
|