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.
Files changed (162) hide show
  1. openstackclient/common/availability_zone.py +4 -4
  2. openstackclient/common/pagination.py +82 -0
  3. openstackclient/compute/v2/flavor.py +2 -16
  4. openstackclient/compute/v2/hypervisor.py +2 -21
  5. openstackclient/compute/v2/keypair.py +2 -9
  6. openstackclient/compute/v2/server.py +220 -131
  7. openstackclient/compute/v2/server_event.py +30 -19
  8. openstackclient/compute/v2/server_group.py +2 -23
  9. openstackclient/compute/v2/server_migration.py +2 -22
  10. openstackclient/compute/v2/usage.py +4 -6
  11. openstackclient/identity/v3/mapping.py +25 -3
  12. openstackclient/identity/v3/policy.py +3 -1
  13. openstackclient/image/v2/cache.py +218 -0
  14. openstackclient/image/v2/image.py +40 -17
  15. openstackclient/image/v2/metadef_namespaces.py +25 -21
  16. openstackclient/image/v2/metadef_objects.py +189 -0
  17. openstackclient/image/v2/metadef_properties.py +284 -0
  18. openstackclient/network/utils.py +100 -0
  19. openstackclient/network/v2/default_security_group_rule.py +418 -0
  20. openstackclient/network/v2/local_ip_association.py +1 -1
  21. openstackclient/network/v2/ndp_proxy.py +7 -3
  22. openstackclient/network/v2/network.py +2 -2
  23. openstackclient/network/v2/port.py +65 -19
  24. openstackclient/network/v2/security_group_rule.py +18 -111
  25. openstackclient/network/v2/subnet.py +1 -0
  26. openstackclient/object/v1/container.py +2 -12
  27. openstackclient/object/v1/object.py +2 -11
  28. openstackclient/tests/functional/base.py +13 -6
  29. openstackclient/tests/functional/identity/v3/test_role.py +11 -3
  30. openstackclient/tests/functional/network/v2/common.py +7 -1
  31. openstackclient/tests/functional/network/v2/test_address_group.py +2 -4
  32. openstackclient/tests/functional/network/v2/test_address_scope.py +0 -6
  33. openstackclient/tests/functional/network/v2/test_default_security_group_rule.py +67 -0
  34. openstackclient/tests/functional/network/v2/test_floating_ip.py +3 -6
  35. openstackclient/tests/functional/network/v2/test_ip_availability.py +3 -8
  36. openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py +3 -4
  37. openstackclient/tests/functional/network/v2/test_local_ip.py +2 -4
  38. openstackclient/tests/functional/network/v2/test_network.py +18 -17
  39. openstackclient/tests/functional/network/v2/test_network_agent.py +24 -21
  40. openstackclient/tests/functional/network/v2/test_network_flavor.py +0 -6
  41. openstackclient/tests/functional/network/v2/test_network_flavor_profile.py +0 -6
  42. openstackclient/tests/functional/network/v2/test_network_meter.py +6 -6
  43. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +7 -8
  44. openstackclient/tests/functional/network/v2/test_network_ndp_proxy.py +1 -3
  45. openstackclient/tests/functional/network/v2/test_network_qos_policy.py +4 -4
  46. openstackclient/tests/functional/network/v2/test_network_qos_rule.py +16 -20
  47. openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py +4 -4
  48. openstackclient/tests/functional/network/v2/test_network_rbac.py +1 -4
  49. openstackclient/tests/functional/network/v2/test_network_segment.py +7 -12
  50. openstackclient/tests/functional/network/v2/test_network_segment_range.py +3 -4
  51. openstackclient/tests/functional/network/v2/test_network_service_provider.py +2 -4
  52. openstackclient/tests/functional/network/v2/test_network_trunk.py +3 -3
  53. openstackclient/tests/functional/network/v2/test_port.py +2 -8
  54. openstackclient/tests/functional/network/v2/test_router.py +0 -6
  55. openstackclient/tests/functional/network/v2/test_security_group.py +1 -4
  56. openstackclient/tests/functional/network/v2/test_security_group_rule.py +1 -4
  57. openstackclient/tests/functional/network/v2/test_subnet.py +4 -22
  58. openstackclient/tests/functional/network/v2/test_subnet_pool.py +0 -6
  59. openstackclient/tests/unit/common/test_availability_zone.py +28 -30
  60. openstackclient/tests/unit/common/test_extension.py +1 -4
  61. openstackclient/tests/unit/common/test_limits.py +2 -4
  62. openstackclient/tests/unit/common/test_project_cleanup.py +3 -10
  63. openstackclient/tests/unit/common/test_quota.py +18 -24
  64. openstackclient/tests/unit/compute/v2/fakes.py +24 -11
  65. openstackclient/tests/unit/compute/v2/test_agent.py +1 -1
  66. openstackclient/tests/unit/compute/v2/test_aggregate.py +62 -72
  67. openstackclient/tests/unit/compute/v2/test_console.py +18 -30
  68. openstackclient/tests/unit/compute/v2/test_flavor.py +85 -89
  69. openstackclient/tests/unit/compute/v2/test_host.py +12 -19
  70. openstackclient/tests/unit/compute/v2/test_hypervisor.py +23 -25
  71. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +2 -6
  72. openstackclient/tests/unit/compute/v2/test_keypair.py +25 -39
  73. openstackclient/tests/unit/compute/v2/test_server.py +316 -365
  74. openstackclient/tests/unit/compute/v2/test_server_backup.py +5 -17
  75. openstackclient/tests/unit/compute/v2/test_server_event.py +23 -25
  76. openstackclient/tests/unit/compute/v2/test_server_group.py +41 -33
  77. openstackclient/tests/unit/compute/v2/test_server_image.py +6 -18
  78. openstackclient/tests/unit/compute/v2/test_server_migration.py +45 -45
  79. openstackclient/tests/unit/compute/v2/test_server_volume.py +15 -31
  80. openstackclient/tests/unit/compute/v2/test_service.py +51 -56
  81. openstackclient/tests/unit/compute/v2/test_usage.py +10 -13
  82. openstackclient/tests/unit/fakes.py +4 -0
  83. openstackclient/tests/unit/identity/v3/test_mappings.py +9 -4
  84. openstackclient/tests/unit/identity/v3/test_trust.py +0 -2
  85. openstackclient/tests/unit/image/v1/fakes.py +2 -1
  86. openstackclient/tests/unit/image/v1/test_image.py +1 -1
  87. openstackclient/tests/unit/image/v2/fakes.py +82 -0
  88. openstackclient/tests/unit/image/v2/test_cache.py +214 -0
  89. openstackclient/tests/unit/image/v2/test_image.py +62 -4
  90. openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +5 -19
  91. openstackclient/tests/unit/image/v2/test_metadef_objects.py +162 -0
  92. openstackclient/tests/unit/image/v2/test_metadef_properties.py +227 -0
  93. openstackclient/tests/unit/integ/cli/test_shell.py +0 -2
  94. openstackclient/tests/unit/network/test_common.py +3 -3
  95. openstackclient/tests/unit/network/v2/fakes.py +1 -0
  96. openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +1133 -0
  97. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +5 -13
  98. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +1 -9
  99. openstackclient/tests/unit/network/v2/test_network.py +33 -0
  100. openstackclient/tests/unit/network/v2/test_network_compute.py +5 -11
  101. openstackclient/tests/unit/network/v2/test_network_trunk.py +6 -8
  102. openstackclient/tests/unit/network/v2/test_port.py +83 -38
  103. openstackclient/tests/unit/network/v2/test_security_group_compute.py +7 -15
  104. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +19 -27
  105. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +3 -6
  106. openstackclient/tests/unit/network/v2/test_subnet.py +92 -0
  107. openstackclient/tests/unit/network/v2/test_subnet_pool.py +11 -13
  108. openstackclient/tests/unit/test_shell.py +1 -7
  109. openstackclient/tests/unit/utils.py +10 -4
  110. openstackclient/tests/unit/volume/v1/fakes.py +7 -1
  111. openstackclient/tests/unit/volume/v1/test_qos_specs.py +2 -2
  112. openstackclient/tests/unit/volume/v1/test_service.py +1 -1
  113. openstackclient/tests/unit/volume/v1/test_transfer_request.py +2 -2
  114. openstackclient/tests/unit/volume/v1/test_type.py +2 -4
  115. openstackclient/tests/unit/volume/v1/test_volume.py +5 -7
  116. openstackclient/tests/unit/volume/v1/test_volume_backup.py +4 -4
  117. openstackclient/tests/unit/volume/v2/fakes.py +32 -12
  118. openstackclient/tests/unit/volume/v2/test_backup_record.py +1 -1
  119. openstackclient/tests/unit/volume/v2/test_consistency_group.py +4 -6
  120. openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py +2 -4
  121. openstackclient/tests/unit/volume/v2/test_qos_specs.py +2 -2
  122. openstackclient/tests/unit/volume/v2/test_service.py +1 -1
  123. openstackclient/tests/unit/volume/v2/test_volume.py +78 -16
  124. openstackclient/tests/unit/volume/v2/test_volume_backend.py +10 -22
  125. openstackclient/tests/unit/volume/v2/test_volume_backup.py +76 -89
  126. openstackclient/tests/unit/volume/v2/test_volume_host.py +1 -1
  127. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +5 -7
  128. openstackclient/tests/unit/volume/v2/test_volume_transfer_request.py +4 -8
  129. openstackclient/tests/unit/volume/v2/test_volume_type.py +164 -24
  130. openstackclient/tests/unit/volume/v3/fakes.py +91 -15
  131. openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py +3 -7
  132. openstackclient/tests/unit/volume/v3/test_block_storage_cluster.py +11 -31
  133. openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +6 -16
  134. openstackclient/tests/unit/volume/v3/test_block_storage_manage.py +219 -157
  135. openstackclient/tests/unit/volume/v3/test_block_storage_resource_filter.py +32 -23
  136. openstackclient/tests/unit/volume/v3/test_volume.py +50 -48
  137. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +17 -47
  138. openstackclient/tests/unit/volume/v3/test_volume_group.py +23 -65
  139. openstackclient/tests/unit/volume/v3/test_volume_group_snapshot.py +88 -77
  140. openstackclient/tests/unit/volume/v3/test_volume_group_type.py +14 -42
  141. openstackclient/tests/unit/volume/v3/test_volume_message.py +10 -28
  142. openstackclient/volume/v1/volume.py +2 -14
  143. openstackclient/volume/v2/volume.py +30 -15
  144. openstackclient/volume/v2/volume_backend.py +10 -18
  145. openstackclient/volume/v2/volume_backup.py +18 -15
  146. openstackclient/volume/v2/volume_snapshot.py +2 -12
  147. openstackclient/volume/v2/volume_type.py +211 -14
  148. openstackclient/volume/v3/block_storage_manage.py +72 -11
  149. openstackclient/volume/v3/block_storage_resource_filter.py +33 -11
  150. openstackclient/volume/v3/volume_attachment.py +2 -14
  151. openstackclient/volume/v3/volume_group_snapshot.py +27 -27
  152. openstackclient/volume/v3/volume_message.py +2 -13
  153. {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/AUTHORS +11 -0
  154. {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/METADATA +6 -5
  155. {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/RECORD +160 -151
  156. {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/entry_points.txt +23 -5
  157. python_openstackclient-6.5.0.dist-info/pbr.json +1 -0
  158. openstackclient/tests/unit/common/test_parseractions.py +0 -233
  159. python_openstackclient-6.3.0.dist-info/pbr.json +0 -1
  160. {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/LICENSE +0 -0
  161. {python_openstackclient-6.3.0.dist-info → python_openstackclient-6.5.0.dist-info}/WHEEL +0 -0
  162. {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
- column_map = {
59
- 'binding:host_id': 'binding_host_id',
60
- 'binding:profile': 'binding_profile',
61
- 'binding:vif_details': 'binding_vif_details',
62
- 'binding:vif_type': 'binding_vif_type',
63
- 'binding:vnic_type': 'binding_vnic_type',
64
- 'is_admin_state_up': 'admin_state_up',
65
- 'is_port_security_enabled': 'port_security_enabled',
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
- hidden_columns = ['location', 'tenant_id']
68
- return utils.get_osc_show_columns_for_sdk_resource(
69
- item, column_map, hidden_columns
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.ArgumentTypeError(msg)
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 argparse.ArgumentTypeError(msg)
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['security_groups'] = parsed_args.security_groups
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=_convert_to_lowercase,
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=_convert_to_lowercase,
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=_convert_ipvx_case,
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'] = self._get_protocol(parsed_args)
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'] = self._get_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 = _is_icmp_protocol(attrs['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 = self._get_protocol(parsed_args, default_protocol='tcp')
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 _format_security_group_rule_show(obj)
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'] = _format_network_port_range(rule)
455
- rule['remote_ip_prefix'] = _format_remote_ip_prefix(rule)
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=_convert_to_lowercase,
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=_convert_to_lowercase,
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'] = _format_remote_ip_prefix(obj)
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 _format_security_group_rule_show(obj)
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
- parser.add_argument(
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
- parser.add_argument(
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, merge_stderr=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.STDOUT if merge_stderr else subprocess.PIPE
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 resuts in '--os-auth-type none' for legacy
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
- return alias in cls.openstack('extension list -f value -c Alias')
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
- items = self.parse_listing(raw_output)
152
- self.assert_table_structure(items, self.IMPLIED_ROLE_LIST_HEADERS)
153
- self.assertEqual(3, len(items))
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(NetworkTests, cls).setUpClass()
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(AddressGroupTests, self).setUp()
23
- # Nothing in this class works with Nova Network
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
- common.NetworkTests.setUpClass()
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(FloatingIpTests, cls).tearDownClass()
56
+ super().tearDownClass()
57
57
 
58
58
  def setUp(self):
59
- super(FloatingIpTests, self).setUp()
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)