python-openstackclient 8.0.0__py3-none-any.whl → 8.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 (85) hide show
  1. openstackclient/compute/client.py +5 -0
  2. openstackclient/compute/v2/console.py +7 -0
  3. openstackclient/compute/v2/console_connection.py +48 -0
  4. openstackclient/compute/v2/keypair.py +10 -3
  5. openstackclient/compute/v2/server.py +75 -10
  6. openstackclient/compute/v2/server_event.py +1 -1
  7. openstackclient/identity/common.py +79 -0
  8. openstackclient/identity/v3/application_credential.py +2 -2
  9. openstackclient/identity/v3/domain.py +62 -43
  10. openstackclient/identity/v3/group.py +113 -68
  11. openstackclient/identity/v3/project.py +17 -0
  12. openstackclient/identity/v3/user.py +38 -5
  13. openstackclient/image/client.py +5 -0
  14. openstackclient/image/v2/image.py +11 -11
  15. openstackclient/network/client.py +0 -6
  16. openstackclient/network/v2/floating_ip.py +58 -29
  17. openstackclient/network/v2/network_qos_rule.py +3 -11
  18. openstackclient/network/v2/router.py +1 -1
  19. openstackclient/network/v2/security_group.py +5 -4
  20. openstackclient/network/v2/security_group_rule.py +1 -1
  21. openstackclient/shell.py +1 -1
  22. openstackclient/tests/functional/base.py +5 -1
  23. openstackclient/tests/functional/compute/v2/test_keypair.py +41 -5
  24. openstackclient/tests/unit/compute/v2/fakes.py +81 -305
  25. openstackclient/tests/unit/compute/v2/test_console.py +18 -1
  26. openstackclient/tests/unit/compute/v2/test_console_connection.py +72 -0
  27. openstackclient/tests/unit/compute/v2/test_flavor.py +1 -1
  28. openstackclient/tests/unit/compute/v2/test_keypair.py +12 -5
  29. openstackclient/tests/unit/compute/v2/test_server.py +169 -46
  30. openstackclient/tests/unit/compute/v2/test_server_backup.py +32 -71
  31. openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
  32. openstackclient/tests/unit/compute/v2/test_server_image.py +33 -72
  33. openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
  34. openstackclient/tests/unit/identity/v3/test_application_credential.py +47 -25
  35. openstackclient/tests/unit/identity/v3/test_domain.py +115 -105
  36. openstackclient/tests/unit/identity/v3/test_group.py +353 -202
  37. openstackclient/tests/unit/identity/v3/test_project.py +16 -0
  38. openstackclient/tests/unit/identity/v3/test_user.py +86 -6
  39. openstackclient/tests/unit/image/v1/test_image.py +8 -9
  40. openstackclient/tests/unit/image/v2/test_image.py +49 -49
  41. openstackclient/tests/unit/network/v2/fakes.py +405 -485
  42. openstackclient/tests/unit/network/v2/test_floating_ip_network.py +13 -19
  43. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +2 -2
  44. openstackclient/tests/unit/network/v2/test_ndp_proxy.py +1 -3
  45. openstackclient/tests/unit/network/v2/test_network.py +4 -4
  46. openstackclient/tests/unit/network/v2/test_network_agent.py +15 -29
  47. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +16 -19
  48. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +79 -152
  49. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +4 -6
  50. openstackclient/tests/unit/network/v2/test_network_rbac.py +2 -2
  51. openstackclient/tests/unit/network/v2/test_port.py +17 -17
  52. openstackclient/tests/unit/network/v2/test_router.py +73 -57
  53. openstackclient/tests/unit/network/v2/test_security_group_network.py +25 -27
  54. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +1 -3
  55. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +33 -39
  56. openstackclient/tests/unit/volume/v2/fakes.py +1 -2
  57. openstackclient/tests/unit/volume/v2/test_service.py +57 -91
  58. openstackclient/tests/unit/volume/v2/test_volume.py +108 -105
  59. openstackclient/tests/unit/volume/v2/test_volume_backup.py +141 -148
  60. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +293 -283
  61. openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +61 -71
  62. openstackclient/tests/unit/volume/v3/test_service.py +221 -141
  63. openstackclient/tests/unit/volume/v3/test_volume.py +130 -119
  64. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
  65. openstackclient/tests/unit/volume/v3/test_volume_backup.py +198 -203
  66. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +682 -47
  67. openstackclient/volume/v2/service.py +41 -38
  68. openstackclient/volume/v2/volume.py +63 -37
  69. openstackclient/volume/v2/volume_backup.py +9 -3
  70. openstackclient/volume/v2/volume_snapshot.py +121 -84
  71. openstackclient/volume/v3/block_storage_log_level.py +22 -28
  72. openstackclient/volume/v3/service.py +105 -14
  73. openstackclient/volume/v3/volume.py +200 -39
  74. openstackclient/volume/v3/volume_backup.py +24 -19
  75. openstackclient/volume/v3/volume_snapshot.py +485 -10
  76. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/AUTHORS +8 -0
  77. python_openstackclient-8.1.0.dist-info/METADATA +264 -0
  78. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/RECORD +83 -81
  79. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/entry_points.txt +7 -6
  80. python_openstackclient-8.1.0.dist-info/pbr.json +1 -0
  81. python_openstackclient-8.0.0.dist-info/METADATA +0 -166
  82. python_openstackclient-8.0.0.dist-info/pbr.json +0 -1
  83. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/LICENSE +0 -0
  84. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/WHEEL +0 -0
  85. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/top_level.txt +0 -0
