python-openstackclient 10.0.0__py3-none-any.whl → 10.1.0__py3-none-any.whl

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