python-openstackclient 8.2.0__py3-none-any.whl → 8.3.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/api/object_store_v1.py +4 -1
- openstackclient/command.py +27 -0
- openstackclient/common/availability_zone.py +1 -1
- openstackclient/common/clientmanager.py +59 -21
- openstackclient/common/configuration.py +1 -1
- openstackclient/common/extension.py +1 -1
- openstackclient/common/limits.py +1 -1
- openstackclient/common/module.py +4 -2
- openstackclient/common/project_cleanup.py +10 -8
- openstackclient/common/quota.py +23 -6
- openstackclient/common/versions.py +1 -2
- openstackclient/compute/v2/agent.py +1 -1
- openstackclient/compute/v2/aggregate.py +6 -5
- openstackclient/compute/v2/console.py +5 -3
- openstackclient/compute/v2/console_connection.py +1 -1
- openstackclient/compute/v2/flavor.py +1 -1
- openstackclient/compute/v2/host.py +1 -1
- openstackclient/compute/v2/hypervisor.py +1 -1
- openstackclient/compute/v2/hypervisor_stats.py +1 -1
- openstackclient/compute/v2/keypair.py +1 -1
- openstackclient/compute/v2/server.py +76 -27
- openstackclient/compute/v2/server_backup.py +1 -1
- openstackclient/compute/v2/server_event.py +1 -1
- openstackclient/compute/v2/server_group.py +4 -2
- openstackclient/compute/v2/server_image.py +1 -1
- openstackclient/compute/v2/server_migration.py +1 -1
- openstackclient/compute/v2/server_volume.py +1 -1
- openstackclient/compute/v2/service.py +1 -1
- openstackclient/compute/v2/usage.py +6 -4
- openstackclient/identity/common.py +2 -1
- openstackclient/identity/v2_0/catalog.py +3 -2
- openstackclient/identity/v2_0/ec2creds.py +1 -1
- openstackclient/identity/v2_0/endpoint.py +1 -1
- openstackclient/identity/v2_0/project.py +17 -7
- openstackclient/identity/v2_0/role.py +1 -1
- openstackclient/identity/v2_0/role_assignment.py +3 -3
- openstackclient/identity/v2_0/service.py +1 -1
- openstackclient/identity/v2_0/token.py +1 -1
- openstackclient/identity/v2_0/user.py +2 -2
- openstackclient/identity/v3/access_rule.py +16 -4
- openstackclient/identity/v3/application_credential.py +30 -10
- openstackclient/identity/v3/catalog.py +3 -3
- openstackclient/identity/v3/consumer.py +1 -1
- openstackclient/identity/v3/credential.py +1 -1
- openstackclient/identity/v3/domain.py +10 -4
- openstackclient/identity/v3/ec2creds.py +1 -1
- openstackclient/identity/v3/endpoint.py +33 -12
- openstackclient/identity/v3/endpoint_group.py +1 -1
- openstackclient/identity/v3/federation_protocol.py +1 -1
- openstackclient/identity/v3/group.py +11 -5
- openstackclient/identity/v3/identity_provider.py +12 -10
- openstackclient/identity/v3/implied_role.py +1 -1
- openstackclient/identity/v3/limit.py +1 -1
- openstackclient/identity/v3/mapping.py +1 -1
- openstackclient/identity/v3/policy.py +1 -1
- openstackclient/identity/v3/project.py +10 -3
- openstackclient/identity/v3/region.py +1 -1
- openstackclient/identity/v3/registered_limit.py +16 -11
- openstackclient/identity/v3/role.py +20 -39
- openstackclient/identity/v3/role_assignment.py +12 -23
- openstackclient/identity/v3/service.py +1 -1
- openstackclient/identity/v3/service_provider.py +1 -1
- openstackclient/identity/v3/tag.py +3 -2
- openstackclient/identity/v3/token.py +3 -2
- openstackclient/identity/v3/trust.py +4 -2
- openstackclient/identity/v3/unscoped_saml.py +1 -1
- openstackclient/identity/v3/user.py +22 -13
- openstackclient/image/v1/image.py +19 -16
- openstackclient/image/v2/cache.py +1 -1
- openstackclient/image/v2/image.py +14 -11
- openstackclient/image/v2/info.py +1 -1
- openstackclient/image/v2/metadef_namespaces.py +1 -1
- openstackclient/image/v2/metadef_objects.py +1 -1
- openstackclient/image/v2/metadef_properties.py +3 -2
- openstackclient/image/v2/metadef_resource_type_association.py +1 -1
- openstackclient/image/v2/metadef_resource_types.py +1 -1
- openstackclient/image/v2/task.py +1 -1
- openstackclient/network/common.py +10 -9
- openstackclient/network/v2/address_group.py +4 -3
- openstackclient/network/v2/address_scope.py +8 -6
- openstackclient/network/v2/default_security_group_rule.py +9 -8
- openstackclient/network/v2/floating_ip.py +16 -9
- openstackclient/network/v2/floating_ip_port_forwarding.py +9 -6
- openstackclient/network/v2/ip_availability.py +7 -4
- openstackclient/network/v2/l3_conntrack_helper.py +11 -4
- openstackclient/network/v2/local_ip.py +13 -7
- openstackclient/network/v2/local_ip_association.py +7 -4
- openstackclient/network/v2/ndp_proxy.py +13 -6
- openstackclient/network/v2/network.py +33 -16
- openstackclient/network/v2/network_agent.py +5 -5
- openstackclient/network/v2/network_auto_allocated_topology.py +1 -1
- openstackclient/network/v2/network_flavor.py +1 -1
- openstackclient/network/v2/network_flavor_profile.py +1 -1
- openstackclient/network/v2/network_meter.py +1 -1
- openstackclient/network/v2/network_meter_rule.py +1 -1
- openstackclient/network/v2/network_qos_policy.py +7 -5
- openstackclient/network/v2/network_qos_rule.py +1 -1
- openstackclient/network/v2/network_qos_rule_type.py +1 -1
- openstackclient/network/v2/network_rbac.py +8 -5
- openstackclient/network/v2/network_segment.py +2 -2
- openstackclient/network/v2/network_segment_range.py +13 -6
- openstackclient/network/v2/network_service_provider.py +1 -1
- openstackclient/network/v2/network_trunk.py +65 -42
- openstackclient/network/v2/port.py +22 -20
- openstackclient/network/v2/router.py +19 -8
- openstackclient/network/v2/security_group.py +10 -6
- openstackclient/network/v2/security_group_rule.py +11 -5
- openstackclient/network/v2/subnet.py +17 -18
- openstackclient/network/v2/subnet_pool.py +11 -9
- openstackclient/network/v2/taas/__init__.py +0 -0
- openstackclient/network/v2/taas/tap_flow.py +245 -0
- openstackclient/network/v2/taas/tap_mirror.py +237 -0
- openstackclient/network/v2/taas/tap_service.py +211 -0
- openstackclient/object/v1/account.py +1 -1
- openstackclient/object/v1/container.py +1 -1
- openstackclient/object/v1/object.py +1 -1
- openstackclient/shell.py +18 -8
- openstackclient/tests/functional/identity/v3/test_catalog.py +42 -23
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +174 -0
- openstackclient/tests/functional/image/v2/test_cache.py +54 -0
- openstackclient/tests/functional/image/v2/test_metadef_resource_type.py +55 -0
- openstackclient/tests/unit/common/test_command.py +1 -1
- openstackclient/tests/unit/common/test_extension.py +2 -3
- openstackclient/tests/unit/common/test_module.py +14 -7
- openstackclient/tests/unit/common/test_quota.py +20 -0
- openstackclient/tests/unit/compute/v2/test_aggregate.py +5 -3
- openstackclient/tests/unit/compute/v2/test_console.py +1 -4
- openstackclient/tests/unit/compute/v2/test_flavor.py +1 -3
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -9
- openstackclient/tests/unit/compute/v2/test_server.py +364 -30
- openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -3
- openstackclient/tests/unit/compute/v2/test_service.py +1 -3
- openstackclient/tests/unit/fakes.py +35 -134
- openstackclient/tests/unit/identity/test_common.py +100 -0
- openstackclient/tests/unit/identity/v2_0/test_project.py +4 -4
- openstackclient/tests/unit/identity/v3/fakes.py +10 -2
- openstackclient/tests/unit/identity/v3/test_application_credential.py +3 -3
- openstackclient/tests/unit/identity/v3/test_domain.py +1 -1
- openstackclient/tests/unit/identity/v3/test_endpoint.py +1 -1
- openstackclient/tests/unit/identity/v3/test_group.py +4 -2
- openstackclient/tests/unit/identity/v3/test_identity_provider.py +10 -10
- openstackclient/tests/unit/identity/v3/test_oauth.py +1 -1
- openstackclient/tests/unit/identity/v3/test_project.py +1 -1
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +2 -2
- openstackclient/tests/unit/identity/v3/test_role.py +1 -82
- openstackclient/tests/unit/identity/v3/test_user.py +7 -51
- openstackclient/tests/unit/image/v2/test_image.py +111 -0
- openstackclient/tests/unit/network/test_common.py +9 -13
- openstackclient/tests/unit/network/v2/taas/__init__.py +0 -0
- openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py +276 -0
- openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py +288 -0
- openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py +271 -0
- openstackclient/tests/unit/network/v2/test_address_group.py +19 -22
- openstackclient/tests/unit/network/v2/test_address_scope.py +10 -15
- openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +38 -49
- openstackclient/tests/unit/network/v2/test_floating_ip_network.py +21 -27
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +21 -18
- openstackclient/tests/unit/network/v2/test_ip_availability.py +6 -8
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +6 -15
- openstackclient/tests/unit/network/v2/test_local_ip.py +12 -23
- openstackclient/tests/unit/network/v2/test_local_ip_association.py +13 -18
- openstackclient/tests/unit/network/v2/test_ndp_proxy.py +11 -21
- openstackclient/tests/unit/network/v2/test_network.py +41 -37
- openstackclient/tests/unit/network/v2/test_network_agent.py +13 -20
- openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +5 -8
- openstackclient/tests/unit/network/v2/test_network_flavor.py +14 -26
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +14 -17
- openstackclient/tests/unit/network/v2/test_network_meter.py +7 -17
- openstackclient/tests/unit/network/v2/test_network_meter_rule.py +10 -20
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +7 -13
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +44 -54
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +2 -7
- openstackclient/tests/unit/network/v2/test_network_rbac.py +21 -36
- openstackclient/tests/unit/network/v2/test_network_segment.py +13 -29
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +20 -19
- openstackclient/tests/unit/network/v2/test_network_service_provider.py +1 -4
- openstackclient/tests/unit/network/v2/test_network_trunk.py +52 -47
- openstackclient/tests/unit/network/v2/test_port.py +75 -86
- openstackclient/tests/unit/network/v2/test_router.py +104 -126
- openstackclient/tests/unit/network/v2/test_security_group_network.py +19 -26
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +17 -18
- openstackclient/tests/unit/network/v2/test_subnet.py +35 -46
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +21 -33
- openstackclient/tests/unit/volume/test_find_resource.py +4 -13
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +3 -1
- openstackclient/tests/unit/volume/v3/test_volume.py +4 -0
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +9 -0
- openstackclient/volume/client.py +7 -17
- openstackclient/volume/v2/backup_record.py +1 -1
- openstackclient/volume/v2/consistency_group.py +1 -1
- openstackclient/volume/v2/consistency_group_snapshot.py +1 -1
- openstackclient/volume/v2/qos_specs.py +1 -1
- openstackclient/volume/v2/service.py +1 -1
- openstackclient/volume/v2/volume.py +2 -2
- openstackclient/volume/v2/volume_backend.py +1 -1
- openstackclient/volume/v2/volume_backup.py +5 -3
- openstackclient/volume/v2/volume_host.py +1 -2
- openstackclient/volume/v2/volume_snapshot.py +2 -2
- openstackclient/volume/v2/volume_transfer_request.py +1 -1
- openstackclient/volume/v2/volume_type.py +11 -6
- openstackclient/volume/v3/block_storage_cleanup.py +1 -1
- openstackclient/volume/v3/block_storage_cluster.py +1 -1
- openstackclient/volume/v3/block_storage_log_level.py +1 -1
- openstackclient/volume/v3/block_storage_manage.py +1 -1
- openstackclient/volume/v3/block_storage_resource_filter.py +1 -1
- openstackclient/volume/v3/service.py +1 -1
- openstackclient/volume/v3/volume.py +2 -2
- openstackclient/volume/v3/volume_attachment.py +6 -5
- openstackclient/volume/v3/volume_backup.py +18 -3
- openstackclient/volume/v3/volume_group.py +1 -1
- openstackclient/volume/v3/volume_group_snapshot.py +1 -1
- openstackclient/volume/v3/volume_group_type.py +1 -1
- openstackclient/volume/v3/volume_message.py +1 -1
- openstackclient/volume/v3/volume_snapshot.py +2 -2
- openstackclient/volume/v3/volume_transfer_request.py +1 -1
- openstackclient/volume/v3/volume_type.py +15 -9
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/METADATA +15 -13
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/RECORD +224 -213
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/WHEEL +1 -1
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/entry_points.txt +15 -0
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/AUTHORS +10 -0
- python_openstackclient-8.3.0.dist-info/pbr.json +1 -0
- openstackclient/tests/unit/common/test_logs.py +0 -221
- python_openstackclient-8.2.0.dist-info/pbr.json +0 -1
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/LICENSE +0 -0
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/top_level.txt +0 -0
|
@@ -20,11 +20,11 @@ import typing as ty
|
|
|
20
20
|
from cliff import columns as cliff_columns
|
|
21
21
|
from osc_lib.cli import format_columns
|
|
22
22
|
from osc_lib.cli import parseractions
|
|
23
|
-
from osc_lib.command import command
|
|
24
23
|
from osc_lib import exceptions
|
|
25
24
|
from osc_lib import utils
|
|
26
25
|
from osc_lib.utils import tags as _tag
|
|
27
26
|
|
|
27
|
+
from openstackclient import command
|
|
28
28
|
from openstackclient.i18n import _
|
|
29
29
|
from openstackclient.identity import common as identity_common
|
|
30
30
|
from openstackclient.network import common
|
|
@@ -44,7 +44,7 @@ def _update_arguments(obj_list, parsed_args_list, option):
|
|
|
44
44
|
raise exceptions.CommandError(msg)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class AllocationPoolsColumn(cliff_columns.FormattableColumn):
|
|
47
|
+
class AllocationPoolsColumn(cliff_columns.FormattableColumn[ty.Any]):
|
|
48
48
|
def human_readable(self):
|
|
49
49
|
pool_formatted = [
|
|
50
50
|
'{}-{}'.format(pool.get('start', ''), pool.get('end', ''))
|
|
@@ -53,7 +53,7 @@ class AllocationPoolsColumn(cliff_columns.FormattableColumn):
|
|
|
53
53
|
return ','.join(pool_formatted)
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
class HostRoutesColumn(cliff_columns.FormattableColumn):
|
|
56
|
+
class HostRoutesColumn(cliff_columns.FormattableColumn[ty.Any]):
|
|
57
57
|
def human_readable(self):
|
|
58
58
|
# Map the host route keys to match --host-route option.
|
|
59
59
|
return utils.format_list_of_dicts(
|
|
@@ -61,7 +61,7 @@ class HostRoutesColumn(cliff_columns.FormattableColumn):
|
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
class UnsortedListColumn(cliff_columns.FormattableColumn):
|
|
64
|
+
class UnsortedListColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
|
|
65
65
|
# format_columns.ListColumn sorts the output, but for things like
|
|
66
66
|
# DNS server addresses the order matters
|
|
67
67
|
def human_readable(self):
|
|
@@ -493,7 +493,7 @@ class ListSubnet(command.Lister):
|
|
|
493
493
|
metavar='<ip-version>',
|
|
494
494
|
dest='ip_version',
|
|
495
495
|
help=_(
|
|
496
|
-
"List only subnets
|
|
496
|
+
"List only subnets with the specified IP version. "
|
|
497
497
|
"Allowed values for IP version are 4 and 6."
|
|
498
498
|
),
|
|
499
499
|
)
|
|
@@ -501,12 +501,12 @@ class ListSubnet(command.Lister):
|
|
|
501
501
|
dhcp_enable_group.add_argument(
|
|
502
502
|
'--dhcp',
|
|
503
503
|
action='store_true',
|
|
504
|
-
help=_("List subnets which have DHCP enabled"),
|
|
504
|
+
help=_("List only subnets which have DHCP enabled"),
|
|
505
505
|
)
|
|
506
506
|
dhcp_enable_group.add_argument(
|
|
507
507
|
'--no-dhcp',
|
|
508
508
|
action='store_true',
|
|
509
|
-
help=_("List subnets which have DHCP disabled"),
|
|
509
|
+
help=_("List only subnets which have DHCP disabled"),
|
|
510
510
|
)
|
|
511
511
|
parser.add_argument(
|
|
512
512
|
'--service-type',
|
|
@@ -514,7 +514,7 @@ class ListSubnet(command.Lister):
|
|
|
514
514
|
action='append',
|
|
515
515
|
dest='service_types',
|
|
516
516
|
help=_(
|
|
517
|
-
"List only subnets
|
|
517
|
+
"List only subnets with the specified service type, "
|
|
518
518
|
"for example, network:floatingip_agent_gateway. "
|
|
519
519
|
"Must be a valid device owner value for a network port "
|
|
520
520
|
"(repeat option to list multiple service types)."
|
|
@@ -524,8 +524,7 @@ class ListSubnet(command.Lister):
|
|
|
524
524
|
'--project',
|
|
525
525
|
metavar='<project>',
|
|
526
526
|
help=_(
|
|
527
|
-
"List only subnets
|
|
528
|
-
"in output (name or ID)"
|
|
527
|
+
"List only subnets with the specified project (name or ID)"
|
|
529
528
|
),
|
|
530
529
|
)
|
|
531
530
|
identity_common.add_project_domain_option_to_parser(parser)
|
|
@@ -533,26 +532,26 @@ class ListSubnet(command.Lister):
|
|
|
533
532
|
'--network',
|
|
534
533
|
metavar='<network>',
|
|
535
534
|
help=_(
|
|
536
|
-
"List only subnets which belong to
|
|
537
|
-
"
|
|
535
|
+
"List only subnets which belong to the specified network "
|
|
536
|
+
"(name or ID)"
|
|
538
537
|
),
|
|
539
538
|
)
|
|
540
539
|
parser.add_argument(
|
|
541
540
|
'--gateway',
|
|
542
541
|
metavar='<gateway>',
|
|
543
|
-
help=_("List only subnets
|
|
542
|
+
help=_("List only subnets with the specified gateway IP"),
|
|
544
543
|
)
|
|
545
544
|
parser.add_argument(
|
|
546
545
|
'--name',
|
|
547
546
|
metavar='<name>',
|
|
548
|
-
help=_("List only subnets
|
|
547
|
+
help=_("List only subnets with the specified name"),
|
|
549
548
|
)
|
|
550
549
|
parser.add_argument(
|
|
551
550
|
'--subnet-range',
|
|
552
551
|
metavar='<subnet-range>',
|
|
553
552
|
help=_(
|
|
554
|
-
"List only subnets
|
|
555
|
-
"(in CIDR notation)
|
|
553
|
+
"List only subnets with the specified subnet range "
|
|
554
|
+
"(in CIDR notation). "
|
|
556
555
|
"For example, --subnet-range 10.10.0.0/16"
|
|
557
556
|
),
|
|
558
557
|
)
|
|
@@ -560,8 +559,8 @@ class ListSubnet(command.Lister):
|
|
|
560
559
|
'--subnet-pool',
|
|
561
560
|
metavar='<subnet-pool>',
|
|
562
561
|
help=_(
|
|
563
|
-
"List only subnets which belong to
|
|
564
|
-
"
|
|
562
|
+
"List only subnets which belong to the specified subnet pool "
|
|
563
|
+
"(name or ID)"
|
|
565
564
|
),
|
|
566
565
|
)
|
|
567
566
|
_tag.add_tag_filtering_option_to_parser(parser, _('subnets'))
|
|
@@ -17,11 +17,11 @@ import logging
|
|
|
17
17
|
|
|
18
18
|
from osc_lib.cli import format_columns
|
|
19
19
|
from osc_lib.cli import parseractions
|
|
20
|
-
from osc_lib.command import command
|
|
21
20
|
from osc_lib import exceptions
|
|
22
21
|
from osc_lib import utils
|
|
23
22
|
from osc_lib.utils import tags as _tag
|
|
24
23
|
|
|
24
|
+
from openstackclient import command
|
|
25
25
|
from openstackclient.i18n import _
|
|
26
26
|
from openstackclient.identity import common as identity_common
|
|
27
27
|
from openstackclient.network import common
|
|
@@ -278,26 +278,27 @@ class ListSubnetPool(command.Lister):
|
|
|
278
278
|
shared_group.add_argument(
|
|
279
279
|
'--share',
|
|
280
280
|
action='store_true',
|
|
281
|
-
help=_("List subnet pools shared between projects"),
|
|
281
|
+
help=_("List only subnet pools shared between projects"),
|
|
282
282
|
)
|
|
283
283
|
shared_group.add_argument(
|
|
284
284
|
'--no-share',
|
|
285
285
|
action='store_true',
|
|
286
|
-
help=_("List subnet pools not shared between projects"),
|
|
286
|
+
help=_("List only subnet pools not shared between projects"),
|
|
287
287
|
)
|
|
288
288
|
default_group = parser.add_mutually_exclusive_group()
|
|
289
289
|
default_group.add_argument(
|
|
290
290
|
'--default',
|
|
291
291
|
action='store_true',
|
|
292
292
|
help=_(
|
|
293
|
-
"List subnet pools used as the default external
|
|
293
|
+
"List only subnet pools used as the default external "
|
|
294
|
+
"subnet pool"
|
|
294
295
|
),
|
|
295
296
|
)
|
|
296
297
|
default_group.add_argument(
|
|
297
298
|
'--no-default',
|
|
298
299
|
action='store_true',
|
|
299
300
|
help=_(
|
|
300
|
-
"List subnet pools not used as the default external "
|
|
301
|
+
"List only subnet pools not used as the default external "
|
|
301
302
|
"subnet pool"
|
|
302
303
|
),
|
|
303
304
|
)
|
|
@@ -305,21 +306,22 @@ class ListSubnetPool(command.Lister):
|
|
|
305
306
|
'--project',
|
|
306
307
|
metavar='<project>',
|
|
307
308
|
help=_(
|
|
308
|
-
"List subnet pools
|
|
309
|
+
"List only subnet pools with the specified project "
|
|
310
|
+
"(name or ID)"
|
|
309
311
|
),
|
|
310
312
|
)
|
|
311
313
|
identity_common.add_project_domain_option_to_parser(parser)
|
|
312
314
|
parser.add_argument(
|
|
313
315
|
'--name',
|
|
314
316
|
metavar='<name>',
|
|
315
|
-
help=_("List only subnet pools
|
|
317
|
+
help=_("List only subnet pools with the specified name"),
|
|
316
318
|
)
|
|
317
319
|
parser.add_argument(
|
|
318
320
|
'--address-scope',
|
|
319
321
|
metavar='<address-scope>',
|
|
320
322
|
help=_(
|
|
321
|
-
"List only subnet pools
|
|
322
|
-
"
|
|
323
|
+
"List only subnet pools with the specified address scope "
|
|
324
|
+
"(name or ID)"
|
|
323
325
|
),
|
|
324
326
|
)
|
|
325
327
|
_tag.add_tag_filtering_option_to_parser(parser, _('subnet pools'))
|
|
File without changes
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# All Rights Reserved 2020
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
4
|
+
# not use this file except in compliance with the License. You may obtain
|
|
5
|
+
# a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
11
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
12
|
+
# License for the specific language governing permissions and limitations
|
|
13
|
+
# under the License.
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
|
|
17
|
+
from osc_lib.cli import format_columns
|
|
18
|
+
from osc_lib.cli import identity as identity_utils
|
|
19
|
+
from osc_lib import exceptions
|
|
20
|
+
from osc_lib import utils as osc_utils
|
|
21
|
+
from osc_lib.utils import columns as column_util
|
|
22
|
+
|
|
23
|
+
from openstackclient import command
|
|
24
|
+
from openstackclient.i18n import _
|
|
25
|
+
from openstackclient.identity import common
|
|
26
|
+
from openstackclient.network.v2.taas import tap_service
|
|
27
|
+
|
|
28
|
+
LOG = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
TAP_FLOW = 'tap_flow'
|
|
31
|
+
TAP_FLOWS = f'{TAP_FLOW}s'
|
|
32
|
+
|
|
33
|
+
_attr_map = [
|
|
34
|
+
('id', 'ID', column_util.LIST_BOTH),
|
|
35
|
+
('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
|
|
36
|
+
('name', 'Name', column_util.LIST_BOTH),
|
|
37
|
+
('status', 'Status', column_util.LIST_BOTH),
|
|
38
|
+
('source_port', 'source_port', column_util.LIST_BOTH),
|
|
39
|
+
('tap_service_id', 'tap_service_id', column_util.LIST_BOTH),
|
|
40
|
+
('direction', 'Direction', column_util.LIST_BOTH),
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
_formatters = {
|
|
44
|
+
'vlan_filter': format_columns.ListColumn,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _add_updatable_args(parser):
|
|
49
|
+
parser.add_argument('--name', help=_('Name of the tap flow.'))
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
'--description', help=_('Description of the tap flow.')
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class CreateTapFlow(command.ShowOne):
|
|
56
|
+
_description = _("Create a new tap flow.")
|
|
57
|
+
|
|
58
|
+
def get_parser(self, prog_name):
|
|
59
|
+
parser = super().get_parser(prog_name)
|
|
60
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
61
|
+
_add_updatable_args(parser)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
'--port',
|
|
64
|
+
required=True,
|
|
65
|
+
metavar="SOURCE_PORT",
|
|
66
|
+
help=_('Source port (name or ID) to monitor.'),
|
|
67
|
+
)
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
'--tap-service',
|
|
70
|
+
required=True,
|
|
71
|
+
metavar="TAP_SERVICE",
|
|
72
|
+
help=_(
|
|
73
|
+
'Tap service (name or ID) to associate with this tap flow.'
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
'--direction',
|
|
78
|
+
required=True,
|
|
79
|
+
metavar="DIRECTION",
|
|
80
|
+
choices=['IN', 'OUT', 'BOTH'],
|
|
81
|
+
type=lambda s: s.upper(),
|
|
82
|
+
help=_(
|
|
83
|
+
'Direction of the Tap flow. Valid options are: '
|
|
84
|
+
'IN, OUT and BOTH'
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
'--vlan-filter',
|
|
89
|
+
required=False,
|
|
90
|
+
metavar="VLAN_FILTER",
|
|
91
|
+
help=_('VLAN IDs to mirror in the form of range string.'),
|
|
92
|
+
)
|
|
93
|
+
return parser
|
|
94
|
+
|
|
95
|
+
def take_action(self, parsed_args):
|
|
96
|
+
client = self.app.client_manager.network
|
|
97
|
+
attrs = {}
|
|
98
|
+
if parsed_args.name is not None:
|
|
99
|
+
attrs['name'] = parsed_args.name
|
|
100
|
+
if parsed_args.description is not None:
|
|
101
|
+
attrs['description'] = parsed_args.description
|
|
102
|
+
if parsed_args.port is not None:
|
|
103
|
+
source_port = client.find_port(
|
|
104
|
+
parsed_args.port, ignore_missing=False
|
|
105
|
+
).id
|
|
106
|
+
attrs['source_port'] = source_port
|
|
107
|
+
if parsed_args.tap_service is not None:
|
|
108
|
+
tap_service_id = client.find_tap_service(
|
|
109
|
+
parsed_args.tap_service, ignore_missing=False
|
|
110
|
+
).id
|
|
111
|
+
attrs['tap_service_id'] = tap_service_id
|
|
112
|
+
if parsed_args.direction is not None:
|
|
113
|
+
attrs['direction'] = parsed_args.direction
|
|
114
|
+
if parsed_args.vlan_filter is not None:
|
|
115
|
+
attrs['vlan_filter'] = parsed_args.vlan_filter
|
|
116
|
+
if 'project' in parsed_args and parsed_args.project is not None:
|
|
117
|
+
attrs['project_id'] = common.find_project(
|
|
118
|
+
self.app.client_manager.identity,
|
|
119
|
+
parsed_args.project,
|
|
120
|
+
parsed_args.project_domain,
|
|
121
|
+
).id
|
|
122
|
+
obj = client.create_tap_flow(**attrs)
|
|
123
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
124
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
125
|
+
return display_columns, data
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class ListTapFlow(command.Lister):
|
|
129
|
+
_description = _("List tap flows.")
|
|
130
|
+
|
|
131
|
+
def get_parser(self, prog_name):
|
|
132
|
+
parser = super().get_parser(prog_name)
|
|
133
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
134
|
+
|
|
135
|
+
return parser
|
|
136
|
+
|
|
137
|
+
def take_action(self, parsed_args):
|
|
138
|
+
client = self.app.client_manager.network
|
|
139
|
+
params = {}
|
|
140
|
+
if parsed_args.project is not None:
|
|
141
|
+
params['project_id'] = common.find_project(
|
|
142
|
+
self.app.client_manager.identity,
|
|
143
|
+
parsed_args.project,
|
|
144
|
+
parsed_args.project_domain,
|
|
145
|
+
).id
|
|
146
|
+
objs = client.tap_flows(retrieve_all=True, params=params)
|
|
147
|
+
headers, columns = column_util.get_column_definitions(
|
|
148
|
+
_attr_map, long_listing=True
|
|
149
|
+
)
|
|
150
|
+
return (
|
|
151
|
+
headers,
|
|
152
|
+
(
|
|
153
|
+
osc_utils.get_dict_properties(
|
|
154
|
+
s, columns, formatters=_formatters
|
|
155
|
+
)
|
|
156
|
+
for s in objs
|
|
157
|
+
),
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class ShowTapFlow(command.ShowOne):
|
|
162
|
+
_description = _("Show tap flow details.")
|
|
163
|
+
|
|
164
|
+
def get_parser(self, prog_name):
|
|
165
|
+
parser = super().get_parser(prog_name)
|
|
166
|
+
parser.add_argument(
|
|
167
|
+
TAP_FLOW,
|
|
168
|
+
metavar=f"<{TAP_FLOW}>",
|
|
169
|
+
help=_("Tap flow to display (name or ID)."),
|
|
170
|
+
)
|
|
171
|
+
return parser
|
|
172
|
+
|
|
173
|
+
def take_action(self, parsed_args):
|
|
174
|
+
client = self.app.client_manager.network
|
|
175
|
+
id = client.find_tap_flow(
|
|
176
|
+
parsed_args.tap_flow, ignore_missing=False
|
|
177
|
+
).id
|
|
178
|
+
obj = client.get_tap_flow(id)
|
|
179
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
180
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
181
|
+
return display_columns, data
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class DeleteTapFlow(command.Command):
|
|
185
|
+
_description = _("Delete a tap flow.")
|
|
186
|
+
|
|
187
|
+
def get_parser(self, prog_name):
|
|
188
|
+
parser = super().get_parser(prog_name)
|
|
189
|
+
parser.add_argument(
|
|
190
|
+
TAP_FLOW,
|
|
191
|
+
metavar=f"<{TAP_FLOW}>",
|
|
192
|
+
nargs="+",
|
|
193
|
+
help=_("Tap flow to delete (name or ID)."),
|
|
194
|
+
)
|
|
195
|
+
return parser
|
|
196
|
+
|
|
197
|
+
def take_action(self, parsed_args):
|
|
198
|
+
client = self.app.client_manager.network
|
|
199
|
+
fails = 0
|
|
200
|
+
for id_or_name in parsed_args.tap_flow:
|
|
201
|
+
try:
|
|
202
|
+
id = client.find_tap_flow(id_or_name, ignore_missing=False).id
|
|
203
|
+
client.delete_tap_flow(id)
|
|
204
|
+
except Exception as e:
|
|
205
|
+
fails += 1
|
|
206
|
+
LOG.error(
|
|
207
|
+
"Failed to delete tap flow with name or ID "
|
|
208
|
+
"'%(id_or_name)s': %(e)s",
|
|
209
|
+
{'id_or_name': id_or_name, 'e': e},
|
|
210
|
+
)
|
|
211
|
+
if fails > 0:
|
|
212
|
+
msg = _("Failed to delete %(fails)s of %(total)s tap flow.") % {
|
|
213
|
+
'fails': fails,
|
|
214
|
+
'total': len(parsed_args.tap_flow),
|
|
215
|
+
}
|
|
216
|
+
raise exceptions.CommandError(msg)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class UpdateTapFlow(command.ShowOne):
|
|
220
|
+
_description = _("Update a tap flow.")
|
|
221
|
+
|
|
222
|
+
def get_parser(self, prog_name):
|
|
223
|
+
parser = super().get_parser(prog_name)
|
|
224
|
+
parser.add_argument(
|
|
225
|
+
TAP_FLOW,
|
|
226
|
+
metavar=f"<{TAP_FLOW}>",
|
|
227
|
+
help=_("Tap flow to modify (name or ID)."),
|
|
228
|
+
)
|
|
229
|
+
_add_updatable_args(parser)
|
|
230
|
+
return parser
|
|
231
|
+
|
|
232
|
+
def take_action(self, parsed_args):
|
|
233
|
+
client = self.app.client_manager.network
|
|
234
|
+
original_t_f = client.find_tap_flow(
|
|
235
|
+
parsed_args.tap_flow, ignore_missing=False
|
|
236
|
+
).id
|
|
237
|
+
attrs = {}
|
|
238
|
+
if parsed_args.name is not None:
|
|
239
|
+
attrs['name'] = parsed_args.name
|
|
240
|
+
if parsed_args.description is not None:
|
|
241
|
+
attrs['description'] = parsed_args.description
|
|
242
|
+
obj = client.update_tap_flow(original_t_f, **attrs)
|
|
243
|
+
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
|
244
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
245
|
+
return display_columns, data
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
2
|
+
# not use this file except in compliance with the License. You may obtain
|
|
3
|
+
# a copy of the License at
|
|
4
|
+
#
|
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
#
|
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
9
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
10
|
+
# License for the specific language governing permissions and limitations
|
|
11
|
+
# under the License.
|
|
12
|
+
|
|
13
|
+
import logging
|
|
14
|
+
|
|
15
|
+
from osc_lib.cli import identity as identity_utils
|
|
16
|
+
from osc_lib import exceptions
|
|
17
|
+
from osc_lib import utils as osc_utils
|
|
18
|
+
from osc_lib.utils import columns as column_util
|
|
19
|
+
|
|
20
|
+
from openstackclient import command
|
|
21
|
+
from openstackclient.i18n import _
|
|
22
|
+
from openstackclient.identity import common
|
|
23
|
+
from openstackclient.network.v2 import port as osc_port
|
|
24
|
+
from openstackclient.network.v2.taas import tap_service
|
|
25
|
+
|
|
26
|
+
LOG = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
TAP_MIRROR = 'tap_mirror'
|
|
29
|
+
TAP_MIRRORS = f'{TAP_MIRROR}s'
|
|
30
|
+
|
|
31
|
+
_attr_map = [
|
|
32
|
+
('id', 'ID', column_util.LIST_BOTH),
|
|
33
|
+
('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
|
|
34
|
+
('name', 'Name', column_util.LIST_BOTH),
|
|
35
|
+
('port_id', 'Port', column_util.LIST_BOTH),
|
|
36
|
+
('directions', 'Directions', column_util.LIST_LONG_ONLY),
|
|
37
|
+
('remote_ip', 'Remote IP', column_util.LIST_BOTH),
|
|
38
|
+
('mirror_type', 'Mirror Type', column_util.LIST_LONG_ONLY),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _get_columns(item):
|
|
43
|
+
column_map: dict[str, str] = {}
|
|
44
|
+
hidden_columns = ['location', 'tenant_id']
|
|
45
|
+
return osc_utils.get_osc_show_columns_for_sdk_resource(
|
|
46
|
+
item, column_map, hidden_columns
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class CreateTapMirror(command.ShowOne):
|
|
51
|
+
_description = _("Create a new tap mirror.")
|
|
52
|
+
|
|
53
|
+
def get_parser(self, prog_name):
|
|
54
|
+
parser = super().get_parser(prog_name)
|
|
55
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
56
|
+
tap_service._add_updatable_args(parser)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
'--port',
|
|
59
|
+
dest='port_id',
|
|
60
|
+
required=True,
|
|
61
|
+
metavar="PORT",
|
|
62
|
+
help=_('Port (name or ID) to which the Tap Mirror is connected.'),
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
'--directions',
|
|
66
|
+
dest='directions',
|
|
67
|
+
action=osc_port.JSONKeyValueAction,
|
|
68
|
+
required=True,
|
|
69
|
+
help=_(
|
|
70
|
+
'Dictionary of direction and tunnel_id. Valid directions are: '
|
|
71
|
+
'IN and OUT.'
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
'--remote-ip',
|
|
76
|
+
dest='remote_ip',
|
|
77
|
+
required=True,
|
|
78
|
+
help=_(
|
|
79
|
+
'Remote IP address for the tap mirror (remote end of the '
|
|
80
|
+
'GRE or ERSPAN v1 tunnel).'
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
'--mirror-type',
|
|
85
|
+
dest='mirror_type',
|
|
86
|
+
required=True,
|
|
87
|
+
help=_('Mirror type. Valid values are: gre and erspanv1.'),
|
|
88
|
+
)
|
|
89
|
+
return parser
|
|
90
|
+
|
|
91
|
+
def take_action(self, parsed_args):
|
|
92
|
+
client = self.app.client_manager.network
|
|
93
|
+
attrs = {}
|
|
94
|
+
if parsed_args.name is not None:
|
|
95
|
+
attrs['name'] = parsed_args.name
|
|
96
|
+
if parsed_args.description is not None:
|
|
97
|
+
attrs['description'] = parsed_args.description
|
|
98
|
+
if parsed_args.port_id is not None:
|
|
99
|
+
port_id = client.find_port(
|
|
100
|
+
parsed_args.port_id, ignore_missing=False
|
|
101
|
+
).id
|
|
102
|
+
attrs['port_id'] = port_id
|
|
103
|
+
if parsed_args.directions is not None:
|
|
104
|
+
attrs['directions'] = parsed_args.directions
|
|
105
|
+
if parsed_args.remote_ip is not None:
|
|
106
|
+
attrs['remote_ip'] = parsed_args.remote_ip
|
|
107
|
+
if parsed_args.mirror_type is not None:
|
|
108
|
+
attrs['mirror_type'] = parsed_args.mirror_type
|
|
109
|
+
if 'project' in parsed_args and parsed_args.project is not None:
|
|
110
|
+
attrs['project_id'] = common.find_project(
|
|
111
|
+
self.app.client_manager.identity,
|
|
112
|
+
parsed_args.project,
|
|
113
|
+
parsed_args.project_domain,
|
|
114
|
+
).id
|
|
115
|
+
obj = client.create_tap_mirror(**attrs)
|
|
116
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
117
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
118
|
+
return display_columns, data
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ListTapMirror(command.Lister):
|
|
122
|
+
_description = _("List tap mirrors.")
|
|
123
|
+
|
|
124
|
+
def get_parser(self, prog_name):
|
|
125
|
+
parser = super().get_parser(prog_name)
|
|
126
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
127
|
+
|
|
128
|
+
return parser
|
|
129
|
+
|
|
130
|
+
def take_action(self, parsed_args):
|
|
131
|
+
client = self.app.client_manager.network
|
|
132
|
+
params = {}
|
|
133
|
+
if parsed_args.project is not None:
|
|
134
|
+
params['project_id'] = common.find_project(
|
|
135
|
+
self.app.client_manager.identity,
|
|
136
|
+
parsed_args.project,
|
|
137
|
+
parsed_args.project_domain,
|
|
138
|
+
).id
|
|
139
|
+
objs = client.tap_mirrors(retrieve_all=True, params=params)
|
|
140
|
+
headers, columns = column_util.get_column_definitions(
|
|
141
|
+
_attr_map, long_listing=True
|
|
142
|
+
)
|
|
143
|
+
return (
|
|
144
|
+
headers,
|
|
145
|
+
(osc_utils.get_dict_properties(s, columns) for s in objs),
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class ShowTapMirror(command.ShowOne):
|
|
150
|
+
_description = _("Show tap mirror details.")
|
|
151
|
+
|
|
152
|
+
def get_parser(self, prog_name):
|
|
153
|
+
parser = super().get_parser(prog_name)
|
|
154
|
+
parser.add_argument(
|
|
155
|
+
TAP_MIRROR,
|
|
156
|
+
metavar=f"<{TAP_MIRROR}>",
|
|
157
|
+
help=_("Tap mirror to display (name or ID)."),
|
|
158
|
+
)
|
|
159
|
+
return parser
|
|
160
|
+
|
|
161
|
+
def take_action(self, parsed_args):
|
|
162
|
+
client = self.app.client_manager.network
|
|
163
|
+
id = client.find_tap_mirror(
|
|
164
|
+
parsed_args.tap_mirror, ignore_missing=False
|
|
165
|
+
).id
|
|
166
|
+
obj = client.get_tap_mirror(id)
|
|
167
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
168
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
169
|
+
return display_columns, data
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class DeleteTapMirror(command.Command):
|
|
173
|
+
_description = _("Delete a tap mirror.")
|
|
174
|
+
|
|
175
|
+
def get_parser(self, prog_name):
|
|
176
|
+
parser = super().get_parser(prog_name)
|
|
177
|
+
parser.add_argument(
|
|
178
|
+
TAP_MIRROR,
|
|
179
|
+
metavar=f"<{TAP_MIRROR}>",
|
|
180
|
+
nargs="+",
|
|
181
|
+
help=_("Tap mirror to delete (name or ID)."),
|
|
182
|
+
)
|
|
183
|
+
return parser
|
|
184
|
+
|
|
185
|
+
def take_action(self, parsed_args):
|
|
186
|
+
client = self.app.client_manager.network
|
|
187
|
+
fails = 0
|
|
188
|
+
for id_or_name in parsed_args.tap_mirror:
|
|
189
|
+
try:
|
|
190
|
+
id = client.find_tap_mirror(
|
|
191
|
+
id_or_name, ignore_missing=False
|
|
192
|
+
).id
|
|
193
|
+
|
|
194
|
+
client.delete_tap_mirror(id)
|
|
195
|
+
LOG.warning("Tap Mirror %(id)s deleted", {'id': id})
|
|
196
|
+
except Exception as e:
|
|
197
|
+
fails += 1
|
|
198
|
+
LOG.error(
|
|
199
|
+
"Failed to delete Tap Mirror with name or ID "
|
|
200
|
+
"'%(id_or_name)s': %(e)s",
|
|
201
|
+
{'id_or_name': id_or_name, 'e': e},
|
|
202
|
+
)
|
|
203
|
+
if fails > 0:
|
|
204
|
+
msg = _("Failed to delete %(fails)s of %(total)s Tap Mirror.") % {
|
|
205
|
+
'fails': fails,
|
|
206
|
+
'total': len(parsed_args.tap_mirror),
|
|
207
|
+
}
|
|
208
|
+
raise exceptions.CommandError(msg)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class UpdateTapMirror(command.ShowOne):
|
|
212
|
+
_description = _("Update a tap mirror.")
|
|
213
|
+
|
|
214
|
+
def get_parser(self, prog_name):
|
|
215
|
+
parser = super().get_parser(prog_name)
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
TAP_MIRROR,
|
|
218
|
+
metavar=f"<{TAP_MIRROR}>",
|
|
219
|
+
help=_("Tap mirror to modify (name or ID)."),
|
|
220
|
+
)
|
|
221
|
+
tap_service._add_updatable_args(parser)
|
|
222
|
+
return parser
|
|
223
|
+
|
|
224
|
+
def take_action(self, parsed_args):
|
|
225
|
+
client = self.app.client_manager.network
|
|
226
|
+
original_t_s = client.find_tap_mirror(
|
|
227
|
+
parsed_args.tap_mirror, ignore_missing=False
|
|
228
|
+
).id
|
|
229
|
+
attrs = {}
|
|
230
|
+
if parsed_args.name is not None:
|
|
231
|
+
attrs['name'] = parsed_args.name
|
|
232
|
+
if parsed_args.description is not None:
|
|
233
|
+
attrs['description'] = parsed_args.description
|
|
234
|
+
obj = client.update_tap_mirror(original_t_s, **attrs)
|
|
235
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
236
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
237
|
+
return display_columns, data
|