python-openstackclient 6.3.0__py3-none-any.whl → 6.5.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 +4 -4
- openstackclient/common/pagination.py +82 -0
- openstackclient/compute/v2/flavor.py +2 -16
- openstackclient/compute/v2/hypervisor.py +2 -21
- openstackclient/compute/v2/keypair.py +2 -9
- openstackclient/compute/v2/server.py +220 -131
- openstackclient/compute/v2/server_event.py +30 -19
- openstackclient/compute/v2/server_group.py +2 -23
- openstackclient/compute/v2/server_migration.py +2 -22
- openstackclient/compute/v2/usage.py +4 -6
- openstackclient/identity/v3/mapping.py +25 -3
- openstackclient/identity/v3/policy.py +3 -1
- openstackclient/image/v2/cache.py +218 -0
- openstackclient/image/v2/image.py +40 -17
- openstackclient/image/v2/metadef_namespaces.py +25 -21
- openstackclient/image/v2/metadef_objects.py +189 -0
- openstackclient/image/v2/metadef_properties.py +284 -0
- openstackclient/network/utils.py +100 -0
- openstackclient/network/v2/default_security_group_rule.py +418 -0
- openstackclient/network/v2/local_ip_association.py +1 -1
- openstackclient/network/v2/ndp_proxy.py +7 -3
- openstackclient/network/v2/network.py +2 -2
- openstackclient/network/v2/port.py +65 -19
- openstackclient/network/v2/security_group_rule.py +18 -111
- openstackclient/network/v2/subnet.py +1 -0
- openstackclient/object/v1/container.py +2 -12
- openstackclient/object/v1/object.py +2 -11
- openstackclient/tests/functional/base.py +13 -6
- openstackclient/tests/functional/identity/v3/test_role.py +11 -3
- openstackclient/tests/functional/network/v2/common.py +7 -1
- openstackclient/tests/functional/network/v2/test_address_group.py +2 -4
- openstackclient/tests/functional/network/v2/test_address_scope.py +0 -6
- openstackclient/tests/functional/network/v2/test_default_security_group_rule.py +67 -0
- openstackclient/tests/functional/network/v2/test_floating_ip.py +3 -6
- openstackclient/tests/functional/network/v2/test_ip_availability.py +3 -8
- openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py +3 -4
- openstackclient/tests/functional/network/v2/test_local_ip.py +2 -4
- openstackclient/tests/functional/network/v2/test_network.py +18 -17
- openstackclient/tests/functional/network/v2/test_network_agent.py +24 -21
- openstackclient/tests/functional/network/v2/test_network_flavor.py +0 -6
- openstackclient/tests/functional/network/v2/test_network_flavor_profile.py +0 -6
- openstackclient/tests/functional/network/v2/test_network_meter.py +6 -6
- openstackclient/tests/functional/network/v2/test_network_meter_rule.py +7 -8
- openstackclient/tests/functional/network/v2/test_network_ndp_proxy.py +1 -3
- openstackclient/tests/functional/network/v2/test_network_qos_policy.py +4 -4
- openstackclient/tests/functional/network/v2/test_network_qos_rule.py +16 -20
- openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py +4 -4
- openstackclient/tests/functional/network/v2/test_network_rbac.py +1 -4
- openstackclient/tests/functional/network/v2/test_network_segment.py +7 -12
- openstackclient/tests/functional/network/v2/test_network_segment_range.py +3 -4
- openstackclient/tests/functional/network/v2/test_network_service_provider.py +2 -4
- openstackclient/tests/functional/network/v2/test_network_trunk.py +3 -3
- openstackclient/tests/functional/network/v2/test_port.py +2 -8
- openstackclient/tests/functional/network/v2/test_router.py +0 -6
- openstackclient/tests/functional/network/v2/test_security_group.py +1 -4
- openstackclient/tests/functional/network/v2/test_security_group_rule.py +1 -4
- openstackclient/tests/functional/network/v2/test_subnet.py +4 -22
- openstackclient/tests/functional/network/v2/test_subnet_pool.py +0 -6
- openstackclient/tests/unit/common/test_availability_zone.py +28 -30
- openstackclient/tests/unit/common/test_extension.py +1 -4
- openstackclient/tests/unit/common/test_limits.py +2 -4
- openstackclient/tests/unit/common/test_project_cleanup.py +3 -10
- openstackclient/tests/unit/common/test_quota.py +18 -24
- openstackclient/tests/unit/compute/v2/fakes.py +24 -11
- openstackclient/tests/unit/compute/v2/test_agent.py +1 -1
- openstackclient/tests/unit/compute/v2/test_aggregate.py +62 -72
- openstackclient/tests/unit/compute/v2/test_console.py +18 -30
- openstackclient/tests/unit/compute/v2/test_flavor.py +85 -89
- openstackclient/tests/unit/compute/v2/test_host.py +12 -19
- openstackclient/tests/unit/compute/v2/test_hypervisor.py +23 -25
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +2 -6
- openstackclient/tests/unit/compute/v2/test_keypair.py +25 -39
- openstackclient/tests/unit/compute/v2/test_server.py +316 -365
- openstackclient/tests/unit/compute/v2/test_server_backup.py +5 -17
- openstackclient/tests/unit/compute/v2/test_server_event.py +23 -25
- openstackclient/tests/unit/compute/v2/test_server_group.py +41 -33
- openstackclient/tests/unit/compute/v2/test_server_image.py +6 -18
- openstackclient/tests/unit/compute/v2/test_server_migration.py +45 -45
- openstackclient/tests/unit/compute/v2/test_server_volume.py +15 -31
- openstackclient/tests/unit/compute/v2/test_service.py +51 -56
- openstackclient/tests/unit/compute/v2/test_usage.py +10 -13
- openstackclient/tests/unit/fakes.py +4 -0
- openstackclient/tests/unit/identity/v3/test_mappings.py +9 -4
- openstackclient/tests/unit/identity/v3/test_trust.py +0 -2
- openstackclient/tests/unit/image/v1/fakes.py +2 -1
- openstackclient/tests/unit/image/v1/test_image.py +1 -1
- openstackclient/tests/unit/image/v2/fakes.py +82 -0
- openstackclient/tests/unit/image/v2/test_cache.py +214 -0
- openstackclient/tests/unit/image/v2/test_image.py +62 -4
- openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +5 -19
- openstackclient/tests/unit/image/v2/test_metadef_objects.py +162 -0
- openstackclient/tests/unit/image/v2/test_metadef_properties.py +227 -0
- openstackclient/tests/unit/integ/cli/test_shell.py +0 -2
- openstackclient/tests/unit/network/test_common.py +3 -3
- openstackclient/tests/unit/network/v2/fakes.py +1 -0
- openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +1133 -0
- openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +5 -13
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +1 -9
- openstackclient/tests/unit/network/v2/test_network.py +33 -0
- openstackclient/tests/unit/network/v2/test_network_compute.py +5 -11
- openstackclient/tests/unit/network/v2/test_network_trunk.py +6 -8
- openstackclient/tests/unit/network/v2/test_port.py +83 -38
- openstackclient/tests/unit/network/v2/test_security_group_compute.py +7 -15
- openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +19 -27
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +3 -6
- openstackclient/tests/unit/network/v2/test_subnet.py +92 -0
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +11 -13
- openstackclient/tests/unit/test_shell.py +1 -7
- openstackclient/tests/unit/utils.py +10 -4
- openstackclient/tests/unit/volume/v1/fakes.py +7 -1
- openstackclient/tests/unit/volume/v1/test_qos_specs.py +2 -2
- openstackclient/tests/unit/volume/v1/test_service.py +1 -1
- openstackclient/tests/unit/volume/v1/test_transfer_request.py +2 -2
- openstackclient/tests/unit/volume/v1/test_type.py +2 -4
- openstackclient/tests/unit/volume/v1/test_volume.py +5 -7
- openstackclient/tests/unit/volume/v1/test_volume_backup.py +4 -4
- openstackclient/tests/unit/volume/v2/fakes.py +32 -12
- openstackclient/tests/unit/volume/v2/test_backup_record.py +1 -1
- openstackclient/tests/unit/volume/v2/test_consistency_group.py +4 -6
- openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py +2 -4
- openstackclient/tests/unit/volume/v2/test_qos_specs.py +2 -2
- openstackclient/tests/unit/volume/v2/test_service.py +1 -1
- openstackclient/tests/unit/volume/v2/test_volume.py +78 -16
- openstackclient/tests/unit/volume/v2/test_volume_backend.py +10 -22
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +76 -89
- openstackclient/tests/unit/volume/v2/test_volume_host.py +1 -1
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +5 -7
- openstackclient/tests/unit/volume/v2/test_volume_transfer_request.py +4 -8
- openstackclient/tests/unit/volume/v2/test_volume_type.py +164 -24
- openstackclient/tests/unit/volume/v3/fakes.py +91 -15
- openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py +3 -7
- openstackclient/tests/unit/volume/v3/test_block_storage_cluster.py +11 -31
- openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +6 -16
- openstackclient/tests/unit/volume/v3/test_block_storage_manage.py +219 -157
- openstackclient/tests/unit/volume/v3/test_block_storage_resource_filter.py +32 -23
- openstackclient/tests/unit/volume/v3/test_volume.py +50 -48
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +17 -47
- openstackclient/tests/unit/volume/v3/test_volume_group.py +23 -65
- openstackclient/tests/unit/volume/v3/test_volume_group_snapshot.py +88 -77
- openstackclient/tests/unit/volume/v3/test_volume_group_type.py +14 -42
- openstackclient/tests/unit/volume/v3/test_volume_message.py +10 -28
- openstackclient/volume/v1/volume.py +2 -14
- openstackclient/volume/v2/volume.py +30 -15
- openstackclient/volume/v2/volume_backend.py +10 -18
- openstackclient/volume/v2/volume_backup.py +18 -15
- openstackclient/volume/v2/volume_snapshot.py +2 -12
- openstackclient/volume/v2/volume_type.py +211 -14
- openstackclient/volume/v3/block_storage_manage.py +72 -11
- openstackclient/volume/v3/block_storage_resource_filter.py +33 -11
- openstackclient/volume/v3/volume_attachment.py +2 -14
- openstackclient/volume/v3/volume_group_snapshot.py +27 -27
- openstackclient/volume/v3/volume_message.py +2 -13
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/AUTHORS +11 -0
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/METADATA +6 -5
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/RECORD +160 -151
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/entry_points.txt +23 -5
- python_openstackclient-6.5.0.dist-info/pbr.json +1 -0
- openstackclient/tests/unit/common/test_parseractions.py +0 -233
- python_openstackclient-6.3.0.dist-info/pbr.json +0 -1
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/LICENSE +0 -0
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/top_level.txt +0 -0
|
@@ -55,18 +55,49 @@ _formatters = {
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def _get_columns(item):
|
|
58
|
-
|
|
59
|
-
'
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'
|
|
65
|
-
'
|
|
58
|
+
column_data_mapping = {
|
|
59
|
+
'admin_state_up': 'is_admin_state_up',
|
|
60
|
+
'allowed_address_pairs': 'allowed_address_pairs',
|
|
61
|
+
'binding_host_id': 'binding_host_id',
|
|
62
|
+
'binding_profile': 'binding_profile',
|
|
63
|
+
'binding_vif_details': 'binding_vif_details',
|
|
64
|
+
'binding_vif_type': 'binding_vif_type',
|
|
65
|
+
'binding_vnic_type': 'binding_vnic_type',
|
|
66
|
+
'created_at': 'created_at',
|
|
67
|
+
'data_plane_status': 'data_plane_status',
|
|
68
|
+
'description': 'description',
|
|
69
|
+
'device_id': 'device_id',
|
|
70
|
+
'device_owner': 'device_owner',
|
|
71
|
+
'device_profile': 'device_profile',
|
|
72
|
+
'dns_assignment': 'dns_assignment',
|
|
73
|
+
'dns_domain': 'dns_domain',
|
|
74
|
+
'dns_name': 'dns_name',
|
|
75
|
+
'extra_dhcp_opts': 'extra_dhcp_opts',
|
|
76
|
+
'fixed_ips': 'fixed_ips',
|
|
77
|
+
'hardware_offload_type': 'hardware_offload_type',
|
|
78
|
+
'hints': 'hints',
|
|
79
|
+
'id': 'id',
|
|
80
|
+
'ip_allocation': 'ip_allocation',
|
|
81
|
+
'mac_address': 'mac_address',
|
|
82
|
+
'name': 'name',
|
|
83
|
+
'network_id': 'network_id',
|
|
84
|
+
'numa_affinity_policy': 'numa_affinity_policy',
|
|
85
|
+
'port_security_enabled': 'is_port_security_enabled',
|
|
86
|
+
'project_id': 'project_id',
|
|
87
|
+
'propagate_uplink_status': 'propagate_uplink_status',
|
|
88
|
+
'resource_request': 'resource_request',
|
|
89
|
+
'revision_number': 'revision_number',
|
|
90
|
+
'qos_network_policy_id': 'qos_network_policy_id',
|
|
91
|
+
'qos_policy_id': 'qos_policy_id',
|
|
92
|
+
'security_group_ids': 'security_group_ids',
|
|
93
|
+
'status': 'status',
|
|
94
|
+
'tags': 'tags',
|
|
95
|
+
'trunk_details': 'trunk_details',
|
|
96
|
+
'updated_at': 'updated_at',
|
|
66
97
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
98
|
+
return (
|
|
99
|
+
tuple(column_data_mapping.keys()),
|
|
100
|
+
tuple(column_data_mapping.values()),
|
|
70
101
|
)
|
|
71
102
|
|
|
72
103
|
|
|
@@ -94,7 +125,7 @@ class JSONKeyValueAction(argparse.Action):
|
|
|
94
125
|
"%(option)s, but encountered JSON parsing error: "
|
|
95
126
|
"%(error)s"
|
|
96
127
|
) % {"option": option_string, "error": e}
|
|
97
|
-
raise argparse.
|
|
128
|
+
raise argparse.ArgumentError(self, msg)
|
|
98
129
|
|
|
99
130
|
|
|
100
131
|
def _get_attrs(client_manager, parsed_args):
|
|
@@ -182,6 +213,12 @@ def _get_attrs(client_manager, parsed_args):
|
|
|
182
213
|
if 'device_profile' in parsed_args and parsed_args.device_profile:
|
|
183
214
|
attrs['device_profile'] = parsed_args.device_profile
|
|
184
215
|
|
|
216
|
+
if (
|
|
217
|
+
'hardware_offload_type' in parsed_args
|
|
218
|
+
and parsed_args.hardware_offload_type
|
|
219
|
+
):
|
|
220
|
+
attrs['hardware_offload_type'] = parsed_args.hardware_offload_type
|
|
221
|
+
|
|
185
222
|
return attrs
|
|
186
223
|
|
|
187
224
|
|
|
@@ -379,7 +416,7 @@ def _validate_port_hints(hints):
|
|
|
379
416
|
{'openvswitch': {'other_config': {'tx-steering': 'hash'}}},
|
|
380
417
|
):
|
|
381
418
|
msg = _("Invalid value to --hints, see --help for valid values.")
|
|
382
|
-
raise
|
|
419
|
+
raise exceptions.CommandError(msg)
|
|
383
420
|
|
|
384
421
|
|
|
385
422
|
# When we have multiple hints, we'll need to refactor this to expand aliases
|
|
@@ -530,6 +567,15 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
|
530
567
|
metavar='<device-profile>',
|
|
531
568
|
help=_('Cyborg port device profile'),
|
|
532
569
|
)
|
|
570
|
+
parser.add_argument(
|
|
571
|
+
'--hardware-offload-type',
|
|
572
|
+
metavar='<hardware-offload-type>',
|
|
573
|
+
dest='hardware_offload_type',
|
|
574
|
+
help=_(
|
|
575
|
+
'Hardware offload type this port will request when '
|
|
576
|
+
'attached to the network backend'
|
|
577
|
+
),
|
|
578
|
+
)
|
|
533
579
|
_tag.add_tag_option_to_parser_for_create(parser, _('port'))
|
|
534
580
|
return parser
|
|
535
581
|
|
|
@@ -813,7 +859,7 @@ class ListPort(command.Lister):
|
|
|
813
859
|
self.app.client_manager, parsed_args
|
|
814
860
|
)
|
|
815
861
|
if parsed_args.security_groups:
|
|
816
|
-
filters['
|
|
862
|
+
filters['security_group_ids'] = parsed_args.security_groups
|
|
817
863
|
|
|
818
864
|
_tag.get_tag_filtering_args(parsed_args, filters)
|
|
819
865
|
|
|
@@ -1133,10 +1179,6 @@ class UnsetPort(common.NeutronUnsetCommandWithExtraArgs):
|
|
|
1133
1179
|
"or ID) (repeat option to unset multiple security groups)"
|
|
1134
1180
|
),
|
|
1135
1181
|
)
|
|
1136
|
-
|
|
1137
|
-
parser.add_argument(
|
|
1138
|
-
'port', metavar="<port>", help=_("Port to modify (name or ID)")
|
|
1139
|
-
)
|
|
1140
1182
|
parser.add_argument(
|
|
1141
1183
|
'--allowed-address',
|
|
1142
1184
|
metavar='ip-address=<ip-address>[,mac-address=<mac-address>]',
|
|
@@ -1179,8 +1221,12 @@ class UnsetPort(common.NeutronUnsetCommandWithExtraArgs):
|
|
|
1179
1221
|
default=False,
|
|
1180
1222
|
help=_("Clear hints for the port."),
|
|
1181
1223
|
)
|
|
1182
|
-
|
|
1183
1224
|
_tag.add_tag_option_to_parser_for_unset(parser, _('port'))
|
|
1225
|
+
parser.add_argument(
|
|
1226
|
+
'port',
|
|
1227
|
+
metavar="<port>",
|
|
1228
|
+
help=_("Port to modify (name or ID)"),
|
|
1229
|
+
)
|
|
1184
1230
|
|
|
1185
1231
|
return parser
|
|
1186
1232
|
|
|
@@ -28,48 +28,6 @@ from openstackclient.network import utils as network_utils
|
|
|
28
28
|
LOG = logging.getLogger(__name__)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def _format_security_group_rule_show(obj):
|
|
32
|
-
data = network_utils.transform_compute_security_group_rule(obj)
|
|
33
|
-
return zip(*sorted(data.items()))
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def _format_network_port_range(rule):
|
|
37
|
-
# Display port range or ICMP type and code. For example:
|
|
38
|
-
# - ICMP type: 'type=3'
|
|
39
|
-
# - ICMP type and code: 'type=3:code=0'
|
|
40
|
-
# - ICMP code: Not supported
|
|
41
|
-
# - Matching port range: '443:443'
|
|
42
|
-
# - Different port range: '22:24'
|
|
43
|
-
# - Single port: '80:80'
|
|
44
|
-
# - No port range: ''
|
|
45
|
-
port_range = ''
|
|
46
|
-
if _is_icmp_protocol(rule['protocol']):
|
|
47
|
-
if rule['port_range_min']:
|
|
48
|
-
port_range += 'type=' + str(rule['port_range_min'])
|
|
49
|
-
if rule['port_range_max']:
|
|
50
|
-
port_range += ':code=' + str(rule['port_range_max'])
|
|
51
|
-
elif rule['port_range_min'] or rule['port_range_max']:
|
|
52
|
-
port_range_min = str(rule['port_range_min'])
|
|
53
|
-
port_range_max = str(rule['port_range_max'])
|
|
54
|
-
if rule['port_range_min'] is None:
|
|
55
|
-
port_range_min = port_range_max
|
|
56
|
-
if rule['port_range_max'] is None:
|
|
57
|
-
port_range_max = port_range_min
|
|
58
|
-
port_range = port_range_min + ':' + port_range_max
|
|
59
|
-
return port_range
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def _format_remote_ip_prefix(rule):
|
|
63
|
-
remote_ip_prefix = rule['remote_ip_prefix']
|
|
64
|
-
if remote_ip_prefix is None:
|
|
65
|
-
ethertype = rule['ether_type']
|
|
66
|
-
if ethertype == 'IPv4':
|
|
67
|
-
remote_ip_prefix = '0.0.0.0/0'
|
|
68
|
-
elif ethertype == 'IPv6':
|
|
69
|
-
remote_ip_prefix = '::/0'
|
|
70
|
-
return remote_ip_prefix
|
|
71
|
-
|
|
72
|
-
|
|
73
31
|
def _get_columns(item):
|
|
74
32
|
column_map = {}
|
|
75
33
|
hidden_columns = ['location', 'tenant_id']
|
|
@@ -78,29 +36,6 @@ def _get_columns(item):
|
|
|
78
36
|
)
|
|
79
37
|
|
|
80
38
|
|
|
81
|
-
def _convert_to_lowercase(string):
|
|
82
|
-
return string.lower()
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def _convert_ipvx_case(string):
|
|
86
|
-
if string.lower() == 'ipv4':
|
|
87
|
-
return 'IPv4'
|
|
88
|
-
if string.lower() == 'ipv6':
|
|
89
|
-
return 'IPv6'
|
|
90
|
-
return string
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def _is_icmp_protocol(protocol):
|
|
94
|
-
# NOTE(rtheis): Neutron has deprecated protocol icmpv6.
|
|
95
|
-
# However, while the OSC CLI doesn't document the protocol,
|
|
96
|
-
# the code must still handle it. In addition, handle both
|
|
97
|
-
# protocol names and numbers.
|
|
98
|
-
if protocol in ['icmp', 'icmpv6', 'ipv6-icmp', '1', '58']:
|
|
99
|
-
return True
|
|
100
|
-
else:
|
|
101
|
-
return False
|
|
102
|
-
|
|
103
|
-
|
|
104
39
|
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
|
105
40
|
# OSC minimum requirements include SDK 1.0.
|
|
106
41
|
class CreateSecurityGroupRule(
|
|
@@ -188,7 +123,7 @@ class CreateSecurityGroupRule(
|
|
|
188
123
|
protocol_group.add_argument(
|
|
189
124
|
'--protocol',
|
|
190
125
|
metavar='<protocol>',
|
|
191
|
-
type=
|
|
126
|
+
type=network_utils.convert_to_lowercase,
|
|
192
127
|
help=protocol_help,
|
|
193
128
|
**proto_choices
|
|
194
129
|
)
|
|
@@ -196,7 +131,7 @@ class CreateSecurityGroupRule(
|
|
|
196
131
|
protocol_group.add_argument(
|
|
197
132
|
'--proto',
|
|
198
133
|
metavar='<proto>',
|
|
199
|
-
type=
|
|
134
|
+
type=network_utils.convert_to_lowercase,
|
|
200
135
|
help=argparse.SUPPRESS,
|
|
201
136
|
**proto_choices
|
|
202
137
|
)
|
|
@@ -246,7 +181,7 @@ class CreateSecurityGroupRule(
|
|
|
246
181
|
'--ethertype',
|
|
247
182
|
metavar='<ethertype>',
|
|
248
183
|
choices=['IPv4', 'IPv6'],
|
|
249
|
-
type=
|
|
184
|
+
type=network_utils.convert_ipvx_case,
|
|
250
185
|
help=self.enhance_help_neutron(
|
|
251
186
|
_(
|
|
252
187
|
"Ethertype of network traffic "
|
|
@@ -264,38 +199,6 @@ class CreateSecurityGroupRule(
|
|
|
264
199
|
)
|
|
265
200
|
return parser
|
|
266
201
|
|
|
267
|
-
def _get_protocol(self, parsed_args, default_protocol='any'):
|
|
268
|
-
protocol = default_protocol
|
|
269
|
-
if parsed_args.protocol is not None:
|
|
270
|
-
protocol = parsed_args.protocol
|
|
271
|
-
if parsed_args.proto is not None:
|
|
272
|
-
protocol = parsed_args.proto
|
|
273
|
-
if protocol == 'any':
|
|
274
|
-
protocol = None
|
|
275
|
-
return protocol
|
|
276
|
-
|
|
277
|
-
def _get_ethertype(self, parsed_args, protocol):
|
|
278
|
-
ethertype = 'IPv4'
|
|
279
|
-
if parsed_args.ethertype is not None:
|
|
280
|
-
ethertype = parsed_args.ethertype
|
|
281
|
-
elif self._is_ipv6_protocol(protocol):
|
|
282
|
-
ethertype = 'IPv6'
|
|
283
|
-
return ethertype
|
|
284
|
-
|
|
285
|
-
def _is_ipv6_protocol(self, protocol):
|
|
286
|
-
# NOTE(rtheis): Neutron has deprecated protocol icmpv6.
|
|
287
|
-
# However, while the OSC CLI doesn't document the protocol,
|
|
288
|
-
# the code must still handle it. In addition, handle both
|
|
289
|
-
# protocol names and numbers.
|
|
290
|
-
if (
|
|
291
|
-
protocol is not None
|
|
292
|
-
and protocol.startswith('ipv6-')
|
|
293
|
-
or protocol in ['icmpv6', '41', '43', '44', '58', '59', '60']
|
|
294
|
-
):
|
|
295
|
-
return True
|
|
296
|
-
else:
|
|
297
|
-
return False
|
|
298
|
-
|
|
299
202
|
def take_action_network(self, client, parsed_args):
|
|
300
203
|
# Get the security group ID to hold the rule.
|
|
301
204
|
security_group_id = client.find_security_group(
|
|
@@ -304,7 +207,7 @@ class CreateSecurityGroupRule(
|
|
|
304
207
|
|
|
305
208
|
# Build the create attributes.
|
|
306
209
|
attrs = {}
|
|
307
|
-
attrs['protocol'] =
|
|
210
|
+
attrs['protocol'] = network_utils.get_protocol(parsed_args)
|
|
308
211
|
|
|
309
212
|
if parsed_args.description is not None:
|
|
310
213
|
attrs['description'] = parsed_args.description
|
|
@@ -318,7 +221,7 @@ class CreateSecurityGroupRule(
|
|
|
318
221
|
|
|
319
222
|
# NOTE(rtheis): Use ethertype specified else default based
|
|
320
223
|
# on IP protocol.
|
|
321
|
-
attrs['ethertype'] =
|
|
224
|
+
attrs['ethertype'] = network_utils.get_ethertype(
|
|
322
225
|
parsed_args, attrs['protocol']
|
|
323
226
|
)
|
|
324
227
|
|
|
@@ -335,7 +238,7 @@ class CreateSecurityGroupRule(
|
|
|
335
238
|
if parsed_args.icmp_type is None and parsed_args.icmp_code is not None:
|
|
336
239
|
msg = _('Argument --icmp-type required with argument --icmp-code')
|
|
337
240
|
raise exceptions.CommandError(msg)
|
|
338
|
-
is_icmp_protocol =
|
|
241
|
+
is_icmp_protocol = network_utils.is_icmp_protocol(attrs['protocol'])
|
|
339
242
|
if not is_icmp_protocol and (
|
|
340
243
|
parsed_args.icmp_type or parsed_args.icmp_code
|
|
341
244
|
):
|
|
@@ -390,7 +293,9 @@ class CreateSecurityGroupRule(
|
|
|
390
293
|
|
|
391
294
|
def take_action_compute(self, client, parsed_args):
|
|
392
295
|
group = client.api.security_group_find(parsed_args.group)
|
|
393
|
-
protocol =
|
|
296
|
+
protocol = network_utils.get_protocol(
|
|
297
|
+
parsed_args, default_protocol='tcp'
|
|
298
|
+
)
|
|
394
299
|
if protocol == 'icmp':
|
|
395
300
|
from_port, to_port = -1, -1
|
|
396
301
|
else:
|
|
@@ -414,7 +319,7 @@ class CreateSecurityGroupRule(
|
|
|
414
319
|
remote_ip=remote_ip,
|
|
415
320
|
remote_group=parsed_args.remote_group,
|
|
416
321
|
)
|
|
417
|
-
return
|
|
322
|
+
return network_utils.format_security_group_rule_show(obj)
|
|
418
323
|
|
|
419
324
|
|
|
420
325
|
class DeleteSecurityGroupRule(common.NetworkAndComputeDelete):
|
|
@@ -451,8 +356,8 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
|
|
|
451
356
|
Create port_range column from port_range_min and port_range_max
|
|
452
357
|
"""
|
|
453
358
|
rule = rule.to_dict()
|
|
454
|
-
rule['port_range'] =
|
|
455
|
-
rule['remote_ip_prefix'] =
|
|
359
|
+
rule['port_range'] = network_utils.format_network_port_range(rule)
|
|
360
|
+
rule['remote_ip_prefix'] = network_utils.format_remote_ip_prefix(rule)
|
|
456
361
|
return rule
|
|
457
362
|
|
|
458
363
|
def update_parser_common(self, parser):
|
|
@@ -478,7 +383,7 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
|
|
|
478
383
|
parser.add_argument(
|
|
479
384
|
'--protocol',
|
|
480
385
|
metavar='<protocol>',
|
|
481
|
-
type=
|
|
386
|
+
type=network_utils.convert_to_lowercase,
|
|
482
387
|
help=self.enhance_help_neutron(
|
|
483
388
|
_(
|
|
484
389
|
"List rules by the IP protocol (ah, dhcp, egp, esp, gre, "
|
|
@@ -493,7 +398,7 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
|
|
|
493
398
|
parser.add_argument(
|
|
494
399
|
'--ethertype',
|
|
495
400
|
metavar='<ethertype>',
|
|
496
|
-
type=
|
|
401
|
+
type=network_utils.convert_to_lowercase,
|
|
497
402
|
help=self.enhance_help_neutron(
|
|
498
403
|
_("List rules by the Ethertype (IPv4 or IPv6)")
|
|
499
404
|
),
|
|
@@ -677,7 +582,9 @@ class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
|
|
|
677
582
|
)
|
|
678
583
|
# necessary for old rules that have None in this field
|
|
679
584
|
if not obj['remote_ip_prefix']:
|
|
680
|
-
obj['remote_ip_prefix'] =
|
|
585
|
+
obj['remote_ip_prefix'] = network_utils.format_remote_ip_prefix(
|
|
586
|
+
obj
|
|
587
|
+
)
|
|
681
588
|
display_columns, columns = _get_columns(obj)
|
|
682
589
|
data = utils.get_item_properties(obj, columns)
|
|
683
590
|
return (display_columns, data)
|
|
@@ -704,4 +611,4 @@ class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
|
|
|
704
611
|
raise exceptions.CommandError(msg)
|
|
705
612
|
|
|
706
613
|
# NOTE(rtheis): Format security group rule
|
|
707
|
-
return
|
|
614
|
+
return network_utils.format_security_group_rule_show(obj)
|
|
@@ -306,6 +306,7 @@ class CreateSubnet(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
|
306
306
|
)
|
|
307
307
|
subnet_pool_group.add_argument(
|
|
308
308
|
'--use-prefix-delegation',
|
|
309
|
+
action='store_true',
|
|
309
310
|
help=_(
|
|
310
311
|
"Use 'prefix-delegation' if IP is IPv6 format "
|
|
311
312
|
"and IP would be delegated externally"
|
|
@@ -22,9 +22,9 @@ from osc_lib.cli import parseractions
|
|
|
22
22
|
from osc_lib.command import command
|
|
23
23
|
from osc_lib import utils
|
|
24
24
|
|
|
25
|
+
from openstackclient.common import pagination
|
|
25
26
|
from openstackclient.i18n import _
|
|
26
27
|
|
|
27
|
-
|
|
28
28
|
LOG = logging.getLogger(__name__)
|
|
29
29
|
|
|
30
30
|
|
|
@@ -127,22 +127,12 @@ class ListContainer(command.Lister):
|
|
|
127
127
|
metavar="<prefix>",
|
|
128
128
|
help=_("Filter list using <prefix>"),
|
|
129
129
|
)
|
|
130
|
-
|
|
131
|
-
"--marker",
|
|
132
|
-
metavar="<marker>",
|
|
133
|
-
help=_("Anchor for paging"),
|
|
134
|
-
)
|
|
130
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
135
131
|
parser.add_argument(
|
|
136
132
|
"--end-marker",
|
|
137
133
|
metavar="<end-marker>",
|
|
138
134
|
help=_("End anchor for paging"),
|
|
139
135
|
)
|
|
140
|
-
parser.add_argument(
|
|
141
|
-
"--limit",
|
|
142
|
-
metavar="<num-containers>",
|
|
143
|
-
type=int,
|
|
144
|
-
help=_("Limit the number of containers returned"),
|
|
145
|
-
)
|
|
146
136
|
parser.add_argument(
|
|
147
137
|
'--long',
|
|
148
138
|
action='store_true',
|
|
@@ -23,6 +23,7 @@ from osc_lib.command import command
|
|
|
23
23
|
from osc_lib import exceptions
|
|
24
24
|
from osc_lib import utils
|
|
25
25
|
|
|
26
|
+
from openstackclient.common import pagination
|
|
26
27
|
from openstackclient.i18n import _
|
|
27
28
|
|
|
28
29
|
|
|
@@ -140,22 +141,12 @@ class ListObject(command.Lister):
|
|
|
140
141
|
metavar="<delimiter>",
|
|
141
142
|
help=_("Roll up items with <delimiter>"),
|
|
142
143
|
)
|
|
143
|
-
|
|
144
|
-
"--marker",
|
|
145
|
-
metavar="<marker>",
|
|
146
|
-
help=_("Anchor for paging"),
|
|
147
|
-
)
|
|
144
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
148
145
|
parser.add_argument(
|
|
149
146
|
"--end-marker",
|
|
150
147
|
metavar="<end-marker>",
|
|
151
148
|
help=_("End anchor for paging"),
|
|
152
149
|
)
|
|
153
|
-
parser.add_argument(
|
|
154
|
-
"--limit",
|
|
155
|
-
metavar="<num-objects>",
|
|
156
|
-
type=int,
|
|
157
|
-
help=_("Limit the number of objects returned"),
|
|
158
|
-
)
|
|
159
150
|
parser.add_argument(
|
|
160
151
|
'--long',
|
|
161
152
|
action='store_true',
|
|
@@ -24,14 +24,17 @@ ADMIN_CLOUD = os.environ.get('OS_ADMIN_CLOUD', 'devstack-admin')
|
|
|
24
24
|
LOG = logging.getLogger(__name__)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def execute(cmd, fail_ok=False
|
|
27
|
+
def execute(cmd, *, fail_ok=False):
|
|
28
28
|
"""Executes specified command for the given action."""
|
|
29
29
|
LOG.debug('Executing: %s', cmd)
|
|
30
30
|
cmdlist = shlex.split(cmd)
|
|
31
31
|
stdout = subprocess.PIPE
|
|
32
|
-
stderr = subprocess.
|
|
32
|
+
stderr = subprocess.PIPE
|
|
33
|
+
env = {
|
|
34
|
+
k: v for k, v in os.environ.copy().items() if not k.startswith('OS_')
|
|
35
|
+
}
|
|
33
36
|
|
|
34
|
-
proc = subprocess.Popen(cmdlist, stdout=stdout, stderr=stderr)
|
|
37
|
+
proc = subprocess.Popen(cmdlist, stdout=stdout, stderr=stderr, env=env)
|
|
35
38
|
|
|
36
39
|
result_out, result_err = proc.communicate()
|
|
37
40
|
result_out = result_out.decode('utf-8')
|
|
@@ -65,7 +68,7 @@ class TestCase(testtools.TestCase):
|
|
|
65
68
|
:param cloud: The cloud to execute against. This can be a string, empty
|
|
66
69
|
string, or None. A string results in '--os-auth-type $cloud', an
|
|
67
70
|
empty string results in the '--os-auth-type' option being
|
|
68
|
-
omitted, and None
|
|
71
|
+
omitted, and None results in '--os-auth-type none' for legacy
|
|
69
72
|
reasons.
|
|
70
73
|
:param fail_ok: If failure is permitted. If False (default), a command
|
|
71
74
|
failure will result in `~tempest.lib.exceptions.CommandFailed`
|
|
@@ -119,9 +122,13 @@ class TestCase(testtools.TestCase):
|
|
|
119
122
|
return bool(ret)
|
|
120
123
|
|
|
121
124
|
@classmethod
|
|
122
|
-
def is_extension_enabled(cls, alias):
|
|
125
|
+
def is_extension_enabled(cls, alias, *, service='network'):
|
|
123
126
|
"""Ask client cloud if extension is enabled"""
|
|
124
|
-
|
|
127
|
+
extensions = cls.openstack(
|
|
128
|
+
f'extension list --{service}',
|
|
129
|
+
parse_output=True,
|
|
130
|
+
)
|
|
131
|
+
return alias in [x['Alias'] for x in extensions]
|
|
125
132
|
|
|
126
133
|
@classmethod
|
|
127
134
|
def get_openstack_configuration_value(cls, configuration):
|
|
@@ -146,11 +146,19 @@ class RoleTests(common.IdentityTests):
|
|
|
146
146
|
self.assertEqual(0, len(remove_raw_output))
|
|
147
147
|
|
|
148
148
|
def test_implied_role_list(self):
|
|
149
|
+
raw_output = self.openstack('implied role list')
|
|
150
|
+
default_roles = self.parse_listing(raw_output)
|
|
151
|
+
self.assert_table_structure(
|
|
152
|
+
default_roles, self.IMPLIED_ROLE_LIST_HEADERS
|
|
153
|
+
)
|
|
154
|
+
|
|
149
155
|
self._create_dummy_implied_role()
|
|
150
156
|
raw_output = self.openstack('implied role list')
|
|
151
|
-
|
|
152
|
-
self.assert_table_structure(
|
|
153
|
-
|
|
157
|
+
current_roles = self.parse_listing(raw_output)
|
|
158
|
+
self.assert_table_structure(
|
|
159
|
+
current_roles, self.IMPLIED_ROLE_LIST_HEADERS
|
|
160
|
+
)
|
|
161
|
+
self.assertEqual(len(default_roles) + 1, len(current_roles))
|
|
154
162
|
|
|
155
163
|
def test_implied_role_create(self):
|
|
156
164
|
role_name = self._create_dummy_role()
|
|
@@ -20,9 +20,15 @@ class NetworkTests(base.TestCase):
|
|
|
20
20
|
|
|
21
21
|
@classmethod
|
|
22
22
|
def setUpClass(cls):
|
|
23
|
-
super(
|
|
23
|
+
super().setUpClass()
|
|
24
24
|
cls.haz_network = cls.is_service_enabled('network')
|
|
25
25
|
|
|
26
|
+
def setUp(self):
|
|
27
|
+
super().setUp()
|
|
28
|
+
|
|
29
|
+
if not self.haz_network:
|
|
30
|
+
self.skipTest("No Network service present")
|
|
31
|
+
|
|
26
32
|
|
|
27
33
|
class NetworkTagTests(NetworkTests):
|
|
28
34
|
"""Functional tests with tag operation"""
|
|
@@ -19,10 +19,8 @@ class AddressGroupTests(common.NetworkTests):
|
|
|
19
19
|
"""Functional tests for address group"""
|
|
20
20
|
|
|
21
21
|
def setUp(self):
|
|
22
|
-
super(
|
|
23
|
-
|
|
24
|
-
if not self.haz_network:
|
|
25
|
-
self.skipTest("No Network service present")
|
|
22
|
+
super().setUp()
|
|
23
|
+
|
|
26
24
|
if not self.is_extension_enabled('address-group'):
|
|
27
25
|
self.skipTest("No address-group extension present")
|
|
28
26
|
|
|
@@ -23,12 +23,6 @@ class AddressScopeTests(common.NetworkTests):
|
|
|
23
23
|
# has its own needs and there are collisions when running
|
|
24
24
|
# tests in parallel.
|
|
25
25
|
|
|
26
|
-
def setUp(self):
|
|
27
|
-
super(AddressScopeTests, self).setUp()
|
|
28
|
-
# Nothing in this class works with Nova Network
|
|
29
|
-
if not self.haz_network:
|
|
30
|
-
self.skipTest("No Network service present")
|
|
31
|
-
|
|
32
26
|
def test_address_scope_delete(self):
|
|
33
27
|
"""Test create, delete multiple"""
|
|
34
28
|
name1 = uuid.uuid4().hex
|
|
@@ -0,0 +1,67 @@
|
|
|
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 random
|
|
14
|
+
|
|
15
|
+
from openstackclient.tests.functional.network.v2 import common
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SecurityGroupRuleTests(common.NetworkTests):
|
|
19
|
+
"""Functional tests for security group rule"""
|
|
20
|
+
|
|
21
|
+
def setUp(self):
|
|
22
|
+
super().setUp()
|
|
23
|
+
|
|
24
|
+
if not self.is_extension_enabled("security-groups-default-rules"):
|
|
25
|
+
self.skipTest("No security-groups-default-rules extension present")
|
|
26
|
+
|
|
27
|
+
self.port = random.randint(1, 65535)
|
|
28
|
+
self.protocol = random.choice(["tcp", "udp"])
|
|
29
|
+
self.direction = random.choice(["ingress", "egress"])
|
|
30
|
+
# Create the default security group rule.
|
|
31
|
+
cmd_output = self.openstack(
|
|
32
|
+
'default security group rule create '
|
|
33
|
+
'--protocol %(protocol)s '
|
|
34
|
+
'--dst-port %(port)s:%(port)s '
|
|
35
|
+
'--%(direction)s --ethertype IPv4 '
|
|
36
|
+
% {
|
|
37
|
+
'protocol': self.protocol,
|
|
38
|
+
'port': self.port,
|
|
39
|
+
'direction': self.direction,
|
|
40
|
+
},
|
|
41
|
+
parse_output=True,
|
|
42
|
+
)
|
|
43
|
+
self.addCleanup(
|
|
44
|
+
self.openstack,
|
|
45
|
+
'default security group rule delete ' + cmd_output['id'],
|
|
46
|
+
)
|
|
47
|
+
self.DEFAULT_SG_RULE_ID = cmd_output['id']
|
|
48
|
+
|
|
49
|
+
def test_security_group_rule_list(self):
|
|
50
|
+
cmd_output = self.openstack(
|
|
51
|
+
'default security group rule list ',
|
|
52
|
+
parse_output=True,
|
|
53
|
+
)
|
|
54
|
+
self.assertIn(
|
|
55
|
+
self.DEFAULT_SG_RULE_ID, [rule['ID'] for rule in cmd_output]
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def test_security_group_rule_show(self):
|
|
59
|
+
cmd_output = self.openstack(
|
|
60
|
+
'default security group rule show ' + self.DEFAULT_SG_RULE_ID,
|
|
61
|
+
parse_output=True,
|
|
62
|
+
)
|
|
63
|
+
self.assertEqual(self.DEFAULT_SG_RULE_ID, cmd_output['id'])
|
|
64
|
+
self.assertEqual(self.protocol, cmd_output['protocol'])
|
|
65
|
+
self.assertEqual(self.port, cmd_output['port_range_min'])
|
|
66
|
+
self.assertEqual(self.port, cmd_output['port_range_max'])
|
|
67
|
+
self.assertEqual(self.direction, cmd_output['direction'])
|
|
@@ -21,7 +21,7 @@ class FloatingIpTests(common.NetworkTests):
|
|
|
21
21
|
|
|
22
22
|
@classmethod
|
|
23
23
|
def setUpClass(cls):
|
|
24
|
-
|
|
24
|
+
super().setUpClass()
|
|
25
25
|
if cls.haz_network:
|
|
26
26
|
# Create common networks that all tests share
|
|
27
27
|
cls.EXTERNAL_NETWORK_NAME = uuid.uuid4().hex
|
|
@@ -53,13 +53,10 @@ class FloatingIpTests(common.NetworkTests):
|
|
|
53
53
|
)
|
|
54
54
|
cls.assertOutput('', del_output)
|
|
55
55
|
finally:
|
|
56
|
-
super(
|
|
56
|
+
super().tearDownClass()
|
|
57
57
|
|
|
58
58
|
def setUp(self):
|
|
59
|
-
super(
|
|
60
|
-
# Nothing in this class works with Nova Network
|
|
61
|
-
if not self.haz_network:
|
|
62
|
-
self.skipTest("No Network service present")
|
|
59
|
+
super().setUp()
|
|
63
60
|
|
|
64
61
|
# Verify setup
|
|
65
62
|
self.assertIsNotNone(self.external_network_id)
|