python-openstackclient 8.3.0__py3-none-any.whl → 10.0.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/__init__.py +2 -6
- openstackclient/api/api.py +41 -23
- openstackclient/api/compute_v2.py +44 -25
- openstackclient/api/object_store_v1.py +75 -97
- openstackclient/api/volume_v2.py +2 -1
- openstackclient/api/volume_v3.py +2 -1
- openstackclient/common/availability_zone.py +58 -42
- openstackclient/common/clientmanager.py +56 -29
- openstackclient/common/configuration.py +10 -3
- openstackclient/common/envvars.py +2 -2
- openstackclient/common/extension.py +14 -5
- openstackclient/common/limits.py +10 -5
- openstackclient/common/module.py +14 -6
- openstackclient/common/pagination.py +8 -2
- openstackclient/common/progressbar.py +7 -6
- openstackclient/common/project_cleanup.py +13 -7
- openstackclient/common/quota.py +126 -114
- openstackclient/common/versions.py +8 -2
- openstackclient/compute/client.py +7 -3
- openstackclient/compute/v2/agent.py +17 -10
- openstackclient/compute/v2/aggregate.py +36 -22
- openstackclient/compute/v2/console.py +14 -8
- openstackclient/compute/v2/console_connection.py +11 -3
- openstackclient/compute/v2/flavor.py +39 -21
- openstackclient/compute/v2/host.py +14 -6
- openstackclient/compute/v2/hypervisor.py +14 -5
- openstackclient/compute/v2/hypervisor_stats.py +10 -2
- openstackclient/compute/v2/keypair.py +29 -14
- openstackclient/compute/v2/server.py +251 -171
- openstackclient/compute/v2/server_backup.py +10 -4
- openstackclient/compute/v2/server_event.py +21 -12
- openstackclient/compute/v2/server_group.py +21 -11
- openstackclient/compute/v2/server_image.py +19 -10
- openstackclient/compute/v2/server_migration.py +24 -10
- openstackclient/compute/v2/server_share.py +274 -0
- openstackclient/compute/v2/server_volume.py +10 -4
- openstackclient/compute/v2/service.py +14 -7
- openstackclient/compute/v2/usage.py +26 -21
- openstackclient/identity/client.py +8 -3
- openstackclient/identity/common.py +103 -41
- openstackclient/identity/v2_0/catalog.py +14 -7
- openstackclient/identity/v2_0/ec2creds.py +21 -10
- openstackclient/identity/v2_0/endpoint.py +23 -11
- openstackclient/identity/v2_0/project.py +25 -14
- openstackclient/identity/v2_0/role.py +28 -14
- openstackclient/identity/v2_0/role_assignment.py +9 -3
- openstackclient/identity/v2_0/service.py +26 -12
- openstackclient/identity/v2_0/token.py +12 -5
- openstackclient/identity/v2_0/user.py +26 -15
- openstackclient/identity/v3/access_rule.py +26 -12
- openstackclient/identity/v3/application_credential.py +59 -24
- openstackclient/identity/v3/catalog.py +14 -7
- openstackclient/identity/v3/consumer.py +22 -11
- openstackclient/identity/v3/credential.py +36 -16
- openstackclient/identity/v3/domain.py +37 -18
- openstackclient/identity/v3/ec2creds.py +25 -12
- openstackclient/identity/v3/endpoint.py +42 -20
- openstackclient/identity/v3/endpoint_group.py +28 -17
- openstackclient/identity/v3/federation_protocol.py +71 -50
- openstackclient/identity/v3/group.py +55 -32
- openstackclient/identity/v3/identity_provider.py +92 -57
- openstackclient/identity/v3/implied_role.py +21 -9
- openstackclient/identity/v3/limit.py +115 -92
- openstackclient/identity/v3/mapping.py +26 -13
- openstackclient/identity/v3/policy.py +23 -12
- openstackclient/identity/v3/project.py +211 -122
- openstackclient/identity/v3/region.py +36 -16
- openstackclient/identity/v3/registered_limit.py +116 -109
- openstackclient/identity/v3/role.py +61 -31
- openstackclient/identity/v3/role_assignment.py +23 -6
- openstackclient/identity/v3/service.py +36 -16
- openstackclient/identity/v3/service_provider.py +37 -15
- openstackclient/identity/v3/tag.py +23 -17
- openstackclient/identity/v3/token.py +30 -14
- openstackclient/identity/v3/trust.py +32 -14
- openstackclient/identity/v3/unscoped_saml.py +10 -2
- openstackclient/identity/v3/user.py +49 -26
- openstackclient/image/client.py +7 -3
- openstackclient/image/v1/image.py +33 -26
- openstackclient/image/v2/cache.py +14 -9
- openstackclient/image/v2/image.py +76 -49
- openstackclient/image/v2/info.py +7 -1
- openstackclient/image/v2/metadef_namespaces.py +109 -13
- openstackclient/image/v2/metadef_objects.py +28 -15
- openstackclient/image/v2/metadef_properties.py +24 -13
- openstackclient/image/v2/metadef_resource_type_association.py +14 -7
- openstackclient/image/v2/metadef_resource_types.py +7 -1
- openstackclient/image/v2/task.py +15 -6
- openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +7 -192
- openstackclient/network/client.py +7 -2
- openstackclient/network/common.py +16 -241
- openstackclient/network/utils.py +36 -22
- openstackclient/network/v2/address_group.py +27 -16
- openstackclient/network/v2/address_scope.py +24 -13
- openstackclient/network/v2/bgpvpn/bgpvpn.py +463 -0
- openstackclient/network/v2/bgpvpn/constants.py +30 -0
- openstackclient/network/v2/bgpvpn/network_association.py +214 -0
- openstackclient/network/v2/bgpvpn/port_association.py +490 -0
- openstackclient/network/v2/bgpvpn/router_association.py +288 -0
- openstackclient/network/v2/default_security_group_rule.py +19 -10
- openstackclient/network/v2/floating_ip.py +110 -159
- openstackclient/network/v2/floating_ip_port_forwarding.py +30 -18
- openstackclient/network/v2/fwaas/__init__.py +0 -0
- openstackclient/network/v2/fwaas/group.py +466 -0
- openstackclient/network/v2/fwaas/policy.py +518 -0
- openstackclient/network/v2/fwaas/rule.py +574 -0
- openstackclient/network/v2/ip_availability.py +13 -5
- openstackclient/network/v2/l3_conntrack_helper.py +22 -13
- openstackclient/network/v2/local_ip.py +24 -13
- openstackclient/network/v2/local_ip_association.py +14 -7
- openstackclient/network/v2/ndp_proxy.py +20 -11
- openstackclient/network/v2/network.py +129 -196
- openstackclient/network/v2/network_agent.py +46 -25
- openstackclient/network/v2/network_auto_allocated_topology.py +22 -11
- openstackclient/network/v2/network_flavor.py +27 -16
- openstackclient/network/v2/network_flavor_profile.py +23 -12
- openstackclient/network/v2/network_meter.py +21 -10
- openstackclient/network/v2/network_meter_rule.py +21 -11
- openstackclient/network/v2/network_qos_policy.py +25 -15
- openstackclient/network/v2/network_qos_rule.py +32 -17
- openstackclient/network/v2/network_qos_rule_type.py +13 -5
- openstackclient/network/v2/network_rbac.py +23 -12
- openstackclient/network/v2/network_segment.py +20 -11
- openstackclient/network/v2/network_segment_range.py +56 -29
- openstackclient/network/v2/network_service_provider.py +7 -1
- openstackclient/network/v2/network_trunk.py +38 -22
- openstackclient/network/v2/port.py +54 -29
- openstackclient/network/v2/router.py +75 -52
- openstackclient/network/v2/security_group.py +87 -157
- openstackclient/network/v2/security_group_rule.py +100 -280
- openstackclient/network/v2/subnet.py +49 -28
- openstackclient/network/v2/subnet_pool.py +30 -17
- openstackclient/network/v2/taas/tap_flow.py +22 -11
- openstackclient/network/v2/taas/tap_mirror.py +22 -11
- openstackclient/network/v2/taas/tap_service.py +23 -12
- openstackclient/object/client.py +7 -2
- openstackclient/object/v1/account.py +13 -6
- openstackclient/object/v1/container.py +25 -15
- openstackclient/object/v1/object.py +25 -15
- openstackclient/py.typed +0 -0
- openstackclient/shell.py +46 -10
- openstackclient/tests/functional/base.py +55 -20
- openstackclient/tests/functional/common/test_extension.py +4 -0
- openstackclient/tests/functional/common/test_quota.py +3 -1
- openstackclient/tests/functional/compute/v2/common.py +14 -13
- openstackclient/tests/functional/compute/v2/test_flavor.py +3 -1
- openstackclient/tests/functional/compute/v2/test_server.py +3 -0
- openstackclient/tests/functional/identity/v2/common.py +10 -6
- openstackclient/tests/functional/identity/v2/test_role.py +4 -4
- openstackclient/tests/functional/identity/v3/common.py +25 -19
- openstackclient/tests/functional/identity/v3/test_group.py +20 -20
- openstackclient/tests/functional/identity/v3/test_idp.py +3 -1
- openstackclient/tests/functional/identity/v3/test_limit.py +47 -0
- openstackclient/tests/functional/identity/v3/test_project.py +10 -10
- openstackclient/tests/functional/identity/v3/test_role.py +18 -18
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +12 -12
- openstackclient/tests/functional/identity/v3/test_user.py +8 -8
- openstackclient/tests/functional/image/base.py +1 -6
- openstackclient/tests/functional/image/v2/test_metadef_objects.py +69 -0
- openstackclient/tests/functional/network/v2/common.py +5 -2
- openstackclient/tests/functional/network/v2/test_floating_ip.py +10 -4
- openstackclient/tests/functional/network/v2/test_ip_availability.py +4 -0
- openstackclient/tests/functional/network/v2/test_network_meter_rule.py +3 -2
- openstackclient/tests/functional/network/v2/test_network_segment.py +5 -0
- openstackclient/tests/functional/network/v2/test_subnet.py +13 -9
- openstackclient/tests/functional/object/v1/common.py +4 -0
- openstackclient/tests/functional/volume/v2/common.py +4 -0
- openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +27 -11
- openstackclient/tests/functional/volume/v2/test_volume_type.py +2 -2
- openstackclient/tests/functional/volume/v3/common.py +4 -0
- openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +56 -138
- openstackclient/tests/functional/volume/v3/test_volume_type.py +2 -2
- openstackclient/tests/unit/common/test_availability_zone.py +35 -49
- openstackclient/tests/unit/common/test_extension.py +2 -2
- openstackclient/tests/unit/common/test_module.py +12 -7
- openstackclient/tests/unit/common/test_project_cleanup.py +3 -1
- openstackclient/tests/unit/common/test_quota.py +62 -23
- openstackclient/tests/unit/compute/v2/fakes.py +25 -0
- openstackclient/tests/unit/compute/v2/test_flavor.py +28 -2
- openstackclient/tests/unit/compute/v2/test_keypair.py +6 -6
- openstackclient/tests/unit/compute/v2/test_server.py +17 -104
- openstackclient/tests/unit/compute/v2/test_server_share.py +287 -0
- openstackclient/tests/unit/identity/v3/fakes.py +3 -0
- openstackclient/tests/unit/identity/v3/test_group.py +4 -14
- openstackclient/tests/unit/identity/v3/test_identity_provider.py +303 -299
- openstackclient/tests/unit/identity/v3/test_limit.py +197 -145
- openstackclient/tests/unit/identity/v3/test_project.py +831 -512
- openstackclient/tests/unit/identity/v3/test_protocol.py +97 -88
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +355 -220
- openstackclient/tests/unit/identity/v3/test_user.py +4 -4
- openstackclient/tests/unit/image/v2/test_image.py +16 -16
- openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +105 -6
- openstackclient/tests/unit/network/test_common.py +0 -155
- openstackclient/tests/unit/network/v2/bgpvpn/__init__.py +0 -0
- openstackclient/tests/unit/network/v2/bgpvpn/fakes.py +179 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_bgpvpn.py +584 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_network_association.py +285 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_port_association.py +384 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_router_association.py +297 -0
- openstackclient/tests/unit/network/v2/fwaas/__init__.py +0 -0
- openstackclient/tests/unit/network/v2/fwaas/test_group.py +897 -0
- openstackclient/tests/unit/network/v2/fwaas/test_policy.py +869 -0
- openstackclient/tests/unit/network/v2/fwaas/test_rule.py +980 -0
- openstackclient/tests/unit/network/v2/taas/{test_osc_tap_flow.py → test_tap_flow.py} +18 -25
- openstackclient/tests/unit/network/v2/taas/{test_osc_tap_mirror.py → test_tap_mirror.py} +19 -29
- openstackclient/tests/unit/network/v2/taas/{test_osc_tap_service.py → test_tap_service.py} +19 -29
- openstackclient/tests/unit/network/v2/test_address_group.py +2 -2
- openstackclient/tests/unit/network/v2/{test_floating_ip_network.py → test_floating_ip.py} +3 -2
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +13 -13
- openstackclient/tests/unit/network/v2/test_network_agent.py +8 -4
- openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +3 -3
- openstackclient/tests/unit/network/v2/test_network_flavor.py +2 -2
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +1 -1
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +2 -2
- openstackclient/tests/unit/network/v2/test_network_rbac.py +1 -1
- openstackclient/tests/unit/network/v2/test_network_segment.py +1 -1
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +7 -10
- openstackclient/tests/unit/network/v2/test_network_trunk.py +1 -1
- openstackclient/tests/unit/network/v2/test_router.py +8 -9
- openstackclient/tests/unit/network/v2/{test_security_group_network.py → test_security_group.py} +1 -20
- openstackclient/tests/unit/network/v2/{test_security_group_rule_network.py → test_security_group_rule.py} +7 -41
- openstackclient/tests/unit/network/v2/test_subnet.py +2 -1
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +2 -1
- openstackclient/tests/unit/object/v1/fakes.py +8 -7
- openstackclient/tests/unit/object/v1/test_container.py +65 -101
- openstackclient/tests/unit/object/v1/test_container_all.py +8 -1
- openstackclient/tests/unit/object/v1/test_object.py +44 -84
- openstackclient/tests/unit/object/v1/test_object_all.py +8 -1
- openstackclient/tests/unit/test_hacking.py +108 -0
- openstackclient/tests/unit/volume/v2/fakes.py +1 -0
- openstackclient/tests/unit/volume/v2/test_consistency_group.py +8 -2
- openstackclient/tests/unit/volume/v2/test_volume.py +7 -6
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +1 -5
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +2 -1
- openstackclient/tests/unit/volume/v2/test_volume_type.py +2 -4
- openstackclient/tests/unit/volume/v3/fakes.py +1 -0
- openstackclient/tests/unit/volume/v3/test_volume.py +94 -15
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +1 -5
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +55 -1
- openstackclient/tests/unit/volume/v3/test_volume_type.py +2 -4
- openstackclient/volume/client.py +7 -3
- openstackclient/volume/v2/backup_record.py +15 -6
- openstackclient/volume/v2/consistency_group.py +37 -25
- openstackclient/volume/v2/consistency_group_snapshot.py +27 -12
- openstackclient/volume/v2/qos_specs.py +30 -19
- openstackclient/volume/v2/service.py +17 -6
- openstackclient/volume/v2/volume.py +69 -34
- openstackclient/volume/v2/volume_backend.py +19 -6
- openstackclient/volume/v2/volume_backup.py +48 -22
- openstackclient/volume/v2/volume_host.py +6 -4
- openstackclient/volume/v2/volume_snapshot.py +52 -26
- openstackclient/volume/v2/volume_transfer_request.py +33 -15
- openstackclient/volume/v2/volume_type.py +46 -27
- openstackclient/volume/v3/block_storage_cleanup.py +11 -3
- openstackclient/volume/v3/block_storage_cluster.py +19 -7
- openstackclient/volume/v3/block_storage_log_level.py +15 -6
- openstackclient/volume/v3/block_storage_manage.py +10 -4
- openstackclient/volume/v3/block_storage_resource_filter.py +17 -5
- openstackclient/volume/v3/service.py +16 -6
- openstackclient/volume/v3/volume.py +103 -46
- openstackclient/volume/v3/volume_attachment.py +43 -21
- openstackclient/volume/v3/volume_backup.py +55 -26
- openstackclient/volume/v3/volume_group.py +23 -13
- openstackclient/volume/v3/volume_group_snapshot.py +32 -13
- openstackclient/volume/v3/volume_group_type.py +26 -13
- openstackclient/volume/v3/volume_message.py +15 -7
- openstackclient/volume/v3/volume_snapshot.py +71 -34
- openstackclient/volume/v3/volume_transfer_request.py +33 -15
- openstackclient/volume/v3/volume_type.py +45 -27
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/METADATA +6 -6
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/RECORD +279 -267
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/WHEEL +1 -1
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/entry_points.txt +53 -1
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/AUTHORS +9 -0
- python_openstackclient-10.0.0.dist-info/pbr.json +1 -0
- openstackclient/api/image_v1.py +0 -69
- openstackclient/api/image_v2.py +0 -79
- openstackclient/network/v2/floating_ip_pool.py +0 -38
- openstackclient/tests/functional/image/v1/test_image.py +0 -97
- openstackclient/tests/unit/api/test_image_v1.py +0 -96
- openstackclient/tests/unit/api/test_image_v2.py +0 -96
- openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +0 -248
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +0 -49
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +0 -39
- openstackclient/tests/unit/network/v2/test_network_compute.py +0 -404
- openstackclient/tests/unit/network/v2/test_security_group_compute.py +0 -392
- openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +0 -555
- python_openstackclient-8.3.0.dist-info/pbr.json +0 -1
- /openstackclient/{tests/functional/image/v1 → network/v2/bgpvpn}/__init__.py +0 -0
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/LICENSE +0 -0
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
# Copyright 2016-2017 FUJITSU LIMITED
|
|
2
|
+
# All Rights Reserved
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
5
|
+
# not use this file except in compliance with the License. You may obtain
|
|
6
|
+
# a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
13
|
+
# License for the specific language governing permissions and limitations
|
|
14
|
+
# under the License.
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
from collections.abc import Iterable, Sequence
|
|
18
|
+
import logging
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from cliff import columns as cliff_columns
|
|
22
|
+
from osc_lib.cli import identity as identity_utils
|
|
23
|
+
from osc_lib import exceptions
|
|
24
|
+
from osc_lib import utils
|
|
25
|
+
from osc_lib.utils import columns as column_util
|
|
26
|
+
|
|
27
|
+
from openstackclient import command
|
|
28
|
+
from openstackclient.i18n import _
|
|
29
|
+
from openstackclient.identity import common as identity_common
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
LOG = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
_attr_map = (
|
|
36
|
+
('id', 'ID', column_util.LIST_BOTH),
|
|
37
|
+
('name', 'Name', column_util.LIST_BOTH),
|
|
38
|
+
('enabled', 'Enabled', column_util.LIST_BOTH),
|
|
39
|
+
('summary', 'Summary', column_util.LIST_SHORT_ONLY),
|
|
40
|
+
('description', 'Description', column_util.LIST_LONG_ONLY),
|
|
41
|
+
('firewall_policy_id', 'Firewall Policy', column_util.LIST_BOTH),
|
|
42
|
+
('ip_version', 'IP Version', column_util.LIST_LONG_ONLY),
|
|
43
|
+
('action', 'Action', column_util.LIST_LONG_ONLY),
|
|
44
|
+
('protocol', 'Protocol', column_util.LIST_LONG_ONLY),
|
|
45
|
+
('source_ip_address', 'Source IP Address', column_util.LIST_LONG_ONLY),
|
|
46
|
+
('source_port', 'Source Port', column_util.LIST_LONG_ONLY),
|
|
47
|
+
(
|
|
48
|
+
'destination_ip_address',
|
|
49
|
+
'Destination IP Address',
|
|
50
|
+
column_util.LIST_LONG_ONLY,
|
|
51
|
+
),
|
|
52
|
+
('destination_port', 'Destination Port', column_util.LIST_LONG_ONLY),
|
|
53
|
+
('shared', 'Shared', column_util.LIST_LONG_ONLY),
|
|
54
|
+
('project_id', 'Project', column_util.LIST_LONG_ONLY),
|
|
55
|
+
(
|
|
56
|
+
'source_firewall_group_id',
|
|
57
|
+
'Source Firewall Group ID',
|
|
58
|
+
column_util.LIST_LONG_ONLY,
|
|
59
|
+
),
|
|
60
|
+
(
|
|
61
|
+
'destination_firewall_group_id',
|
|
62
|
+
'Destination Firewall Group ID',
|
|
63
|
+
column_util.LIST_LONG_ONLY,
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
_attr_map_dict = {x[0]: x[1] for x in _attr_map}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _convert_to_lowercase(string: str) -> str:
|
|
71
|
+
return string.lower()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _get_common_parser(
|
|
75
|
+
parser: argparse.ArgumentParser,
|
|
76
|
+
) -> argparse.ArgumentParser:
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
'--name', metavar='<name>', help=_('Name of the firewall rule')
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
'--description',
|
|
82
|
+
metavar='<description>',
|
|
83
|
+
help=_('Description of the firewall rule'),
|
|
84
|
+
)
|
|
85
|
+
parser.add_argument(
|
|
86
|
+
'--protocol',
|
|
87
|
+
type=_convert_to_lowercase,
|
|
88
|
+
help=_(
|
|
89
|
+
'IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, '
|
|
90
|
+
'ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, '
|
|
91
|
+
'ipv6-route, ospf, pgm, rsvp, sctp, tcp, udp, udplite, '
|
|
92
|
+
'vrrp and integer representations [0-255] or any; '
|
|
93
|
+
'default: any (all protocols))'
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
parser.add_argument(
|
|
97
|
+
'--action',
|
|
98
|
+
choices=['allow', 'deny', 'reject'],
|
|
99
|
+
type=_convert_to_lowercase,
|
|
100
|
+
help=_('Action for the firewall rule'),
|
|
101
|
+
)
|
|
102
|
+
parser.add_argument(
|
|
103
|
+
'--ip-version',
|
|
104
|
+
metavar='<ip-version>',
|
|
105
|
+
choices=['4', '6'],
|
|
106
|
+
help=_('Set IP version 4 or 6 (default is 4)'),
|
|
107
|
+
)
|
|
108
|
+
src_ip_group = parser.add_mutually_exclusive_group()
|
|
109
|
+
src_ip_group.add_argument(
|
|
110
|
+
'--source-ip-address',
|
|
111
|
+
metavar='<source-ip-address>',
|
|
112
|
+
help=_('Source IP address or subnet'),
|
|
113
|
+
)
|
|
114
|
+
src_ip_group.add_argument(
|
|
115
|
+
'--no-source-ip-address',
|
|
116
|
+
action='store_true',
|
|
117
|
+
help=_('Detach source IP address'),
|
|
118
|
+
)
|
|
119
|
+
dst_ip_group = parser.add_mutually_exclusive_group()
|
|
120
|
+
dst_ip_group.add_argument(
|
|
121
|
+
'--destination-ip-address',
|
|
122
|
+
metavar='<destination-ip-address>',
|
|
123
|
+
help=_('Destination IP address or subnet'),
|
|
124
|
+
)
|
|
125
|
+
dst_ip_group.add_argument(
|
|
126
|
+
'--no-destination-ip-address',
|
|
127
|
+
action='store_true',
|
|
128
|
+
help=_('Detach destination IP address'),
|
|
129
|
+
)
|
|
130
|
+
src_port_group = parser.add_mutually_exclusive_group()
|
|
131
|
+
src_port_group.add_argument(
|
|
132
|
+
'--source-port',
|
|
133
|
+
metavar='<source-port>',
|
|
134
|
+
help=_(
|
|
135
|
+
'Source port number or range '
|
|
136
|
+
'(integer in [1, 65535] or range like 123:456)'
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
src_port_group.add_argument(
|
|
140
|
+
'--no-source-port',
|
|
141
|
+
action='store_true',
|
|
142
|
+
help=_('Detach source port number or range'),
|
|
143
|
+
)
|
|
144
|
+
dst_port_group = parser.add_mutually_exclusive_group()
|
|
145
|
+
dst_port_group.add_argument(
|
|
146
|
+
'--destination-port',
|
|
147
|
+
metavar='<destination-port>',
|
|
148
|
+
help=_(
|
|
149
|
+
'Destination port number or range'
|
|
150
|
+
'(integer in [1, 65535] or range like 123:456)'
|
|
151
|
+
),
|
|
152
|
+
)
|
|
153
|
+
dst_port_group.add_argument(
|
|
154
|
+
'--no-destination-port',
|
|
155
|
+
action='store_true',
|
|
156
|
+
help=_('Detach destination port number or range'),
|
|
157
|
+
)
|
|
158
|
+
shared_group = parser.add_mutually_exclusive_group()
|
|
159
|
+
shared_group.add_argument(
|
|
160
|
+
'--share',
|
|
161
|
+
action='store_true',
|
|
162
|
+
default=None,
|
|
163
|
+
dest='shared',
|
|
164
|
+
help=_(
|
|
165
|
+
'Share the firewall rule to be used in all projects '
|
|
166
|
+
'(by default, it is restricted to be used by the '
|
|
167
|
+
'current project).'
|
|
168
|
+
),
|
|
169
|
+
)
|
|
170
|
+
shared_group.add_argument(
|
|
171
|
+
'--no-share',
|
|
172
|
+
action='store_false',
|
|
173
|
+
dest='shared',
|
|
174
|
+
help=_('Restrict use of the firewall rule to the current project'),
|
|
175
|
+
)
|
|
176
|
+
enable_group = parser.add_mutually_exclusive_group()
|
|
177
|
+
enable_group.add_argument(
|
|
178
|
+
'--enable-rule',
|
|
179
|
+
action='store_true',
|
|
180
|
+
default=None,
|
|
181
|
+
dest='enabled',
|
|
182
|
+
help=_('Enable this rule (default is enabled)'),
|
|
183
|
+
)
|
|
184
|
+
enable_group.add_argument(
|
|
185
|
+
'--disable-rule',
|
|
186
|
+
action='store_false',
|
|
187
|
+
dest='enabled',
|
|
188
|
+
help=_('Disable this rule'),
|
|
189
|
+
)
|
|
190
|
+
src_fwg_group = parser.add_mutually_exclusive_group()
|
|
191
|
+
src_fwg_group.add_argument(
|
|
192
|
+
'--source-firewall-group',
|
|
193
|
+
metavar='<source-firewall-group>',
|
|
194
|
+
help=_('Source firewall group (name or ID)'),
|
|
195
|
+
)
|
|
196
|
+
src_fwg_group.add_argument(
|
|
197
|
+
'--no-source-firewall-group',
|
|
198
|
+
action='store_true',
|
|
199
|
+
help=_('No associated source firewall group'),
|
|
200
|
+
)
|
|
201
|
+
dst_fwg_group = parser.add_mutually_exclusive_group()
|
|
202
|
+
dst_fwg_group.add_argument(
|
|
203
|
+
'--destination-firewall-group',
|
|
204
|
+
metavar='<destination-firewall-group>',
|
|
205
|
+
help=_('Destination firewall group (name or ID)'),
|
|
206
|
+
)
|
|
207
|
+
dst_fwg_group.add_argument(
|
|
208
|
+
'--no-destination-firewall-group',
|
|
209
|
+
action='store_true',
|
|
210
|
+
help=_('No associated destination firewall group'),
|
|
211
|
+
)
|
|
212
|
+
return parser
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _get_common_attrs(
|
|
216
|
+
client_manager: Any,
|
|
217
|
+
parsed_args: argparse.Namespace,
|
|
218
|
+
is_create: bool = True,
|
|
219
|
+
) -> dict[str, Any]:
|
|
220
|
+
attrs: dict[str, Any] = {}
|
|
221
|
+
client = client_manager.network
|
|
222
|
+
if parsed_args.name:
|
|
223
|
+
attrs['name'] = parsed_args.name
|
|
224
|
+
if parsed_args.description:
|
|
225
|
+
attrs['description'] = parsed_args.description
|
|
226
|
+
if parsed_args.protocol:
|
|
227
|
+
protocol = parsed_args.protocol
|
|
228
|
+
attrs['protocol'] = None if protocol == 'any' else protocol
|
|
229
|
+
if parsed_args.action:
|
|
230
|
+
attrs['action'] = parsed_args.action
|
|
231
|
+
if parsed_args.ip_version:
|
|
232
|
+
attrs['ip_version'] = str(parsed_args.ip_version)
|
|
233
|
+
|
|
234
|
+
if parsed_args.source_port:
|
|
235
|
+
attrs['source_port'] = parsed_args.source_port
|
|
236
|
+
if parsed_args.no_source_port:
|
|
237
|
+
attrs['source_port'] = None
|
|
238
|
+
|
|
239
|
+
if parsed_args.source_ip_address:
|
|
240
|
+
attrs['source_ip_address'] = parsed_args.source_ip_address
|
|
241
|
+
if parsed_args.no_source_ip_address:
|
|
242
|
+
attrs['source_ip_address'] = None
|
|
243
|
+
|
|
244
|
+
if parsed_args.destination_port:
|
|
245
|
+
attrs['destination_port'] = parsed_args.destination_port
|
|
246
|
+
if parsed_args.no_destination_port:
|
|
247
|
+
attrs['destination_port'] = None
|
|
248
|
+
|
|
249
|
+
if parsed_args.destination_ip_address:
|
|
250
|
+
attrs['destination_ip_address'] = parsed_args.destination_ip_address
|
|
251
|
+
if parsed_args.no_destination_ip_address:
|
|
252
|
+
attrs['destination_ip_address'] = None
|
|
253
|
+
|
|
254
|
+
if parsed_args.enabled is not None:
|
|
255
|
+
attrs['enabled'] = parsed_args.enabled
|
|
256
|
+
|
|
257
|
+
if parsed_args.shared is not None:
|
|
258
|
+
attrs['shared'] = parsed_args.shared
|
|
259
|
+
|
|
260
|
+
if parsed_args.source_firewall_group:
|
|
261
|
+
attrs['source_firewall_group_id'] = client.find_firewall_group(
|
|
262
|
+
parsed_args.source_firewall_group, ignore_missing=False
|
|
263
|
+
).id
|
|
264
|
+
if parsed_args.no_source_firewall_group:
|
|
265
|
+
attrs['source_firewall_group_id'] = None
|
|
266
|
+
|
|
267
|
+
if parsed_args.destination_firewall_group:
|
|
268
|
+
attrs['destination_firewall_group_id'] = client.find_firewall_group(
|
|
269
|
+
parsed_args.destination_firewall_group, ignore_missing=False
|
|
270
|
+
).id
|
|
271
|
+
if parsed_args.no_destination_firewall_group:
|
|
272
|
+
attrs['destination_firewall_group_id'] = None
|
|
273
|
+
|
|
274
|
+
return attrs
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class ProtocolColumn(cliff_columns.FormattableColumn[str | None]):
|
|
278
|
+
def human_readable(self) -> str:
|
|
279
|
+
return self._value if self._value else 'any'
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
_formatters = {'protocol': ProtocolColumn}
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class CreateFirewallRule(command.ShowOne):
|
|
286
|
+
_description = _("Create a new firewall rule")
|
|
287
|
+
|
|
288
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
289
|
+
parser = super().get_parser(prog_name)
|
|
290
|
+
_get_common_parser(parser)
|
|
291
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
292
|
+
return parser
|
|
293
|
+
|
|
294
|
+
def take_action(
|
|
295
|
+
self, parsed_args: argparse.Namespace
|
|
296
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
297
|
+
client = self.app.client_manager.network
|
|
298
|
+
attrs = _get_common_attrs(self.app.client_manager, parsed_args)
|
|
299
|
+
if 'project' in parsed_args and parsed_args.project is not None:
|
|
300
|
+
attrs['project_id'] = identity_common.find_project(
|
|
301
|
+
self.app.client_manager.identity,
|
|
302
|
+
parsed_args.project,
|
|
303
|
+
parsed_args.project_domain,
|
|
304
|
+
).id
|
|
305
|
+
obj = client.create_firewall_rule(**attrs)
|
|
306
|
+
display_columns, columns = utils.get_osc_show_columns_for_sdk_resource(
|
|
307
|
+
obj, _attr_map_dict, ['location', 'tenant_id']
|
|
308
|
+
)
|
|
309
|
+
data = utils.get_dict_properties(obj, columns, formatters=_formatters)
|
|
310
|
+
return display_columns, data
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
class DeleteFirewallRule(command.Command):
|
|
314
|
+
_description = _("Delete firewall rule(s)")
|
|
315
|
+
|
|
316
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
317
|
+
parser = super().get_parser(prog_name)
|
|
318
|
+
parser.add_argument(
|
|
319
|
+
'firewall_rule',
|
|
320
|
+
metavar='<firewall-rule>',
|
|
321
|
+
nargs='+',
|
|
322
|
+
help=_('Firewall rule(s) to delete (name or ID)'),
|
|
323
|
+
)
|
|
324
|
+
return parser
|
|
325
|
+
|
|
326
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
327
|
+
client = self.app.client_manager.network
|
|
328
|
+
result = 0
|
|
329
|
+
for fwr in parsed_args.firewall_rule:
|
|
330
|
+
try:
|
|
331
|
+
fwr = client.find_firewall_rule(fwr, ignore_missing=False)
|
|
332
|
+
client.delete_firewall_rule(fwr.id)
|
|
333
|
+
except Exception as e:
|
|
334
|
+
result += 1
|
|
335
|
+
LOG.error(
|
|
336
|
+
_(
|
|
337
|
+
"Failed to delete Firewall rule with "
|
|
338
|
+
"name or ID '%(firewall_rule)s': %(e)s"
|
|
339
|
+
),
|
|
340
|
+
{'firewall_rule': fwr, 'e': e},
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
if result > 0:
|
|
344
|
+
total = len(parsed_args.firewall_rule)
|
|
345
|
+
msg = _(
|
|
346
|
+
"%(result)s of %(total)s firewall rule(s) failed to delete."
|
|
347
|
+
) % {'result': result, 'total': total}
|
|
348
|
+
raise exceptions.CommandError(msg)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
class ListFirewallRule(command.Lister):
|
|
352
|
+
_description = _("List firewall rules that belong to a given tenant")
|
|
353
|
+
|
|
354
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
355
|
+
parser = super().get_parser(prog_name)
|
|
356
|
+
parser.add_argument(
|
|
357
|
+
'--long',
|
|
358
|
+
action='store_true',
|
|
359
|
+
default=False,
|
|
360
|
+
help=_("List additional fields in output"),
|
|
361
|
+
)
|
|
362
|
+
return parser
|
|
363
|
+
|
|
364
|
+
def extend_list(
|
|
365
|
+
self, data: Iterable[Any], parsed_args: argparse.Namespace
|
|
366
|
+
) -> list[Any]:
|
|
367
|
+
ext_data = []
|
|
368
|
+
for d in data:
|
|
369
|
+
protocol = d['protocol'].upper() if d['protocol'] else 'ANY'
|
|
370
|
+
src_ip = 'none specified'
|
|
371
|
+
dst_ip = 'none specified'
|
|
372
|
+
src_port = '(none specified)'
|
|
373
|
+
dst_port = '(none specified)'
|
|
374
|
+
if d.get('source_ip_address'):
|
|
375
|
+
src_ip = str(d['source_ip_address']).lower()
|
|
376
|
+
if d.get('source_port'):
|
|
377
|
+
src_port = '(' + str(d['source_port']).lower() + ')'
|
|
378
|
+
if d.get('destination_ip_address'):
|
|
379
|
+
dst_ip = str(d['destination_ip_address']).lower()
|
|
380
|
+
if d.get('destination_port'):
|
|
381
|
+
dst_port = '(' + str(d['destination_port']).lower() + ')'
|
|
382
|
+
action = d['action'] if d.get('action') else 'no-action'
|
|
383
|
+
src = 'source(port): ' + src_ip + src_port
|
|
384
|
+
dst = 'dest(port): ' + dst_ip + dst_port
|
|
385
|
+
d['summary'] = ',\n '.join([protocol, src, dst, action])
|
|
386
|
+
ext_data.append(d)
|
|
387
|
+
return ext_data
|
|
388
|
+
|
|
389
|
+
def take_action(
|
|
390
|
+
self, parsed_args: argparse.Namespace
|
|
391
|
+
) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
|
|
392
|
+
client = self.app.client_manager.network
|
|
393
|
+
obj = client.firewall_rules()
|
|
394
|
+
obj_extend = self.extend_list(obj, parsed_args)
|
|
395
|
+
headers, columns = column_util.get_column_definitions(
|
|
396
|
+
list(_attr_map), long_listing=parsed_args.long
|
|
397
|
+
)
|
|
398
|
+
return (
|
|
399
|
+
headers,
|
|
400
|
+
(
|
|
401
|
+
utils.get_dict_properties(s, columns, formatters=_formatters)
|
|
402
|
+
for s in obj_extend
|
|
403
|
+
),
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class SetFirewallRule(command.Command):
|
|
408
|
+
_description = _("Set firewall rule properties")
|
|
409
|
+
|
|
410
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
411
|
+
parser = super().get_parser(prog_name)
|
|
412
|
+
_get_common_parser(parser)
|
|
413
|
+
parser.add_argument(
|
|
414
|
+
'firewall_rule',
|
|
415
|
+
metavar='<firewall-rule>',
|
|
416
|
+
help=_('Firewall rule to set (name or ID)'),
|
|
417
|
+
)
|
|
418
|
+
return parser
|
|
419
|
+
|
|
420
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
421
|
+
client = self.app.client_manager.network
|
|
422
|
+
attrs = _get_common_attrs(
|
|
423
|
+
self.app.client_manager, parsed_args, is_create=False
|
|
424
|
+
)
|
|
425
|
+
fwr_id = client.find_firewall_rule(
|
|
426
|
+
parsed_args.firewall_rule, ignore_missing=False
|
|
427
|
+
).id
|
|
428
|
+
try:
|
|
429
|
+
client.update_firewall_rule(fwr_id, **attrs)
|
|
430
|
+
except Exception as e:
|
|
431
|
+
msg = _("Failed to set firewall rule '%(rule)s': %(e)s") % {
|
|
432
|
+
'rule': parsed_args.firewall_rule,
|
|
433
|
+
'e': e,
|
|
434
|
+
}
|
|
435
|
+
raise exceptions.CommandError(msg)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
class ShowFirewallRule(command.ShowOne):
|
|
439
|
+
_description = _("Display firewall rule details")
|
|
440
|
+
|
|
441
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
442
|
+
parser = super().get_parser(prog_name)
|
|
443
|
+
parser.add_argument(
|
|
444
|
+
'firewall_rule',
|
|
445
|
+
metavar='<firewall-rule>',
|
|
446
|
+
help=_('Firewall rule to display (name or ID)'),
|
|
447
|
+
)
|
|
448
|
+
return parser
|
|
449
|
+
|
|
450
|
+
def take_action(
|
|
451
|
+
self, parsed_args: argparse.Namespace
|
|
452
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
453
|
+
client = self.app.client_manager.network
|
|
454
|
+
fwr_id = client.find_firewall_rule(
|
|
455
|
+
parsed_args.firewall_rule, ignore_missing=False
|
|
456
|
+
).id
|
|
457
|
+
obj = client.get_firewall_rule(fwr_id)
|
|
458
|
+
display_columns, columns = utils.get_osc_show_columns_for_sdk_resource(
|
|
459
|
+
obj, _attr_map_dict, ['location', 'tenant_id']
|
|
460
|
+
)
|
|
461
|
+
data = utils.get_dict_properties(obj, columns, formatters=_formatters)
|
|
462
|
+
return (display_columns, data)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
class UnsetFirewallRule(command.Command):
|
|
466
|
+
_description = _("Unset firewall rule properties")
|
|
467
|
+
|
|
468
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
469
|
+
parser = super().get_parser(prog_name)
|
|
470
|
+
parser.add_argument(
|
|
471
|
+
'firewall_rule',
|
|
472
|
+
metavar='<firewall-rule>',
|
|
473
|
+
help=_('Firewall rule to unset (name or ID)'),
|
|
474
|
+
)
|
|
475
|
+
parser.add_argument(
|
|
476
|
+
'--source-ip-address',
|
|
477
|
+
action='store_true',
|
|
478
|
+
help=_('Source IP address or subnet'),
|
|
479
|
+
)
|
|
480
|
+
parser.add_argument(
|
|
481
|
+
'--destination-ip-address',
|
|
482
|
+
action='store_true',
|
|
483
|
+
help=_('Destination IP address or subnet'),
|
|
484
|
+
)
|
|
485
|
+
parser.add_argument(
|
|
486
|
+
'--source-port',
|
|
487
|
+
action='store_true',
|
|
488
|
+
help=_(
|
|
489
|
+
'Source port number or range'
|
|
490
|
+
'(integer in [1, 65535] or range like 123:456)'
|
|
491
|
+
),
|
|
492
|
+
)
|
|
493
|
+
parser.add_argument(
|
|
494
|
+
'--destination-port',
|
|
495
|
+
action='store_true',
|
|
496
|
+
help=_(
|
|
497
|
+
'Destination port number or range'
|
|
498
|
+
'(integer in [1, 65535] or range like 123:456)'
|
|
499
|
+
),
|
|
500
|
+
)
|
|
501
|
+
parser.add_argument(
|
|
502
|
+
'--share',
|
|
503
|
+
action='store_true',
|
|
504
|
+
help=_(
|
|
505
|
+
'(Deprecated) Use "firewall rule set --no-share" instead. '
|
|
506
|
+
'Restrict use of the firewall rule to the current project'
|
|
507
|
+
),
|
|
508
|
+
)
|
|
509
|
+
parser.add_argument(
|
|
510
|
+
'--enable-rule',
|
|
511
|
+
action='store_true',
|
|
512
|
+
help=_(
|
|
513
|
+
'(Deprecated) Use "firewall rule set --disable-rule" instead. '
|
|
514
|
+
'Disable this rule'
|
|
515
|
+
),
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
parser.add_argument(
|
|
519
|
+
'--source-firewall-group',
|
|
520
|
+
action='store_true',
|
|
521
|
+
help=_('Source firewall group (name or ID)'),
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
parser.add_argument(
|
|
525
|
+
'--destination-firewall-group',
|
|
526
|
+
action='store_true',
|
|
527
|
+
help=_('Destination firewall group (name or ID)'),
|
|
528
|
+
)
|
|
529
|
+
return parser
|
|
530
|
+
|
|
531
|
+
def _get_attrs(
|
|
532
|
+
self, client_manager: Any, parsed_args: argparse.Namespace
|
|
533
|
+
) -> dict[str, Any]:
|
|
534
|
+
attrs: dict[str, Any] = {}
|
|
535
|
+
if parsed_args.source_ip_address:
|
|
536
|
+
attrs['source_ip_address'] = None
|
|
537
|
+
if parsed_args.source_port:
|
|
538
|
+
attrs['source_port'] = None
|
|
539
|
+
if parsed_args.destination_ip_address:
|
|
540
|
+
attrs['destination_ip_address'] = None
|
|
541
|
+
if parsed_args.destination_port:
|
|
542
|
+
attrs['destination_port'] = None
|
|
543
|
+
if parsed_args.share:
|
|
544
|
+
LOG.warning(
|
|
545
|
+
'The --share option is deprecated, please use '
|
|
546
|
+
'"firewall rule set --no-share" instead.'
|
|
547
|
+
)
|
|
548
|
+
attrs['shared'] = False
|
|
549
|
+
if parsed_args.enable_rule:
|
|
550
|
+
LOG.warning(
|
|
551
|
+
'The --enable-rule option is deprecated, please use '
|
|
552
|
+
'"firewall rule set --disable-rule" instead.'
|
|
553
|
+
)
|
|
554
|
+
attrs['enabled'] = False
|
|
555
|
+
if parsed_args.source_firewall_group:
|
|
556
|
+
attrs['source_firewall_group_id'] = None
|
|
557
|
+
if parsed_args.destination_firewall_group:
|
|
558
|
+
attrs['destination_firewall_group_id'] = None
|
|
559
|
+
return attrs
|
|
560
|
+
|
|
561
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
562
|
+
client = self.app.client_manager.network
|
|
563
|
+
attrs = self._get_attrs(self.app.client_manager, parsed_args)
|
|
564
|
+
fwr_id = client.find_firewall_rule(
|
|
565
|
+
parsed_args.firewall_rule, ignore_missing=False
|
|
566
|
+
).id
|
|
567
|
+
try:
|
|
568
|
+
client.update_firewall_rule(fwr_id, **attrs)
|
|
569
|
+
except Exception as e:
|
|
570
|
+
msg = _("Failed to unset firewall rule '%(rule)s': %(e)s") % {
|
|
571
|
+
'rule': parsed_args.firewall_rule,
|
|
572
|
+
'e': e,
|
|
573
|
+
}
|
|
574
|
+
raise exceptions.CommandError(msg)
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
"""IP Availability Info implementations"""
|
|
15
15
|
|
|
16
|
+
import argparse
|
|
17
|
+
from collections.abc import Iterable, Sequence
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
16
20
|
from osc_lib.cli import format_columns
|
|
17
21
|
from osc_lib import utils
|
|
18
22
|
|
|
@@ -25,7 +29,7 @@ _formatters = {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
|
|
28
|
-
def _get_columns(item):
|
|
32
|
+
def _get_columns(item: Any) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
29
33
|
hidden_columns = ['id', 'name', 'location', 'tenant_id']
|
|
30
34
|
return utils.get_osc_show_columns_for_sdk_resource(
|
|
31
35
|
item, {}, hidden_columns
|
|
@@ -37,7 +41,7 @@ def _get_columns(item):
|
|
|
37
41
|
class ListIPAvailability(command.Lister):
|
|
38
42
|
_description = _("List IP availability for network")
|
|
39
43
|
|
|
40
|
-
def get_parser(self, prog_name):
|
|
44
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
41
45
|
parser = super().get_parser(prog_name)
|
|
42
46
|
parser.add_argument(
|
|
43
47
|
'--ip-version',
|
|
@@ -62,7 +66,9 @@ class ListIPAvailability(command.Lister):
|
|
|
62
66
|
identity_common.add_project_domain_option_to_parser(parser)
|
|
63
67
|
return parser
|
|
64
68
|
|
|
65
|
-
def take_action(
|
|
69
|
+
def take_action(
|
|
70
|
+
self, parsed_args: argparse.Namespace
|
|
71
|
+
) -> tuple[tuple[str, ...], Iterable[tuple[Any, ...]]]:
|
|
66
72
|
client = self.app.client_manager.network
|
|
67
73
|
|
|
68
74
|
columns = (
|
|
@@ -106,7 +112,7 @@ class ListIPAvailability(command.Lister):
|
|
|
106
112
|
class ShowIPAvailability(command.ShowOne):
|
|
107
113
|
_description = _("Show network IP availability details")
|
|
108
114
|
|
|
109
|
-
def get_parser(self, prog_name):
|
|
115
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
110
116
|
parser = super().get_parser(prog_name)
|
|
111
117
|
parser.add_argument(
|
|
112
118
|
'network',
|
|
@@ -115,7 +121,9 @@ class ShowIPAvailability(command.ShowOne):
|
|
|
115
121
|
)
|
|
116
122
|
return parser
|
|
117
123
|
|
|
118
|
-
def take_action(
|
|
124
|
+
def take_action(
|
|
125
|
+
self, parsed_args: argparse.Namespace
|
|
126
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
119
127
|
client = self.app.client_manager.network
|
|
120
128
|
network_id = client.find_network(
|
|
121
129
|
parsed_args.network, ignore_missing=False
|