@@ -31,7 +31,6 @@ from osc_lib import utils
31
31
  from openstackclient.common import pagination
32
32
  from openstackclient.i18n import _
33
33
  from openstackclient.identity import common as identity_common
34
- from openstackclient.volume.v2 import volume as volume_v2
35
34
 
36
35
 
37
36
  LOG = logging.getLogger(__name__)
@@ -91,7 +90,7 @@ class AttachmentsColumn(cliff_columns.FormattableColumn):
91
90
  return msg
92
91
 
93
92
 
94
- class CreateVolume(volume_v2.CreateVolume):
93
+ class CreateVolume(command.ShowOne):
95
94
  _description = _("Create new volume")
96
95
 
97
96
  @staticmethod
@@ -117,8 +116,48 @@ class CreateVolume(volume_v2.CreateVolume):
117
116
  raise exceptions.CommandError(msg)
118
117
 
119
118
  def get_parser(self, prog_name):
120
- parser, source_group = self._get_parser(prog_name)
121
-
119
+ parser = super().get_parser(prog_name)
120
+ parser.add_argument(
121
+ "name",
122
+ metavar="<name>",
123
+ nargs="?",
124
+ help=_("Volume name"),
125
+ )
126
+ parser.add_argument(
127
+ "--size",
128
+ metavar="<size>",
129
+ type=int,
130
+ help=_(
131
+ "Volume size in GB (required unless --snapshot or "
132
+ "--source specified)"
133
+ ),
134
+ )
135
+ parser.add_argument(
136
+ "--type",
137
+ metavar="<volume-type>",
138
+ help=_("Set the type of volume"),
139
+ )
140
+ source_group = parser.add_mutually_exclusive_group()
141
+ source_group.add_argument(
142
+ "--image",
143
+ metavar="<image>",
144
+ help=_("Use <image> as source of volume (name or ID)"),
145
+ )
146
+ source_group.add_argument(
147
+ "--snapshot",
148
+ metavar="<snapshot>",
149
+ help=_("Use <snapshot> as source of volume (name or ID)"),
150
+ )
151
+ source_group.add_argument(
152
+ "--source",
153
+ metavar="<volume>",
154
+ help=_("Volume to clone (name or ID)"),
155
+ )
156
+ source_group.add_argument(
157
+ "--source-replicated",
158
+ metavar="<replicated-volume>",
159
+ help=argparse.SUPPRESS,
160
+ )
122
161
  source_group.add_argument(
123
162
  "--backup",
124
163
  metavar="<backup>",
@@ -138,6 +177,72 @@ class CreateVolume(volume_v2.CreateVolume):
138
177
  "--remote-source source-id=test_id')"
139
178
  ),
140
179
  )
