python-openstackclient 6.1.0__py3-none-any.whl → 6.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openstackclient/common/project_cleanup.py +3 -5
- openstackclient/common/quota.py +4 -6
- openstackclient/compute/v2/host.py +44 -16
- openstackclient/compute/v2/server.py +18 -24
- openstackclient/compute/v2/server_migration.py +53 -29
- openstackclient/compute/v2/server_volume.py +35 -38
- openstackclient/compute/v2/service.py +5 -5
- openstackclient/identity/common.py +12 -0
- openstackclient/identity/v3/access_rule.py +8 -6
- openstackclient/image/v2/image.py +8 -2
- openstackclient/network/v2/floating_ip_port_forwarding.py +70 -32
- openstackclient/network/v2/network_service_provider.py +16 -10
- openstackclient/tests/functional/compute/v2/test_server.py +0 -3
- openstackclient/tests/unit/compute/v2/fakes.py +122 -207
- openstackclient/tests/unit/compute/v2/test_host.py +63 -42
- openstackclient/tests/unit/compute/v2/test_server.py +1 -2
- openstackclient/tests/unit/compute/v2/test_server_migration.py +92 -95
- openstackclient/tests/unit/compute/v2/test_server_volume.py +103 -83
- openstackclient/tests/unit/identity/v3/test_access_rule.py +11 -11
- openstackclient/tests/unit/network/v2/fakes.py +31 -7
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +213 -18
- openstackclient/tests/unit/volume/v1/test_volume.py +48 -3
- openstackclient/tests/unit/volume/v2/test_consistency_group.py +2 -2
- openstackclient/tests/unit/volume/v2/test_volume.py +50 -3
- openstackclient/tests/unit/volume/v3/test_volume_group.py +47 -8
- openstackclient/volume/v1/volume.py +33 -4
- openstackclient/volume/v2/backup_record.py +8 -6
- openstackclient/volume/v2/consistency_group.py +32 -13
- openstackclient/volume/v2/volume.py +33 -4
- openstackclient/volume/v3/volume_group.py +91 -36
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/AUTHORS +5 -0
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/METADATA +1 -1
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/RECORD +38 -38
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/entry_points.txt +1 -0
- python_openstackclient-6.2.1.dist-info/pbr.json +1 -0
- python_openstackclient-6.1.0.dist-info/pbr.json +0 -1
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/LICENSE +0 -0
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/WHEEL +0 -0
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/top_level.txt +0 -0
|
@@ -28,16 +28,15 @@ from openstackclient.identity import common as identity_common
|
|
|
28
28
|
LOG = logging.getLogger(__name__)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def ask_user_yesno(msg
|
|
31
|
+
def ask_user_yesno(msg):
|
|
32
32
|
"""Ask user Y/N question
|
|
33
33
|
|
|
34
34
|
:param str msg: question text
|
|
35
|
-
:param bool default: default value
|
|
36
35
|
:return bool: User choice
|
|
37
36
|
"""
|
|
38
37
|
while True:
|
|
39
38
|
answer = getpass._raw_input(
|
|
40
|
-
'{} [{}]: '.format(msg, 'y/
|
|
39
|
+
'{} [{}]: '.format(msg, 'y/n'))
|
|
41
40
|
if answer in ('y', 'Y', 'yes'):
|
|
42
41
|
return True
|
|
43
42
|
elif answer in ('n', 'N', 'no'):
|
|
@@ -129,8 +128,7 @@ class ProjectCleanup(command.Command):
|
|
|
129
128
|
return
|
|
130
129
|
|
|
131
130
|
confirm = ask_user_yesno(
|
|
132
|
-
_("These resources will be deleted. Are you sure")
|
|
133
|
-
default=False)
|
|
131
|
+
_("These resources will be deleted. Are you sure"))
|
|
134
132
|
|
|
135
133
|
if confirm:
|
|
136
134
|
self.log.warning(_('Deleting resources'))
|
openstackclient/common/quota.py
CHANGED
|
@@ -749,12 +749,10 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
749
749
|
|
|
750
750
|
|
|
751
751
|
class ShowQuota(command.Lister):
|
|
752
|
-
_description = _(
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
"quota class."
|
|
757
|
-
)
|
|
752
|
+
_description = _("""Show quotas for project or class.
|
|
753
|
+
|
|
754
|
+
Specify ``--os-compute-api-version 2.50`` or higher to see ``server-groups``
|
|
755
|
+
and ``server-group-members`` output for a given quota class.""")
|
|
758
756
|
|
|
759
757
|
def get_parser(self, prog_name):
|
|
760
758
|
parser = super().get_parser(prog_name)
|
|
@@ -22,10 +22,10 @@ from openstackclient.i18n import _
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ListHost(command.Lister):
|
|
25
|
-
_description = _("List hosts")
|
|
25
|
+
_description = _("DEPRECATED: List hosts")
|
|
26
26
|
|
|
27
27
|
def get_parser(self, prog_name):
|
|
28
|
-
parser = super(
|
|
28
|
+
parser = super().get_parser(prog_name)
|
|
29
29
|
parser.add_argument(
|
|
30
30
|
"--zone",
|
|
31
31
|
metavar="<zone>",
|
|
@@ -34,17 +34,33 @@ class ListHost(command.Lister):
|
|
|
34
34
|
return parser
|
|
35
35
|
|
|
36
36
|
def take_action(self, parsed_args):
|
|
37
|
-
compute_client = self.app.client_manager.compute
|
|
37
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
38
38
|
columns = (
|
|
39
39
|
"Host Name",
|
|
40
40
|
"Service",
|
|
41
41
|
"Zone"
|
|
42
42
|
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
|
|
44
|
+
self.log.warning(
|
|
45
|
+
"API has been deprecated. "
|
|
46
|
+
"Please consider using 'hypervisor list' instead."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# doing this since openstacksdk has decided not to support this
|
|
50
|
+
# deprecated command
|
|
51
|
+
hosts = compute_client.get(
|
|
52
|
+
'/os-hosts', microversion='2.1'
|
|
53
|
+
).json().get('hosts')
|
|
54
|
+
|
|
55
|
+
if parsed_args.zone is not None:
|
|
56
|
+
filtered_hosts = []
|
|
57
|
+
for host in hosts:
|
|
58
|
+
if host['zone'] == parsed_args.zone:
|
|
59
|
+
filtered_hosts.append(host)
|
|
60
|
+
|
|
61
|
+
hosts = filtered_hosts
|
|
62
|
+
|
|
63
|
+
return columns, (utils.get_dict_properties(s, columns) for s in hosts)
|
|
48
64
|
|
|
49
65
|
|
|
50
66
|
class SetHost(command.Command):
|
|
@@ -102,10 +118,10 @@ class SetHost(command.Command):
|
|
|
102
118
|
|
|
103
119
|
|
|
104
120
|
class ShowHost(command.Lister):
|
|
105
|
-
_description = _("Display host details")
|
|
121
|
+
_description = _("DEPRECATED: Display host details")
|
|
106
122
|
|
|
107
123
|
def get_parser(self, prog_name):
|
|
108
|
-
parser = super(
|
|
124
|
+
parser = super().get_parser(prog_name)
|
|
109
125
|
parser.add_argument(
|
|
110
126
|
"host",
|
|
111
127
|
metavar="<host>",
|
|
@@ -114,7 +130,7 @@ class ShowHost(command.Lister):
|
|
|
114
130
|
return parser
|
|
115
131
|
|
|
116
132
|
def take_action(self, parsed_args):
|
|
117
|
-
compute_client = self.app.client_manager.compute
|
|
133
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
118
134
|
columns = (
|
|
119
135
|
"Host",
|
|
120
136
|
"Project",
|
|
@@ -123,9 +139,21 @@ class ShowHost(command.Lister):
|
|
|
123
139
|
"Disk GB"
|
|
124
140
|
)
|
|
125
141
|
|
|
126
|
-
|
|
142
|
+
self.log.warning(
|
|
143
|
+
"API has been deprecated. "
|
|
144
|
+
"Please consider using 'hypervisor show' instead."
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# doing this since openstacksdk has decided not to support this
|
|
148
|
+
# deprecated command
|
|
149
|
+
resources = compute_client.get(
|
|
150
|
+
'/os-hosts/' + parsed_args.host,
|
|
151
|
+
microversion='2.1'
|
|
152
|
+
).json().get('host')
|
|
153
|
+
|
|
154
|
+
data = []
|
|
155
|
+
if resources is not None:
|
|
156
|
+
for resource in resources:
|
|
157
|
+
data.append(resource['resource'])
|
|
127
158
|
|
|
128
|
-
return (columns
|
|
129
|
-
(utils.get_dict_properties(
|
|
130
|
-
s, columns,
|
|
131
|
-
) for s in data))
|
|
159
|
+
return columns, (utils.get_dict_properties(s, columns) for s in data)
|
|
@@ -608,10 +608,10 @@ class AddServerSecurityGroup(command.Command):
|
|
|
608
608
|
|
|
609
609
|
|
|
610
610
|
class AddServerVolume(command.ShowOne):
|
|
611
|
-
_description = _(
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
611
|
+
_description = _("""Add volume to server.
|
|
612
|
+
|
|
613
|
+
Specify ``--os-compute-api-version 2.20`` or higher to add a volume to a server
|
|
614
|
+
with status ``SHELVED`` or ``SHELVED_OFFLOADED``.""")
|
|
615
615
|
|
|
616
616
|
def get_parser(self, prog_name):
|
|
617
617
|
parser = super(AddServerVolume, self).get_parser(prog_name)
|
|
@@ -3757,11 +3757,10 @@ class RemoveServerSecurityGroup(command.Command):
|
|
|
3757
3757
|
|
|
3758
3758
|
|
|
3759
3759
|
class RemoveServerVolume(command.Command):
|
|
3760
|
-
_description = _(
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
"``SHELVED_OFFLOADED``.")
|
|
3760
|
+
_description = _("""Remove volume from server.
|
|
3761
|
+
|
|
3762
|
+
Specify ``--os-compute-api-version 2.20`` or higher to remove a
|
|
3763
|
+
volume from a server with status ``SHELVED`` or ``SHELVED_OFFLOADED``.""")
|
|
3765
3764
|
|
|
3766
3765
|
def get_parser(self, prog_name):
|
|
3767
3766
|
parser = super(RemoveServerVolume, self).get_parser(prog_name)
|
|
@@ -3798,11 +3797,10 @@ class RemoveServerVolume(command.Command):
|
|
|
3798
3797
|
|
|
3799
3798
|
|
|
3800
3799
|
class RescueServer(command.Command):
|
|
3801
|
-
_description = _(
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
)
|
|
3800
|
+
_description = _("""Put server in rescue mode.
|
|
3801
|
+
|
|
3802
|
+
Specify ``--os-compute-api-version 2.87`` or higher to rescue a
|
|
3803
|
+
server booted from a volume.""")
|
|
3806
3804
|
|
|
3807
3805
|
def get_parser(self, prog_name):
|
|
3808
3806
|
parser = super(RescueServer, self).get_parser(prog_name)
|
|
@@ -3958,9 +3956,7 @@ Confirm (verify) success of resize operation and release the old server.""")
|
|
|
3958
3956
|
|
|
3959
3957
|
# TODO(stephenfin): Remove in OSC 7.0
|
|
3960
3958
|
class MigrateConfirm(ResizeConfirm):
|
|
3961
|
-
_description = _("
|
|
3962
|
-
|
|
3963
|
-
Use 'server migration confirm' instead.""")
|
|
3959
|
+
_description = _("DEPRECATED: Use 'server migration confirm' instead.")
|
|
3964
3960
|
|
|
3965
3961
|
def take_action(self, parsed_args):
|
|
3966
3962
|
msg = _(
|
|
@@ -4006,9 +4002,7 @@ one.""")
|
|
|
4006
4002
|
|
|
4007
4003
|
# TODO(stephenfin): Remove in OSC 7.0
|
|
4008
4004
|
class MigrateRevert(ResizeRevert):
|
|
4009
|
-
_description = _("
|
|
4010
|
-
|
|
4011
|
-
Use 'server migration revert' instead.""")
|
|
4005
|
+
_description = _("DEPRECATED: Use 'server migration revert' instead.")
|
|
4012
4006
|
|
|
4013
4007
|
def take_action(self, parsed_args):
|
|
4014
4008
|
msg = _(
|
|
@@ -4346,10 +4340,10 @@ class ShelveServer(command.Command):
|
|
|
4346
4340
|
|
|
4347
4341
|
|
|
4348
4342
|
class ShowServer(command.ShowOne):
|
|
4349
|
-
_description = _(
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4343
|
+
_description = _("""Show server details.
|
|
4344
|
+
|
|
4345
|
+
Specify ``--os-compute-api-version 2.47`` or higher to see the embedded flavor
|
|
4346
|
+
information for the server.""")
|
|
4353
4347
|
|
|
4354
4348
|
def get_parser(self, prog_name):
|
|
4355
4349
|
parser = super(ShowServer, self).get_parser(prog_name)
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
import uuid
|
|
16
16
|
|
|
17
|
-
from novaclient import api_versions
|
|
18
17
|
from openstack import utils as sdk_utils
|
|
19
18
|
from osc_lib.command import command
|
|
20
19
|
from osc_lib import exceptions
|
|
@@ -256,7 +255,7 @@ class ListMigration(command.Lister):
|
|
|
256
255
|
|
|
257
256
|
|
|
258
257
|
def _get_migration_by_uuid(compute_client, server_id, migration_uuid):
|
|
259
|
-
for migration in compute_client.server_migrations
|
|
258
|
+
for migration in compute_client.server_migrations(server_id):
|
|
260
259
|
if migration.uuid == migration_uuid:
|
|
261
260
|
return migration
|
|
262
261
|
break
|
|
@@ -290,9 +289,9 @@ class ShowMigration(command.ShowOne):
|
|
|
290
289
|
return parser
|
|
291
290
|
|
|
292
291
|
def take_action(self, parsed_args):
|
|
293
|
-
compute_client = self.app.client_manager.compute
|
|
292
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
294
293
|
|
|
295
|
-
if
|
|
294
|
+
if not sdk_utils.supports_microversion(compute_client, '2.24'):
|
|
296
295
|
msg = _(
|
|
297
296
|
'--os-compute-api-version 2.24 or greater is required to '
|
|
298
297
|
'support the server migration show command'
|
|
@@ -308,16 +307,16 @@ class ShowMigration(command.ShowOne):
|
|
|
308
307
|
)
|
|
309
308
|
raise exceptions.CommandError(msg)
|
|
310
309
|
|
|
311
|
-
if
|
|
310
|
+
if not sdk_utils.supports_microversion(compute_client, '2.59'):
|
|
312
311
|
msg = _(
|
|
313
312
|
'--os-compute-api-version 2.59 or greater is required to '
|
|
314
313
|
'retrieve server migrations by UUID'
|
|
315
314
|
)
|
|
316
315
|
raise exceptions.CommandError(msg)
|
|
317
316
|
|
|
318
|
-
server =
|
|
319
|
-
compute_client.servers,
|
|
317
|
+
server = compute_client.find_server(
|
|
320
318
|
parsed_args.server,
|
|
319
|
+
ignore_missing=False,
|
|
321
320
|
)
|
|
322
321
|
|
|
323
322
|
# the nova API doesn't currently allow retrieval by UUID but it's a
|
|
@@ -328,11 +327,13 @@ class ShowMigration(command.ShowOne):
|
|
|
328
327
|
compute_client, server.id, parsed_args.migration,
|
|
329
328
|
)
|
|
330
329
|
else:
|
|
331
|
-
server_migration = compute_client.
|
|
332
|
-
server.id,
|
|
330
|
+
server_migration = compute_client.get_server_migration(
|
|
331
|
+
server.id,
|
|
332
|
+
parsed_args.migration,
|
|
333
|
+
ignore_missing=False,
|
|
333
334
|
)
|
|
334
335
|
|
|
335
|
-
|
|
336
|
+
column_headers = (
|
|
336
337
|
'ID',
|
|
337
338
|
'Server UUID',
|
|
338
339
|
'Status',
|
|
@@ -351,14 +352,35 @@ class ShowMigration(command.ShowOne):
|
|
|
351
352
|
'Updated At',
|
|
352
353
|
)
|
|
353
354
|
|
|
354
|
-
|
|
355
|
-
|
|
355
|
+
columns = (
|
|
356
|
+
'id',
|
|
357
|
+
'server_id',
|
|
358
|
+
'status',
|
|
359
|
+
'source_compute',
|
|
360
|
+
'source_node',
|
|
361
|
+
'dest_compute',
|
|
362
|
+
'dest_host',
|
|
363
|
+
'dest_node',
|
|
364
|
+
'memory_total_bytes',
|
|
365
|
+
'memory_processed_bytes',
|
|
366
|
+
'memory_remaining_bytes',
|
|
367
|
+
'disk_total_bytes',
|
|
368
|
+
'disk_processed_bytes',
|
|
369
|
+
'disk_remaining_bytes',
|
|
370
|
+
'created_at',
|
|
371
|
+
'updated_at',
|
|
372
|
+
)
|
|
356
373
|
|
|
357
|
-
if compute_client
|
|
358
|
-
|
|
374
|
+
if sdk_utils.supports_microversion(compute_client, '2.59'):
|
|
375
|
+
column_headers += ('UUID',)
|
|
376
|
+
columns += ('uuid',)
|
|
377
|
+
|
|
378
|
+
if sdk_utils.supports_microversion(compute_client, '2.80'):
|
|
379
|
+
column_headers += ('User ID', 'Project ID')
|
|
380
|
+
columns += ('user_id', 'project_id')
|
|
359
381
|
|
|
360
382
|
data = utils.get_item_properties(server_migration, columns)
|
|
361
|
-
return
|
|
383
|
+
return column_headers, data
|
|
362
384
|
|
|
363
385
|
|
|
364
386
|
class AbortMigration(command.Command):
|
|
@@ -382,9 +404,9 @@ class AbortMigration(command.Command):
|
|
|
382
404
|
return parser
|
|
383
405
|
|
|
384
406
|
def take_action(self, parsed_args):
|
|
385
|
-
compute_client = self.app.client_manager.compute
|
|
407
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
386
408
|
|
|
387
|
-
if
|
|
409
|
+
if not sdk_utils.supports_microversion(compute_client, '2.24'):
|
|
388
410
|
msg = _(
|
|
389
411
|
'--os-compute-api-version 2.24 or greater is required to '
|
|
390
412
|
'support the server migration abort command'
|
|
@@ -400,16 +422,16 @@ class AbortMigration(command.Command):
|
|
|
400
422
|
)
|
|
401
423
|
raise exceptions.CommandError(msg)
|
|
402
424
|
|
|
403
|
-
if
|
|
425
|
+
if not sdk_utils.supports_microversion(compute_client, '2.59'):
|
|
404
426
|
msg = _(
|
|
405
427
|
'--os-compute-api-version 2.59 or greater is required to '
|
|
406
428
|
'abort server migrations by UUID'
|
|
407
429
|
)
|
|
408
430
|
raise exceptions.CommandError(msg)
|
|
409
431
|
|
|
410
|
-
server =
|
|
411
|
-
compute_client.servers,
|
|
432
|
+
server = compute_client.find_server(
|
|
412
433
|
parsed_args.server,
|
|
434
|
+
ignore_missing=False,
|
|
413
435
|
)
|
|
414
436
|
|
|
415
437
|
# the nova API doesn't currently allow retrieval by UUID but it's a
|
|
@@ -421,8 +443,10 @@ class AbortMigration(command.Command):
|
|
|
421
443
|
compute_client, server.id, parsed_args.migration,
|
|
422
444
|
).id
|
|
423
445
|
|
|
424
|
-
compute_client.
|
|
425
|
-
|
|
446
|
+
compute_client.abort_server_migration(
|
|
447
|
+
migration_id,
|
|
448
|
+
server.id,
|
|
449
|
+
ignore_missing=False,
|
|
426
450
|
)
|
|
427
451
|
|
|
428
452
|
|
|
@@ -447,9 +471,9 @@ class ForceCompleteMigration(command.Command):
|
|
|
447
471
|
return parser
|
|
448
472
|
|
|
449
473
|
def take_action(self, parsed_args):
|
|
450
|
-
compute_client = self.app.client_manager.compute
|
|
474
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
451
475
|
|
|
452
|
-
if
|
|
476
|
+
if not sdk_utils.supports_microversion(compute_client, '2.22'):
|
|
453
477
|
msg = _(
|
|
454
478
|
'--os-compute-api-version 2.22 or greater is required to '
|
|
455
479
|
'support the server migration force complete command'
|
|
@@ -465,16 +489,16 @@ class ForceCompleteMigration(command.Command):
|
|
|
465
489
|
)
|
|
466
490
|
raise exceptions.CommandError(msg)
|
|
467
491
|
|
|
468
|
-
if
|
|
492
|
+
if not sdk_utils.supports_microversion(compute_client, '2.59'):
|
|
469
493
|
msg = _(
|
|
470
494
|
'--os-compute-api-version 2.59 or greater is required to '
|
|
471
495
|
'abort server migrations by UUID'
|
|
472
496
|
)
|
|
473
497
|
raise exceptions.CommandError(msg)
|
|
474
498
|
|
|
475
|
-
server =
|
|
476
|
-
compute_client.servers,
|
|
499
|
+
server = compute_client.find_server(
|
|
477
500
|
parsed_args.server,
|
|
501
|
+
ignore_missing=False,
|
|
478
502
|
)
|
|
479
503
|
|
|
480
504
|
# the nova API doesn't currently allow retrieval by UUID but it's a
|
|
@@ -486,6 +510,6 @@ class ForceCompleteMigration(command.Command):
|
|
|
486
510
|
compute_client, server.id, parsed_args.migration,
|
|
487
511
|
).id
|
|
488
512
|
|
|
489
|
-
compute_client.
|
|
490
|
-
server.id
|
|
513
|
+
compute_client.force_complete_server_migration(
|
|
514
|
+
migration_id, server.id
|
|
491
515
|
)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
"""Compute v2 Server action implementations"""
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from openstack import utils as sdk_utils
|
|
18
18
|
from osc_lib.command import command
|
|
19
19
|
from osc_lib import exceptions
|
|
20
20
|
from osc_lib import utils
|
|
@@ -34,27 +34,25 @@ class ListServerVolume(command.Lister):
|
|
|
34
34
|
return parser
|
|
35
35
|
|
|
36
36
|
def take_action(self, parsed_args):
|
|
37
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
server = utils.find_resource(
|
|
41
|
-
compute_client.servers,
|
|
39
|
+
server = compute_client.find_server(
|
|
42
40
|
parsed_args.server,
|
|
41
|
+
ignore_missing=False,
|
|
43
42
|
)
|
|
44
|
-
|
|
45
|
-
volumes = compute_client.volumes.get_server_volumes(server.id)
|
|
43
|
+
volumes = compute_client.volume_attachments(server)
|
|
46
44
|
|
|
47
45
|
columns = ()
|
|
48
46
|
column_headers = ()
|
|
49
47
|
|
|
50
|
-
if
|
|
48
|
+
if not sdk_utils.supports_microversion(compute_client, '2.89'):
|
|
51
49
|
columns += ('id',)
|
|
52
50
|
column_headers += ('ID',)
|
|
53
51
|
|
|
54
52
|
columns += (
|
|
55
53
|
'device',
|
|
56
|
-
'
|
|
57
|
-
'
|
|
54
|
+
'server_id',
|
|
55
|
+
'volume_id',
|
|
58
56
|
)
|
|
59
57
|
column_headers += (
|
|
60
58
|
'Device',
|
|
@@ -62,40 +60,36 @@ class ListServerVolume(command.Lister):
|
|
|
62
60
|
'Volume ID',
|
|
63
61
|
)
|
|
64
62
|
|
|
65
|
-
if compute_client
|
|
63
|
+
if sdk_utils.supports_microversion(compute_client, '2.70'):
|
|
66
64
|
columns += ('tag',)
|
|
67
65
|
column_headers += ('Tag',)
|
|
68
66
|
|
|
69
|
-
if compute_client
|
|
67
|
+
if sdk_utils.supports_microversion(compute_client, '2.79'):
|
|
70
68
|
columns += ('delete_on_termination',)
|
|
71
69
|
column_headers += ('Delete On Termination?',)
|
|
72
70
|
|
|
73
|
-
if compute_client
|
|
74
|
-
columns += ('attachment_id', '
|
|
71
|
+
if sdk_utils.supports_microversion(compute_client, '2.89'):
|
|
72
|
+
columns += ('attachment_id', 'bdm_id')
|
|
75
73
|
column_headers += ('Attachment ID', 'BlockDeviceMapping UUID')
|
|
76
74
|
|
|
77
75
|
return (
|
|
78
76
|
column_headers,
|
|
79
|
-
(
|
|
80
|
-
utils.get_item_properties(
|
|
81
|
-
s, columns, mixed_case_fields=('serverId', 'volumeId')
|
|
82
|
-
) for s in volumes
|
|
83
|
-
),
|
|
77
|
+
(utils.get_item_properties(s, columns) for s in volumes),
|
|
84
78
|
)
|
|
85
79
|
|
|
86
80
|
|
|
87
|
-
class
|
|
81
|
+
class SetServerVolume(command.Command):
|
|
88
82
|
"""Update a volume attachment on the server."""
|
|
89
83
|
|
|
90
84
|
def get_parser(self, prog_name):
|
|
91
|
-
parser = super(
|
|
85
|
+
parser = super().get_parser(prog_name)
|
|
92
86
|
parser.add_argument(
|
|
93
87
|
'server',
|
|
94
88
|
help=_('Server to update volume for (name or ID)'),
|
|
95
89
|
)
|
|
96
90
|
parser.add_argument(
|
|
97
91
|
'volume',
|
|
98
|
-
help=_('Volume (ID)'),
|
|
92
|
+
help=_('Volume to update attachment for (name or ID)'),
|
|
99
93
|
)
|
|
100
94
|
termination_group = parser.add_mutually_exclusive_group()
|
|
101
95
|
termination_group.add_argument(
|
|
@@ -120,31 +114,34 @@ class UpdateServerVolume(command.Command):
|
|
|
120
114
|
return parser
|
|
121
115
|
|
|
122
116
|
def take_action(self, parsed_args):
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
118
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
125
119
|
|
|
126
120
|
if parsed_args.delete_on_termination is not None:
|
|
127
|
-
if
|
|
121
|
+
if not sdk_utils.supports_microversion(compute_client, '2.85'):
|
|
128
122
|
msg = _(
|
|
129
123
|
'--os-compute-api-version 2.85 or greater is required to '
|
|
130
|
-
'support the
|
|
124
|
+
'support the -delete-on-termination or '
|
|
125
|
+
'--preserve-on-termination option'
|
|
131
126
|
)
|
|
132
127
|
raise exceptions.CommandError(msg)
|
|
133
128
|
|
|
134
|
-
server =
|
|
135
|
-
compute_client.servers,
|
|
129
|
+
server = compute_client.find_server(
|
|
136
130
|
parsed_args.server,
|
|
131
|
+
ignore_missing=False,
|
|
137
132
|
)
|
|
138
|
-
|
|
139
|
-
# NOTE(stephenfin): This may look silly, and that's because it is.
|
|
140
|
-
# This API was originally used only for the swapping volumes, which
|
|
141
|
-
# is an internal operation that should only be done by
|
|
142
|
-
# orchestration software rather than a human. We're not going to
|
|
143
|
-
# expose that, but we are going to expose the ability to change the
|
|
144
|
-
# delete on termination behavior.
|
|
145
|
-
compute_client.volumes.update_server_volume(
|
|
146
|
-
server.id,
|
|
147
|
-
parsed_args.volume,
|
|
133
|
+
volume = volume_client.find_volume(
|
|
148
134
|
parsed_args.volume,
|
|
135
|
+
ignore_missing=False,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
compute_client.update_volume_attachment(
|
|
139
|
+
server,
|
|
140
|
+
volume,
|
|
149
141
|
delete_on_termination=parsed_args.delete_on_termination,
|
|
150
142
|
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# Legacy alias
|
|
146
|
+
class UpdateServerVolume(SetServerVolume):
|
|
147
|
+
"""DEPRECATED: Use 'server volume set' instead."""
|
|
@@ -71,11 +71,11 @@ class DeleteService(command.Command):
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
class ListService(command.Lister):
|
|
74
|
-
_description = _("List compute services.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
_description = _("""List compute services.
|
|
75
|
+
|
|
76
|
+
Using ``--os-compute-api-version`` 2.53 or greater will return the ID as a UUID
|
|
77
|
+
value which can be used to uniquely identify the service in a multi-cell
|
|
78
|
+
deployment.""")
|
|
79
79
|
|
|
80
80
|
def get_parser(self, prog_name):
|
|
81
81
|
parser = super(ListService, self).get_parser(prog_name)
|
|
@@ -87,6 +87,18 @@ def get_resource(manager, name_type_or_id):
|
|
|
87
87
|
raise exceptions.CommandError(msg % name_type_or_id)
|
|
88
88
|
|
|
89
89
|
|
|
90
|
+
def get_resource_by_id(manager, resource_id):
|
|
91
|
+
"""Get resource by ID
|
|
92
|
+
|
|
93
|
+
Raises CommandError if the resource is not found
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
return manager.get(resource_id)
|
|
97
|
+
except identity_exc.NotFound:
|
|
98
|
+
msg = _("Resource with id {} not found")
|
|
99
|
+
raise exceptions.CommandError(msg.format(resource_id))
|
|
100
|
+
|
|
101
|
+
|
|
90
102
|
def _get_token_resource(client, resource, parsed_name, parsed_domain=None):
|
|
91
103
|
"""Peek into the user's auth token to get resource IDs
|
|
92
104
|
|
|
@@ -37,7 +37,7 @@ class DeleteAccessRule(command.Command):
|
|
|
37
37
|
'access_rule',
|
|
38
38
|
metavar='<access-rule>',
|
|
39
39
|
nargs="+",
|
|
40
|
-
help=_('Access rule(s) to delete
|
|
40
|
+
help=_('Access rule ID(s) to delete'),
|
|
41
41
|
)
|
|
42
42
|
return parser
|
|
43
43
|
|
|
@@ -47,8 +47,9 @@ class DeleteAccessRule(command.Command):
|
|
|
47
47
|
errors = 0
|
|
48
48
|
for ac in parsed_args.access_rule:
|
|
49
49
|
try:
|
|
50
|
-
access_rule =
|
|
51
|
-
identity_client.access_rules, ac
|
|
50
|
+
access_rule = common.get_resource_by_id(
|
|
51
|
+
identity_client.access_rules, ac
|
|
52
|
+
)
|
|
52
53
|
identity_client.access_rules.delete(access_rule.id)
|
|
53
54
|
except Exception as e:
|
|
54
55
|
errors += 1
|
|
@@ -103,14 +104,15 @@ class ShowAccessRule(command.ShowOne):
|
|
|
103
104
|
parser.add_argument(
|
|
104
105
|
'access_rule',
|
|
105
106
|
metavar='<access-rule>',
|
|
106
|
-
help=_('Access rule to display
|
|
107
|
+
help=_('Access rule ID to display'),
|
|
107
108
|
)
|
|
108
109
|
return parser
|
|
109
110
|
|
|
110
111
|
def take_action(self, parsed_args):
|
|
111
112
|
identity_client = self.app.client_manager.identity
|
|
112
|
-
access_rule =
|
|
113
|
-
|
|
113
|
+
access_rule = common.get_resource_by_id(
|
|
114
|
+
identity_client.access_rules, parsed_args.access_rule
|
|
115
|
+
)
|
|
114
116
|
|
|
115
117
|
access_rule._info.pop('links', None)
|
|
116
118
|
|
|
@@ -1206,7 +1206,10 @@ class SetImage(command.Command):
|
|
|
1206
1206
|
const="accepted",
|
|
1207
1207
|
dest="membership",
|
|
1208
1208
|
default=None,
|
|
1209
|
-
help=_(
|
|
1209
|
+
help=_(
|
|
1210
|
+
"Accept the image membership for either the project indicated "
|
|
1211
|
+
"by '--project', if provided, or the current user's project"
|
|
1212
|
+
),
|
|
1210
1213
|
)
|
|
1211
1214
|
membership_group.add_argument(
|
|
1212
1215
|
"--reject",
|
|
@@ -1214,7 +1217,10 @@ class SetImage(command.Command):
|
|
|
1214
1217
|
const="rejected",
|
|
1215
1218
|
dest="membership",
|
|
1216
1219
|
default=None,
|
|
1217
|
-
help=_(
|
|
1220
|
+
help=_(
|
|
1221
|
+
"Reject the image membership for either the project indicated "
|
|
1222
|
+
"by '--project', if provided, or the current user's project"
|
|
1223
|
+
),
|
|
1218
1224
|
)
|
|
1219
1225
|
membership_group.add_argument(
|
|
1220
1226
|
"--pending",
|