180
+ parser.add_argument(
181
+ "--description",
182
+ metavar="<description>",
183
+ help=_("Volume description"),
184
+ )
185
+ parser.add_argument(
186
+ "--availability-zone",
187
+ metavar="<availability-zone>",
188
+ help=_("Create volume in <availability-zone>"),
189
+ )
190
+ parser.add_argument(
191
+ "--consistency-group",
192
+ metavar="consistency-group>",
193
+ help=_("Consistency group where the new volume belongs to"),
194
+ )
195
+ parser.add_argument(
196
+ "--property",
197
+ metavar="<key=value>",
198
+ action=parseractions.KeyValueAction,
199
+ dest="properties",
200
+ help=_(
201
+ "Set a property to this volume "
202
+ "(repeat option to set multiple properties)"
203
+ ),
204
+ )
205
+ parser.add_argument(
206
+ "--hint",
207
+ metavar="<key=value>",
208
+ action=KeyValueHintAction,
209
+ help=_(
210
+ "Arbitrary scheduler hint key-value pairs to help creating "
211
+ "a volume. Repeat the option to set multiple hints. "
212
+ "'same_host' and 'different_host' get values appended when "
213
+ "repeated, all other keys take the last given value"
214
+ ),
215
+ )
216
+ bootable_group = parser.add_mutually_exclusive_group()
217
+ bootable_group.add_argument(
218
+ "--bootable",
219
+ action="store_true",
220
+ dest="bootable",
221
+ default=None,
222
+ help=_("Mark volume as bootable"),
223
+ )
224
+ bootable_group.add_argument(
225
+ "--non-bootable",
226
+ action="store_false",
227
+ dest="bootable",
228
+ default=None,
229
+ help=_("Mark volume as non-bootable (default)"),
230
+ )
231
+ readonly_group = parser.add_mutually_exclusive_group()
232
+ readonly_group.add_argument(
233
+ "--read-only",
234
+ action="store_true",
235
+ dest="read_only",
236
+ default=None,
237
+ help=_("Set volume to read-only access mode"),
238
+ )
239
+ readonly_group.add_argument(
240
+ "--read-write",
241
+ action="store_false",
242
+ dest="read_only",
243
+ default=None,
244
+ help=_("Set volume to read-write access mode (default)"),
245
+ )
141
246
  parser.add_argument(
142
247
  "--host",
143
248
  metavar="<host>",
@@ -160,7 +265,7 @@ class CreateVolume(volume_v2.CreateVolume):
160
265
  return parser
161
266
 
162
267
  def take_action(self, parsed_args):
163
- CreateVolume._check_size_arg(parsed_args)
268
+ self._check_size_arg(parsed_args)
164
269
  # size is validated in the above call to
165
270
  # _check_size_arg where we check that size
166
271
  # should be passed if we are not creating a
@@ -194,8 +299,7 @@ class CreateVolume(volume_v2.CreateVolume):
194
299
  parsed_args.size
195
300
  or parsed_args.consistency_group
196
301
  or parsed_args.hint
197
- or parsed_args.read_only
198
- or parsed_args.read_write
302
+ or parsed_args.read_only is not None
199
303
  ):
200
304
  msg = _(
201
305
  "The --size, --consistency-group, --hint, --read-only "
@@ -232,10 +336,24 @@ class CreateVolume(volume_v2.CreateVolume):
232
336
  description=parsed_args.description,
233
337
  volume_type=parsed_args.type,
234
338
  availability_zone=parsed_args.availability_zone,
235
- metadata=parsed_args.property,
339
+ metadata=parsed_args.properties,
236
340
  bootable=parsed_args.bootable,
237
341
  )
238
- return zip(*sorted(volume.items()))
342
+ data = {}
343
+ for key, value in volume.to_dict().items():
344
+ # FIXME(stephenfin): Stop ignoring these once we bump SDK
345
+ # https://review.opendev.org/c/openstack/openstacksdk/+/945836/
346
+ if key in (
347
+ 'cluster_name',
348
+ 'consumes_quota',
349
+ 'encryption_key_id',
350
+ 'service_uuid',
351
+ 'shared_targets',
352
+ 'volume_type_id',
353
+ ):
354
+ continue
355
+ data[key] = value
356
+ return zip(*sorted(data.items()))
239
357
 
240
358
  source_volume = None
241
359
  if parsed_args.source:
@@ -287,7 +405,7 @@ class CreateVolume(volume_v2.CreateVolume):
287
405
  description=parsed_args.description,
288
406
  volume_type=parsed_args.type,
289
407
  availability_zone=parsed_args.availability_zone,
290
- metadata=parsed_args.property,
408
+ metadata=parsed_args.properties,
291
409
  imageRef=image,
292
410
  source_volid=source_volume,
293
411
  consistencygroup_id=consistency_group,
@@ -295,7 +413,7 @@ class CreateVolume(volume_v2.CreateVolume):
295
413
  backup_id=backup,
296
414
  )
297
415
 
298
- if parsed_args.bootable or parsed_args.non_bootable:
416
+ if parsed_args.bootable is not None:
299
417
  try:
300
418
  if utils.wait_for_status(
301
419
  volume_client.volumes.get,
@@ -314,7 +432,8 @@ class CreateVolume(volume_v2.CreateVolume):
314
432
  raise exceptions.CommandError(msg)
315
433
  except Exception as e:
316
434
  LOG.error(_("Failed to set volume bootable property: %s"), e)
317
- if parsed_args.read_only or parsed_args.read_write:
435
+
436
+ if parsed_args.read_only is not None:
318
437
  try:
319
438
  if utils.wait_for_status(
320
439
  volume_client.volumes.get,
@@ -351,11 +470,33 @@ class CreateVolume(volume_v2.CreateVolume):
351
470
  return zip(*sorted(volume._info.items()))
352
471
 
353
472
 
354
- class DeleteVolume(volume_v2.DeleteVolume):
473
+ class DeleteVolume(command.Command):
355
474
  _description = _("Delete volume(s)")
356
475
 
357
476
  def get_parser(self, prog_name):
358
477
  parser = super().get_parser(prog_name)
478
+ parser.add_argument(
479
+ "volumes",
480
+ metavar="<volume>",
481
+ nargs="+",
482
+ help=_("Volume(s) to delete (name or ID)"),
483
+ )
484
+ group = parser.add_mutually_exclusive_group()
485
+ group.add_argument(
486
+ "--force",
487
+ action="store_true",
488
+ help=_(
489
+ "Attempt forced removal of volume(s), regardless of state "
490
+ "(defaults to False)"
491
+ ),
492
+ )
493
+ group.add_argument(
494
+ "--purge",
495
+ action="store_true",
496
+ help=_(
497
+ "Remove any snapshots along with volume(s) (defaults to False)"
498
+ ),
499
+ )
359
500
  parser.add_argument(
360
501
  '--remote',
361
502
  action='store_true',
@@ -364,8 +505,7 @@ class DeleteVolume(volume_v2.DeleteVolume):
364
505
  return parser
365
506
 
366
507
  def take_action(self, parsed_args):
367
- volume_client = self.app.client_manager.volume
368
- volume_client_sdk = self.app.client_manager.sdk_connection.volume
508
+ volume_client = self.app.client_manager.sdk_connection.volume
369
509
  result = 0
370
510
 
371
511
  if parsed_args.remote and (parsed_args.force or parsed_args.purge):
@@ -375,16 +515,18 @@ class DeleteVolume(volume_v2.DeleteVolume):
375
515
  )
376
516
  raise exceptions.CommandError(msg)
377
517
 
378
- for i in parsed_args.volumes:
518
+ for volume in parsed_args.volumes:
379
519
  try:
380
- volume_obj = utils.find_resource(volume_client.volumes, i)
520
+ volume_obj = volume_client.find_volume(
521
+ volume, ignore_missing=False
522
+ )
381
523
  if parsed_args.remote:
382
- volume_client_sdk.unmanage_volume(volume_obj.id)
383
- elif parsed_args.force:
384
- volume_client.volumes.force_delete(volume_obj.id)
524
+ volume_client.unmanage_volume(volume_obj.id)
385
525
  else:
386
- volume_client.volumes.delete(
387
- volume_obj.id, cascade=parsed_args.purge
526
+ volume_client.delete_volume(
527
+ volume_obj.id,
528
+ force=parsed_args.force,
529
+ cascade=parsed_args.purge,
388
530
  )
389
531
  except Exception as e:
390
532
  result += 1
@@ -393,7 +535,7 @@ class DeleteVolume(volume_v2.DeleteVolume):
393
535
  "Failed to delete volume with "
394
536
  "name or ID '%(volume)s': %(e)s"
395
537
  ),
396
- {'volume': i, 'e': e},
538
+ {'volume': volume, 'e': e},
397
539
  )
398
540
 
399
541
  if result > 0:
@@ -638,6 +780,7 @@ class SetVolume(command.Command):
638
780
  '--property',
639
781
  metavar='<key=value>',
640
782
  action=parseractions.KeyValueAction,
783
+ dest='properties',
641
784
  help=_(
642
785
  'Set a property on this volume '
643
786
  '(repeat option to set multiple properties)'
@@ -647,6 +790,7 @@ class SetVolume(command.Command):
647
790
  '--image-property',
648
791
  metavar='<key=value>',
649
792
  action=parseractions.KeyValueAction,
793
+ dest='image_properties',
650
794
  help=_(
651
795
  'Set an image property on this volume '
652
796
  '(repeat option to set multiple image properties)'
@@ -723,22 +867,30 @@ class SetVolume(command.Command):
723
867
  bootable_group.add_argument(
724
868
  "--bootable",
725
869
  action="store_true",
870
+ dest="bootable",
871
+ default=None,
726
872
  help=_("Mark volume as bootable"),
727
873
  )
728
874
  bootable_group.add_argument(
729
875
  "--non-bootable",
730
- action="store_true",
876
+ action="store_false",
877
+ dest="bootable",
878
+ default=None,
731
879
  help=_("Mark volume as non-bootable"),
732
880
  )
733
881
  readonly_group = parser.add_mutually_exclusive_group()
734
882
  readonly_group.add_argument(
735
883
  "--read-only",
736
884
  action="store_true",
885
+ dest="read_only",
886
+ default=None,
737
887
  help=_("Set volume to read-only access mode"),
738
888
  )
739
889
  readonly_group.add_argument(
740
890
  "--read-write",
741
- action="store_true",
891
+ action="store_false",
892
+ dest="read_only",
893
+ default=None,
742
894
  help=_("Set volume to read-write access mode"),
743
895
  )
744
896
  return parser
@@ -796,28 +948,31 @@ class SetVolume(command.Command):
796
948
  LOG.error(_("Failed to clean volume properties: %s"), e)
797
949
  result += 1
798
950
 
799
- if parsed_args.property:
951
+ if parsed_args.properties:
800
952
  try:
801
953
  volume_client.volumes.set_metadata(
802
- volume.id, parsed_args.property
954
+ volume.id, parsed_args.properties
803
955
  )
804
956
  except Exception as e:
805
- LOG.error(_("Failed to set volume property: %s"), e)
957
+ LOG.error(_("Failed to set volume properties: %s"), e)
806
958
  result += 1
807
- if parsed_args.image_property:
959
+
960
+ if parsed_args.image_properties:
808
961
  try:
809
962
  volume_client.volumes.set_image_metadata(
810
- volume.id, parsed_args.image_property
963
+ volume.id, parsed_args.image_properties
811
964
  )
812
965
  except Exception as e:
813
- LOG.error(_("Failed to set image property: %s"), e)
966
+ LOG.error(_("Failed to set image properties: %s"), e)
814
967
  result += 1
968
+
815
969
  if parsed_args.state:
816
970
  try:
817
971
  volume_client.volumes.reset_state(volume.id, parsed_args.state)
818
972
  except Exception as e:
819
973
  LOG.error(_("Failed to set volume state: %s"), e)
820
974
  result += 1
975
+
821
976
  if parsed_args.attached:
822
977
  try:
823
978
  volume_client.volumes.reset_state(
@@ -826,6 +981,7 @@ class SetVolume(command.Command):
826
981
  except Exception as e:
827
982
  LOG.error(_("Failed to set volume attach-status: %s"), e)
828
983
  result += 1
984
+
829
985
  if parsed_args.detached:
830
986
  try:
831
987
  volume_client.volumes.reset_state(
@@ -834,7 +990,8 @@ class SetVolume(command.Command):
834
990
  except Exception as e:
835
991
  LOG.error(_("Failed to set volume attach-status: %s"), e)
836
992
  result += 1
837
- if parsed_args.bootable or parsed_args.non_bootable:
993
+
994
+ if parsed_args.bootable is not None:
838
995
  try:
839
996
  volume_client.volumes.set_bootable(
840
997
  volume.id, parsed_args.bootable
@@ -842,7 +999,8 @@ class SetVolume(command.Command):
842
999
  except Exception as e:
843
1000
  LOG.error(_("Failed to set volume bootable property: %s"), e)
844
1001
  result += 1
845
- if parsed_args.read_only or parsed_args.read_write:
1002
+
1003
+ if parsed_args.read_only is not None:
846
1004
  try:
847
1005
  volume_client.volumes.update_readonly_flag(
848
1006
  volume.id, parsed_args.read_only
@@ -853,6 +1011,7 @@ class SetVolume(command.Command):
853
1011
  e,
854
1012
  )
855
1013
  result += 1
1014
+
856
1015
  policy = parsed_args.migration_policy or parsed_args.retype_policy
857
1016
  if parsed_args.type:
858
1017
  # get the migration policy
@@ -953,6 +1112,7 @@ class UnsetVolume(command.Command):
953
1112
  '--property',
954
1113
  metavar='<key>',
955
1114
  action='append',
1115
+ dest='properties',
956
1116
  help=_(
957
1117
  'Remove a property from volume '
958
1118
  '(repeat option to remove multiple properties)'
@@ -962,6 +1122,7 @@ class UnsetVolume(command.Command):
962
1122
  '--image-property',
963
1123
  metavar='<key>',
964
1124
  action='append',
1125
+ dest='image_properties',
965
1126
  help=_(
966
1127
  'Remove an image property from volume '
967
1128
  '(repeat option to remove multiple image properties)'
@@ -974,22 +1135,22 @@ class UnsetVolume(command.Command):
974
1135
  volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
975
1136
 
976
1137
  result = 0
977
- if parsed_args.property:
1138
+ if parsed_args.properties:
978
1139
  try:
979
1140
  volume_client.volumes.delete_metadata(
980
- volume.id, parsed_args.property
1141
+ volume.id, parsed_args.properties
981
1142
  )
982
1143
  except Exception as e:
983
- LOG.error(_("Failed to unset volume property: %s"), e)
1144
+ LOG.error(_("Failed to unset volume properties: %s"), e)
984
1145
  result += 1
985
1146
 
986
- if parsed_args.image_property:
1147
+ if parsed_args.image_properties:
987
1148
  try:
988
1149
  volume_client.volumes.delete_image_metadata(
989
- volume.id, parsed_args.image_property
1150
+ volume.id, parsed_args.image_properties
990
1151
  )
991
1152
  except Exception as e:
992
- LOG.error(_("Failed to unset image property: %s"), e)
1153
+ LOG.error(_("Failed to unset image properties: %s"), e)
993
1154
  result += 1
994
1155
 
995
1156
  if result > 0:
@@ -18,7 +18,6 @@ import copy
18
18
  import functools
19
19
  import logging
20
20
 
21
- from cinderclient import api_versions
22
21
  from cliff import columns as cliff_columns
23
22
  from openstack import utils as sdk_utils
24
23
  from osc_lib.cli import parseractions
@@ -512,13 +511,19 @@ class SetVolumeBackup(command.Command):
512
511
  return parser
513
512
 
514
513
  def take_action(self, parsed_args):
515
- volume_client = self.app.client_manager.volume
516
- backup = utils.find_resource(volume_client.backups, parsed_args.backup)
514
+ volume_client = self.app.client_manager.sdk_connection.volume
515
+
516
+ backup = volume_client.find_backup(
517
+ parsed_args.backup,
518
+ ignore_missing=False,
519
+ )
517
520
 
518
521
  result = 0
519
522
  if parsed_args.state:
520
523
  try:
521
- volume_client.backups.reset_state(backup.id, parsed_args.state)
524
+ volume_client.reset_backup_status(
525
+ backup, status=parsed_args.state
526
+ )
522
527
  except Exception as e:
523
528
  LOG.error(_("Failed to set backup state: %s"), e)
524
529
  result += 1
@@ -526,7 +531,7 @@ class SetVolumeBackup(command.Command):
526
531
  kwargs = {}
527
532
 
528
533
  if parsed_args.name:
529
- if volume_client.api_version < api_versions.APIVersion('3.9'):
534
+ if not sdk_utils.supports_microversion(volume_client, '3.9'):
530
535
  msg = _(
531
536
  '--os-volume-api-version 3.9 or greater is required to '
532
537
  'support the --name option'
@@ -536,7 +541,7 @@ class SetVolumeBackup(command.Command):
536
541
  kwargs['name'] = parsed_args.name
537
542
 
538
543
  if parsed_args.description:
539
- if volume_client.api_version < api_versions.APIVersion('3.9'):
544
+ if not sdk_utils.supports_microversion(volume_client, '3.9'):
540
545
  msg = _(
541
546
  '--os-volume-api-version 3.9 or greater is required to '
542
547
  'support the --description option'
@@ -546,7 +551,7 @@ class SetVolumeBackup(command.Command):
546
551
  kwargs['description'] = parsed_args.description
547
552
 
548
553
  if parsed_args.no_property:
549
- if volume_client.api_version < api_versions.APIVersion('3.43'):
554
+ if not sdk_utils.supports_microversion(volume_client, '3.43'):
550
555
  msg = _(
551
556
  '--os-volume-api-version 3.43 or greater is required to '
552
557
  'support the --no-property option'
@@ -554,14 +559,14 @@ class SetVolumeBackup(command.Command):
554
559
  raise exceptions.CommandError(msg)
555
560
 
556
561
  if parsed_args.properties:
557
- if volume_client.api_version < api_versions.APIVersion('3.43'):
562
+ if not sdk_utils.supports_microversion(volume_client, '3.43'):
558
563
  msg = _(
559
564
  '--os-volume-api-version 3.43 or greater is required to '
560
565
  'support the --property option'
561
566
  )
562
567
  raise exceptions.CommandError(msg)
563
568
 
564
- if volume_client.api_version >= api_versions.APIVersion('3.43'):
569
+ if sdk_utils.supports_microversion(volume_client, '3.43'):
565
570
  metadata = copy.deepcopy(backup.metadata)
566
571
 
567
572
  if parsed_args.no_property:
@@ -572,7 +577,7 @@ class SetVolumeBackup(command.Command):
572
577
 
573
578
  if kwargs:
574
579
  try:
575
- volume_client.backups.update(backup.id, **kwargs)
580
+ volume_client.update_backup(backup, **kwargs)
576
581
  except Exception as e:
577
582
  LOG.error("Failed to update backup: %s", e)
578
583
  result += 1
@@ -608,16 +613,18 @@ class UnsetVolumeBackup(command.Command):
608
613
  return parser
609
614
 
610
615
  def take_action(self, parsed_args):
611
- volume_client = self.app.client_manager.volume
616
+ volume_client = self.app.client_manager.sdk_connection.volume
612
617
 
613
- if volume_client.api_version < api_versions.APIVersion('3.43'):
618
+ if not sdk_utils.supports_microversion(volume_client, '3.43'):
614
619
  msg = _(
615
620
  '--os-volume-api-version 3.43 or greater is required to '
616
621
  'support the --property option'
617
622
  )
618
623
  raise exceptions.CommandError(msg)
619
624
 
620
- backup = utils.find_resource(volume_client.backups, parsed_args.backup)
625
+ backup = volume_client.find_backup(
626
+ parsed_args.backup, ignore_missing=False
627
+ )
621
628
  metadata = copy.deepcopy(backup.metadata)
622
629
 
623
630
  for key in parsed_args.properties:
@@ -632,11 +639,7 @@ class UnsetVolumeBackup(command.Command):
632
639
 
633
640
  del metadata[key]
634
641
 
635
- kwargs = {
636
- 'metadata': metadata,
637
- }
638
-
639
- volume_client.backups.update(backup.id, **kwargs)
642
+ volume_client.delete_backup_metadata(backup, keys=list(metadata))
640
643
 
641
644
 
642
645
  class ShowVolumeBackup(command.ShowOne):
@@ -653,7 +656,9 @@ class ShowVolumeBackup(command.ShowOne):
653
656
 
654
657
  def take_action(self, parsed_args):
655
658
  volume_client = self.app.client_manager.sdk_connection.volume
656
- backup = volume_client.find_backup(parsed_args.backup)
659
+ backup = volume_client.find_backup(
660
+ parsed_args.backup, ignore_missing=False
661
+ )
657
662
  columns: tuple[str, ...] = (
658
663
  "availability_zone",
659
664
  "container",