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.
- openstackclient/compute/client.py +5 -0
- openstackclient/compute/v2/console.py +7 -0
- openstackclient/compute/v2/console_connection.py +48 -0
- openstackclient/compute/v2/keypair.py +10 -3
- openstackclient/compute/v2/server.py +75 -10
- openstackclient/compute/v2/server_event.py +1 -1
- openstackclient/identity/common.py +79 -0
- openstackclient/identity/v3/application_credential.py +2 -2
- openstackclient/identity/v3/domain.py +62 -43
- openstackclient/identity/v3/group.py +113 -68
- openstackclient/identity/v3/project.py +17 -0
- openstackclient/identity/v3/user.py +38 -5
- openstackclient/image/client.py +5 -0
- openstackclient/image/v2/image.py +11 -11
- openstackclient/network/client.py +0 -6
- openstackclient/network/v2/floating_ip.py +58 -29
- openstackclient/network/v2/network_qos_rule.py +3 -11
- openstackclient/network/v2/router.py +1 -1
- openstackclient/network/v2/security_group.py +5 -4
- openstackclient/network/v2/security_group_rule.py +1 -1
- openstackclient/shell.py +1 -1
- openstackclient/tests/functional/base.py +5 -1
- openstackclient/tests/functional/compute/v2/test_keypair.py +41 -5
- openstackclient/tests/unit/compute/v2/fakes.py +81 -305
- openstackclient/tests/unit/compute/v2/test_console.py +18 -1
- openstackclient/tests/unit/compute/v2/test_console_connection.py +72 -0
- openstackclient/tests/unit/compute/v2/test_flavor.py +1 -1
- openstackclient/tests/unit/compute/v2/test_keypair.py +12 -5
- openstackclient/tests/unit/compute/v2/test_server.py +169 -46
- openstackclient/tests/unit/compute/v2/test_server_backup.py +32 -71
- openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
- openstackclient/tests/unit/compute/v2/test_server_image.py +33 -72
- openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
- openstackclient/tests/unit/identity/v3/test_application_credential.py +47 -25
- openstackclient/tests/unit/identity/v3/test_domain.py +115 -105
- openstackclient/tests/unit/identity/v3/test_group.py +353 -202
- openstackclient/tests/unit/identity/v3/test_project.py +16 -0
- openstackclient/tests/unit/identity/v3/test_user.py +86 -6
- openstackclient/tests/unit/image/v1/test_image.py +8 -9
- openstackclient/tests/unit/image/v2/test_image.py +49 -49
- openstackclient/tests/unit/network/v2/fakes.py +405 -485
- openstackclient/tests/unit/network/v2/test_floating_ip_network.py +13 -19
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +2 -2
- openstackclient/tests/unit/network/v2/test_ndp_proxy.py +1 -3
- openstackclient/tests/unit/network/v2/test_network.py +4 -4
- openstackclient/tests/unit/network/v2/test_network_agent.py +15 -29
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +16 -19
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +79 -152
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +4 -6
- openstackclient/tests/unit/network/v2/test_network_rbac.py +2 -2
- openstackclient/tests/unit/network/v2/test_port.py +17 -17
- openstackclient/tests/unit/network/v2/test_router.py +73 -57
- openstackclient/tests/unit/network/v2/test_security_group_network.py +25 -27
- openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +1 -3
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +33 -39
- openstackclient/tests/unit/volume/v2/fakes.py +1 -2
- openstackclient/tests/unit/volume/v2/test_service.py +57 -91
- openstackclient/tests/unit/volume/v2/test_volume.py +108 -105
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +141 -148
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +293 -283
- openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +61 -71
- openstackclient/tests/unit/volume/v3/test_service.py +221 -141
- openstackclient/tests/unit/volume/v3/test_volume.py +130 -119
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +198 -203
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +682 -47
- openstackclient/volume/v2/service.py +41 -38
- openstackclient/volume/v2/volume.py +63 -37
- openstackclient/volume/v2/volume_backup.py +9 -3
- openstackclient/volume/v2/volume_snapshot.py +121 -84
- openstackclient/volume/v3/block_storage_log_level.py +22 -28
- openstackclient/volume/v3/service.py +105 -14
- openstackclient/volume/v3/volume.py +200 -39
- openstackclient/volume/v3/volume_backup.py +24 -19
- openstackclient/volume/v3/volume_snapshot.py +485 -10
- {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/AUTHORS +8 -0
- python_openstackclient-8.1.0.dist-info/METADATA +264 -0
- {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/RECORD +83 -81
- {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/entry_points.txt +7 -6
- python_openstackclient-8.1.0.dist-info/pbr.json +1 -0
- python_openstackclient-8.0.0.dist-info/METADATA +0 -166
- python_openstackclient-8.0.0.dist-info/pbr.json +0 -1
- {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/LICENSE +0 -0
- {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.1.0.dist-info}/top_level.txt +0 -0
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import logging
|
|
19
19
|
|
|
20
|
-
from
|
|
20
|
+
from openstack import exceptions as sdk_exc
|
|
21
21
|
from osc_lib.command import command
|
|
22
22
|
from osc_lib import exceptions
|
|
23
23
|
from osc_lib import utils
|
|
@@ -29,6 +29,25 @@ from openstackclient.identity import common
|
|
|
29
29
|
LOG = logging.getLogger(__name__)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def _format_group(group):
|
|
33
|
+
columns = (
|
|
34
|
+
'description',
|
|
35
|
+
'domain_id',
|
|
36
|
+
'id',
|
|
37
|
+
'name',
|
|
38
|
+
)
|
|
39
|
+
column_headers = (
|
|
40
|
+
'description',
|
|
41
|
+
'domain_id',
|
|
42
|
+
'id',
|
|
43
|
+
'name',
|
|
44
|
+
)
|
|
45
|
+
return (
|
|
46
|
+
column_headers,
|
|
47
|
+
utils.get_item_properties(group, columns),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
32
51
|
class AddUserToGroup(command.Command):
|
|
33
52
|
_description = _("Add user to group")
|
|
34
53
|
|
|
@@ -53,19 +72,19 @@ class AddUserToGroup(command.Command):
|
|
|
53
72
|
return parser
|
|
54
73
|
|
|
55
74
|
def take_action(self, parsed_args):
|
|
56
|
-
identity_client = self.app.client_manager.identity
|
|
75
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
57
76
|
|
|
58
|
-
group_id = common.
|
|
77
|
+
group_id = common.find_group_id_sdk(
|
|
59
78
|
identity_client, parsed_args.group, parsed_args.group_domain
|
|
60
|
-
)
|
|
79
|
+
)
|
|
61
80
|
|
|
62
81
|
result = 0
|
|
63
82
|
for i in parsed_args.user:
|
|
64
83
|
try:
|
|
65
|
-
user_id = common.
|
|
84
|
+
user_id = common.find_user_id_sdk(
|
|
66
85
|
identity_client, i, parsed_args.user_domain
|
|
67
|
-
)
|
|
68
|
-
identity_client.
|
|
86
|
+
)
|
|
87
|
+
identity_client.add_user_to_group(user_id, group_id)
|
|
69
88
|
except Exception as e:
|
|
70
89
|
result += 1
|
|
71
90
|
msg = _("%(user)s not added to group %(group)s: %(e)s") % {
|
|
@@ -109,32 +128,41 @@ class CheckUserInGroup(command.Command):
|
|
|
109
128
|
return parser
|
|
110
129
|
|
|
111
130
|
def take_action(self, parsed_args):
|
|
112
|
-
identity_client = self.app.client_manager.identity
|
|
131
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
113
132
|
|
|
114
|
-
user_id = common.
|
|
115
|
-
identity_client,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
133
|
+
user_id = common.find_user_id_sdk(
|
|
134
|
+
identity_client,
|
|
135
|
+
parsed_args.user,
|
|
136
|
+
parsed_args.user_domain,
|
|
137
|
+
validate_actor_existence=False,
|
|
138
|
+
)
|
|
139
|
+
group_id = common.find_group_id_sdk(
|
|
140
|
+
identity_client,
|
|
141
|
+
parsed_args.group,
|
|
142
|
+
parsed_args.group_domain,
|
|
143
|
+
validate_actor_existence=False,
|
|
144
|
+
)
|
|
120
145
|
|
|
146
|
+
user_in_group = False
|
|
121
147
|
try:
|
|
122
|
-
identity_client.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
self.app.stderr.write(msg)
|
|
130
|
-
else:
|
|
131
|
-
raise e
|
|
132
|
-
else:
|
|
148
|
+
user_in_group = identity_client.check_user_in_group(
|
|
149
|
+
user_id, group_id
|
|
150
|
+
)
|
|
151
|
+
except sdk_exc.ForbiddenException:
|
|
152
|
+
# Assume False if forbidden
|
|
153
|
+
pass
|
|
154
|
+
if user_in_group:
|
|
133
155
|
msg = _("%(user)s in group %(group)s\n") % {
|
|
134
156
|
'user': parsed_args.user,
|
|
135
157
|
'group': parsed_args.group,
|
|
136
158
|
}
|
|
137
159
|
self.app.stdout.write(msg)
|
|
160
|
+
else:
|
|
161
|
+
msg = _("%(user)s not in group %(group)s\n") % {
|
|
162
|
+
'user': parsed_args.user,
|
|
163
|
+
'group': parsed_args.group,
|
|
164
|
+
}
|
|
165
|
+
self.app.stderr.write(msg)
|
|
138
166
|
|
|
139
167
|
|
|
140
168
|
class CreateGroup(command.ShowOne):
|
|
@@ -165,29 +193,33 @@ class CreateGroup(command.ShowOne):
|
|
|
165
193
|
return parser
|
|
166
194
|
|
|
167
195
|
def take_action(self, parsed_args):
|
|
168
|
-
identity_client = self.app.client_manager.identity
|
|
196
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
169
197
|
|
|
170
|
-
|
|
198
|
+
kwargs = {}
|
|
199
|
+
if parsed_args.name:
|
|
200
|
+
kwargs['name'] = parsed_args.name
|
|
201
|
+
if parsed_args.description:
|
|
202
|
+
kwargs['description'] = parsed_args.description
|
|
171
203
|
if parsed_args.domain:
|
|
172
|
-
|
|
204
|
+
kwargs['domain_id'] = common.find_domain_id_sdk(
|
|
205
|
+
identity_client, parsed_args.domain
|
|
206
|
+
)
|
|
173
207
|
|
|
174
208
|
try:
|
|
175
|
-
group = identity_client.
|
|
176
|
-
|
|
177
|
-
domain=domain,
|
|
178
|
-
description=parsed_args.description,
|
|
179
|
-
)
|
|
180
|
-
except ks_exc.Conflict:
|
|
209
|
+
group = identity_client.create_group(**kwargs)
|
|
210
|
+
except sdk_exc.ConflictException:
|
|
181
211
|
if parsed_args.or_show:
|
|
182
|
-
|
|
183
|
-
identity_client.
|
|
184
|
-
|
|
212
|
+
if parsed_args.domain:
|
|
213
|
+
group = identity_client.find_group(
|
|
214
|
+
parsed_args.name, domain_id=parsed_args.domain
|
|
215
|
+
)
|
|
216
|
+
else:
|
|
217
|
+
group = identity_client.find_group(parsed_args.name)
|
|
185
218
|
LOG.info(_('Returning existing group %s'), group.name)
|
|
186
219
|
else:
|
|
187
220
|
raise
|
|
188
221
|
|
|
189
|
-
group
|
|
190
|
-
return zip(*sorted(group._info.items()))
|
|
222
|
+
return _format_group(group)
|
|
191
223
|
|
|
192
224
|
|
|
193
225
|
class DeleteGroup(command.Command):
|
|
@@ -209,15 +241,15 @@ class DeleteGroup(command.Command):
|
|
|
209
241
|
return parser
|
|
210
242
|
|
|
211
243
|
def take_action(self, parsed_args):
|
|
212
|
-
identity_client = self.app.client_manager.identity
|
|
244
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
213
245
|
|
|
214
246
|
errors = 0
|
|
215
247
|
for group in parsed_args.groups:
|
|
216
248
|
try:
|
|
217
|
-
|
|
249
|
+
group_id = common.find_group_id_sdk(
|
|
218
250
|
identity_client, group, parsed_args.domain
|
|
219
251
|
)
|
|
220
|
-
identity_client.
|
|
252
|
+
identity_client.delete_group(group_id)
|
|
221
253
|
except Exception as e:
|
|
222
254
|
errors += 1
|
|
223
255
|
LOG.error(
|
|
@@ -262,29 +294,37 @@ class ListGroup(command.Lister):
|
|
|
262
294
|
return parser
|
|
263
295
|
|
|
264
296
|
def take_action(self, parsed_args):
|
|
265
|
-
identity_client = self.app.client_manager.identity
|
|
297
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
266
298
|
|
|
267
299
|
domain = None
|
|
268
300
|
if parsed_args.domain:
|
|
269
|
-
domain = common.
|
|
301
|
+
domain = common.find_domain_id_sdk(
|
|
302
|
+
identity_client, parsed_args.domain
|
|
303
|
+
)
|
|
270
304
|
|
|
305
|
+
data = []
|
|
271
306
|
if parsed_args.user:
|
|
272
|
-
user = common.
|
|
307
|
+
user = common.find_user_id_sdk(
|
|
273
308
|
identity_client,
|
|
274
309
|
parsed_args.user,
|
|
275
310
|
parsed_args.user_domain,
|
|
276
|
-
)
|
|
311
|
+
)
|
|
312
|
+
if domain:
|
|
313
|
+
# NOTE(0weng): The API doesn't actually support filtering additionally by domain_id,
|
|
314
|
+
# so this doesn't really do anything.
|
|
315
|
+
data = identity_client.user_groups(user, domain_id=domain)
|
|
316
|
+
else:
|
|
317
|
+
data = identity_client.user_groups(user)
|
|
277
318
|
else:
|
|
278
|
-
|
|
319
|
+
if domain:
|
|
320
|
+
data = identity_client.groups(domain_id=domain)
|
|
321
|
+
else:
|
|
322
|
+
data = identity_client.groups()
|
|
279
323
|
|
|
280
324
|
# List groups
|
|
281
325
|
columns: tuple[str, ...] = ('ID', 'Name')
|
|
282
326
|
if parsed_args.long:
|
|
283
327
|
columns += ('Domain ID', 'Description')
|
|
284
|
-
data = identity_client.groups.list(
|
|
285
|
-
domain=domain,
|
|
286
|
-
user=user,
|
|
287
|
-
)
|
|
288
328
|
|
|
289
329
|
return (
|
|
290
330
|
columns,
|
|
@@ -323,19 +363,19 @@ class RemoveUserFromGroup(command.Command):
|
|
|
323
363
|
return parser
|
|
324
364
|
|
|
325
365
|
def take_action(self, parsed_args):
|
|
326
|
-
identity_client = self.app.client_manager.identity
|
|
366
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
327
367
|
|
|
328
|
-
group_id = common.
|
|
368
|
+
group_id = common.find_group_id_sdk(
|
|
329
369
|
identity_client, parsed_args.group, parsed_args.group_domain
|
|
330
|
-
)
|
|
370
|
+
)
|
|
331
371
|
|
|
332
372
|
result = 0
|
|
333
373
|
for i in parsed_args.user:
|
|
334
374
|
try:
|
|
335
|
-
user_id = common.
|
|
375
|
+
user_id = common.find_user_id_sdk(
|
|
336
376
|
identity_client, i, parsed_args.user_domain
|
|
337
|
-
)
|
|
338
|
-
identity_client.
|
|
377
|
+
)
|
|
378
|
+
identity_client.remove_user_from_group(user_id, group_id)
|
|
339
379
|
except Exception as e:
|
|
340
380
|
result += 1
|
|
341
381
|
msg = _("%(user)s not removed from group %(group)s: %(e)s") % {
|
|
@@ -387,8 +427,8 @@ class SetGroup(command.Command):
|
|
|
387
427
|
return parser
|
|
388
428
|
|
|
389
429
|
def take_action(self, parsed_args):
|
|
390
|
-
identity_client = self.app.client_manager.identity
|
|
391
|
-
group = common.
|
|
430
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
431
|
+
group = common.find_group_id_sdk(
|
|
392
432
|
identity_client, parsed_args.group, parsed_args.domain
|
|
393
433
|
)
|
|
394
434
|
kwargs = {}
|
|
@@ -397,7 +437,7 @@ class SetGroup(command.Command):
|
|
|
397
437
|
if parsed_args.description:
|
|
398
438
|
kwargs['description'] = parsed_args.description
|
|
399
439
|
|
|
400
|
-
identity_client.
|
|
440
|
+
identity_client.update_group(group, **kwargs)
|
|
401
441
|
|
|
402
442
|
|
|
403
443
|
class ShowGroup(command.ShowOne):
|
|
@@ -418,13 +458,18 @@ class ShowGroup(command.ShowOne):
|
|
|
418
458
|
return parser
|
|
419
459
|
|
|
420
460
|
def take_action(self, parsed_args):
|
|
421
|
-
identity_client = self.app.client_manager.identity
|
|
461
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
422
462
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
463
|
+
if parsed_args.domain:
|
|
464
|
+
domain = common.find_domain_id_sdk(
|
|
465
|
+
identity_client, parsed_args.domain
|
|
466
|
+
)
|
|
467
|
+
group = identity_client.find_group(
|
|
468
|
+
parsed_args.group, domain_id=domain, ignore_missing=False
|
|
469
|
+
)
|
|
470
|
+
else:
|
|
471
|
+
group = identity_client.find_group(
|
|
472
|
+
parsed_args.group, ignore_missing=False
|
|
473
|
+
)
|
|
428
474
|
|
|
429
|
-
group
|
|
430
|
-
return zip(*sorted(group._info.items()))
|
|
475
|
+
return _format_group(group)
|
|
@@ -240,6 +240,20 @@ class ListProject(command.Lister):
|
|
|
240
240
|
'keys and directions.'
|
|
241
241
|
),
|
|
242
242
|
)
|
|
243
|
+
parser.add_argument(
|
|
244
|
+
'--enabled',
|
|
245
|
+
action='store_true',
|
|
246
|
+
dest='is_enabled',
|
|
247
|
+
default=None,
|
|
248
|
+
help=_('List only enabled projects'),
|
|
249
|
+
)
|
|
250
|
+
parser.add_argument(
|
|
251
|
+
'--disabled',
|
|
252
|
+
action='store_false',
|
|
253
|
+
dest='is_enabled',
|
|
254
|
+
default=None,
|
|
255
|
+
help=_('List only disabled projects'),
|
|
256
|
+
)
|
|
243
257
|
tag.add_tag_filtering_option_to_parser(parser, _('projects'))
|
|
244
258
|
return parser
|
|
245
259
|
|
|
@@ -277,6 +291,9 @@ class ListProject(command.Lister):
|
|
|
277
291
|
|
|
278
292
|
kwargs['user'] = user_id
|
|
279
293
|
|
|
294
|
+
if parsed_args.is_enabled is not None:
|
|
295
|
+
kwargs['is_enabled'] = parsed_args.is_enabled
|
|
296
|
+
|
|
280
297
|
tag.get_tag_filtering_args(parsed_args, kwargs)
|
|
281
298
|
|
|
282
299
|
if parsed_args.my_projects:
|
|
@@ -41,6 +41,7 @@ def _format_user(user):
|
|
|
41
41
|
'name',
|
|
42
42
|
'description',
|
|
43
43
|
'password_expires_at',
|
|
44
|
+
'options',
|
|
44
45
|
)
|
|
45
46
|
column_headers = (
|
|
46
47
|
'default_project_id',
|
|
@@ -51,6 +52,7 @@ def _format_user(user):
|
|
|
51
52
|
'name',
|
|
52
53
|
'description',
|
|
53
54
|
'password_expires_at',
|
|
55
|
+
'options',
|
|
54
56
|
)
|
|
55
57
|
return (
|
|
56
58
|
column_headers,
|
|
@@ -289,7 +291,7 @@ class CreateUser(command.ShowOne):
|
|
|
289
291
|
elif parsed_args.password_prompt:
|
|
290
292
|
password = utils.get_password(self.app.stdin)
|
|
291
293
|
|
|
292
|
-
if not
|
|
294
|
+
if not password:
|
|
293
295
|
LOG.warning(
|
|
294
296
|
_(
|
|
295
297
|
"No password was supplied, authentication will fail "
|
|
@@ -412,6 +414,24 @@ class ListUser(command.Lister):
|
|
|
412
414
|
default=False,
|
|
413
415
|
help=_('List additional fields in output'),
|
|
414
416
|
)
|
|
417
|
+
parser.add_argument(
|
|
418
|
+
'--enabled',
|
|
419
|
+
action='store_true',
|
|
420
|
+
dest='is_enabled',
|
|
421
|
+
default=None,
|
|
422
|
+
help=_(
|
|
423
|
+
'List only enabled users, does nothing with --project and --group'
|
|
424
|
+
),
|
|
425
|
+
)
|
|
426
|
+
parser.add_argument(
|
|
427
|
+
'--disabled',
|
|
428
|
+
action='store_false',
|
|
429
|
+
dest='is_enabled',
|
|
430
|
+
default=None,
|
|
431
|
+
help=_(
|
|
432
|
+
'List only disabled users, does nothing with --project and --group'
|
|
433
|
+
),
|
|
434
|
+
)
|
|
415
435
|
return parser
|
|
416
436
|
|
|
417
437
|
def take_action(self, parsed_args):
|
|
@@ -431,6 +451,9 @@ class ListUser(command.Lister):
|
|
|
431
451
|
ignore_missing=False,
|
|
432
452
|
).id
|
|
433
453
|
|
|
454
|
+
if parsed_args.is_enabled is not None:
|
|
455
|
+
enabled = parsed_args.is_enabled
|
|
456
|
+
|
|
434
457
|
if parsed_args.project:
|
|
435
458
|
if domain is not None:
|
|
436
459
|
project = identity_client.find_project(
|
|
@@ -469,9 +492,15 @@ class ListUser(command.Lister):
|
|
|
469
492
|
group=group,
|
|
470
493
|
)
|
|
471
494
|
else:
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
495
|
+
if parsed_args.is_enabled is not None:
|
|
496
|
+
data = identity_client.users(
|
|
497
|
+
domain_id=domain,
|
|
498
|
+
is_enabled=enabled,
|
|
499
|
+
)
|
|
500
|
+
else:
|
|
501
|
+
data = identity_client.users(
|
|
502
|
+
domain_id=domain,
|
|
503
|
+
)
|
|
475
504
|
|
|
476
505
|
# Column handling
|
|
477
506
|
if parsed_args.long:
|
|
@@ -659,6 +688,8 @@ class SetPasswordUser(command.Command):
|
|
|
659
688
|
|
|
660
689
|
def take_action(self, parsed_args):
|
|
661
690
|
identity_client = self.app.client_manager.sdk_connection.identity
|
|
691
|
+
conn = self.app.client_manager.sdk_connection
|
|
692
|
+
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
|
662
693
|
|
|
663
694
|
# FIXME(gyee): there are two scenarios:
|
|
664
695
|
#
|
|
@@ -701,7 +732,9 @@ class SetPasswordUser(command.Command):
|
|
|
701
732
|
)
|
|
702
733
|
|
|
703
734
|
identity_client.update_user(
|
|
704
|
-
|
|
735
|
+
user=user_id,
|
|
736
|
+
current_password=current_password,
|
|
737
|
+
password=password,
|
|
705
738
|
)
|
|
706
739
|
|
|
707
740
|
|
openstackclient/image/client.py
CHANGED
|
@@ -17,14 +17,15 @@
|
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
19
|
from base64 import b64encode
|
|
20
|
+
import copy
|
|
20
21
|
import logging
|
|
21
22
|
import os
|
|
22
23
|
import sys
|
|
23
24
|
import typing as ty
|
|
24
25
|
|
|
25
|
-
from cinderclient import api_versions
|
|
26
26
|
from openstack import exceptions as sdk_exceptions
|
|
27
27
|
from openstack.image import image_signer
|
|
28
|
+
from openstack import utils as sdk_utils
|
|
28
29
|
from osc_lib.api import utils as api_utils
|
|
29
30
|
from osc_lib.cli import format_columns
|
|
30
31
|
from osc_lib.cli import parseractions
|
|
@@ -576,7 +577,7 @@ class CreateImage(command.ShowOne):
|
|
|
576
577
|
return _format_image(image)
|
|
577
578
|
|
|
578
579
|
def _take_action_volume(self, parsed_args):
|
|
579
|
-
volume_client = self.app.client_manager.volume
|
|
580
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
580
581
|
|
|
581
582
|
unsupported_opts = {
|
|
582
583
|
# 'name', # 'name' is a positional argument and will always exist
|
|
@@ -607,15 +608,14 @@ class CreateImage(command.ShowOne):
|
|
|
607
608
|
# version
|
|
608
609
|
LOG.warning(msg % opt_name)
|
|
609
610
|
|
|
610
|
-
source_volume =
|
|
611
|
-
|
|
612
|
-
parsed_args.volume,
|
|
611
|
+
source_volume = volume_client.find_volume(
|
|
612
|
+
parsed_args.volume, ignore_missing=False
|
|
613
613
|
)
|
|
614
614
|
kwargs: dict[str, ty.Any] = {
|
|
615
615
|
'visibility': None,
|
|
616
616
|
'protected': None,
|
|
617
617
|
}
|
|
618
|
-
if
|
|
618
|
+
if not sdk_utils.supports_microversion(volume_client, '3.1'):
|
|
619
619
|
if parsed_args.visibility or parsed_args.is_protected is not None:
|
|
620
620
|
msg = _(
|
|
621
621
|
'--os-volume-api-version 3.1 or greater is required '
|
|
@@ -627,15 +627,15 @@ class CreateImage(command.ShowOne):
|
|
|
627
627
|
kwargs['visibility'] = parsed_args.visibility or 'private'
|
|
628
628
|
kwargs['protected'] = parsed_args.is_protected or False
|
|
629
629
|
|
|
630
|
-
response
|
|
630
|
+
response = volume_client.upload_volume_to_image(
|
|
631
631
|
source_volume.id,
|
|
632
|
-
parsed_args.force,
|
|
633
632
|
parsed_args.name,
|
|
634
|
-
parsed_args.
|
|
635
|
-
parsed_args.disk_format,
|
|
633
|
+
force=parsed_args.force,
|
|
634
|
+
disk_format=parsed_args.disk_format,
|
|
635
|
+
container_format=parsed_args.container_format,
|
|
636
636
|
**kwargs,
|
|
637
637
|
)
|
|
638
|
-
info =
|
|
638
|
+
info = copy.deepcopy(response)
|
|
639
639
|
try:
|
|
640
640
|
info['volume_type'] = info['volume_type']['name']
|
|
641
641
|
except TypeError:
|
|
@@ -27,12 +27,6 @@ API_VERSIONS = ('2.0', '2')
|
|
|
27
27
|
|
|
28
28
|
def make_client(instance):
|
|
29
29
|
"""Returns a network proxy"""
|
|
30
|
-
# NOTE(dtroyer): As of osc-lib 1.8.0 and OpenStackSDK 0.10.0 the
|
|
31
|
-
# old Profile interface and separate client creation
|
|
32
|
-
# for each API that uses the SDK is unnecessary. This
|
|
33
|
-
# callback remains as a remnant of the original plugin
|
|
34
|
-
# interface and to avoid the code churn of changing all
|
|
35
|
-
# of the existing references.
|
|
36
30
|
LOG.debug(
|
|
37
31
|
'Network client initialized using OpenStack SDK: %s',
|
|
38
32
|
instance.sdk_connection.network,
|
|
@@ -243,18 +243,26 @@ class ListFloatingIP(common.NetworkAndComputeLister):
|
|
|
243
243
|
parser.add_argument(
|
|
244
244
|
'--network',
|
|
245
245
|
metavar='<network>',
|
|
246
|
+
dest='networks',
|
|
247
|
+
action='append',
|
|
246
248
|
help=self.enhance_help_neutron(
|
|
247
249
|
_(
|
|
248
|
-
"List floating IP(s) according to "
|
|
249
|
-
"
|
|
250
|
+
"List floating IP(s) according to given network "
|
|
251
|
+
"(name or ID) "
|
|
252
|
+
"(repeat option to fiter on multiple networks)"
|
|
250
253
|
)
|
|
251
254
|
),
|
|
252
255
|
)
|
|
253
256
|
parser.add_argument(
|
|
254
257
|
'--port',
|
|
255
258
|
metavar='<port>',
|
|
259
|
+
dest='ports',
|
|
260
|
+
action='append',
|
|
256
261
|
help=self.enhance_help_neutron(
|
|
257
|
-
_(
|
|
262
|
+
_(
|
|
263
|
+
"List floating IP(s) according to given port (name or ID) "
|
|
264
|
+
"(repeat option to fiter on multiple ports)"
|
|
265
|
+
)
|
|
258
266
|
),
|
|
259
267
|
)
|
|
260
268
|
parser.add_argument(
|
|
@@ -271,14 +279,6 @@ class ListFloatingIP(common.NetworkAndComputeLister):
|
|
|
271
279
|
_("List floating IP(s) according to given floating IP address")
|
|
272
280
|
),
|
|
273
281
|
)
|
|
274
|
-
parser.add_argument(
|
|
275
|
-
'--long',
|
|
276
|
-
action='store_true',
|
|
277
|
-
default=False,
|
|
278
|
-
help=self.enhance_help_neutron(
|
|
279
|
-
_("List additional fields in output")
|
|
280
|
-
),
|
|
281
|
-
)
|
|
282
282
|
parser.add_argument(
|
|
283
283
|
'--status',
|
|
284
284
|
metavar='<status>',
|
|
@@ -295,8 +295,8 @@ class ListFloatingIP(common.NetworkAndComputeLister):
|
|
|
295
295
|
metavar='<project>',
|
|
296
296
|
help=self.enhance_help_neutron(
|
|
297
297
|
_(
|
|
298
|
-
"List floating IP(s) according to given project
|
|
299
|
-
"ID)"
|
|
298
|
+
"List floating IP(s) according to given project "
|
|
299
|
+
"(name or ID) "
|
|
300
300
|
)
|
|
301
301
|
),
|
|
302
302
|
)
|
|
@@ -304,13 +304,27 @@ class ListFloatingIP(common.NetworkAndComputeLister):
|
|
|
304
304
|
parser.add_argument(
|
|
305
305
|
'--router',
|
|
306
306
|
metavar='<router>',
|
|
307
|
+
dest='routers',
|
|
308
|
+
action='append',
|
|
307
309
|
help=self.enhance_help_neutron(
|
|
308
|
-
_(
|
|
310
|
+
_(
|
|
311
|
+
"List floating IP(s) according to given router "
|
|
312
|
+
"(name or ID) "
|
|
313
|
+
"(repeat option to fiter on multiple routers)"
|
|
314
|
+
)
|
|
309
315
|
),
|
|
310
316
|
)
|
|
311
317
|
_tag.add_tag_filtering_option_to_parser(
|
|
312
318
|
parser, _('floating IP'), enhance_help=self.enhance_help_neutron
|
|
313
319
|
)
|
|
320
|
+
parser.add_argument(
|
|
321
|
+
'--long',
|
|
322
|
+
action='store_true',
|
|
323
|
+
default=False,
|
|
324
|
+
help=self.enhance_help_neutron(
|
|
325
|
+
_("List additional fields in output")
|
|
326
|
+
),
|
|
327
|
+
)
|
|
314
328
|
|
|
315
329
|
return parser
|
|
316
330
|
|
|
@@ -354,22 +368,33 @@ class ListFloatingIP(common.NetworkAndComputeLister):
|
|
|
354
368
|
|
|
355
369
|
query = {}
|
|
356
370
|
|
|
357
|
-
if parsed_args.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
371
|
+
if parsed_args.networks is not None:
|
|
372
|
+
network_ids = []
|
|
373
|
+
for network in parsed_args.networks:
|
|
374
|
+
network_id = network_client.find_network(
|
|
375
|
+
network, ignore_missing=False
|
|
376
|
+
).id
|
|
377
|
+
network_ids.append(network_id)
|
|
378
|
+
query['floating_network_id'] = network_ids
|
|
379
|
+
|
|
380
|
+
if parsed_args.ports is not None:
|
|
381
|
+
port_ids = []
|
|
382
|
+
for port in parsed_args.ports:
|
|
383
|
+
port_id = network_client.find_port(
|
|
384
|
+
port, ignore_missing=False
|
|
385
|
+
).id
|
|
386
|
+
port_ids.append(port_id)
|
|
387
|
+
query['port_id'] = port_ids
|
|
388
|
+
|
|
367
389
|
if parsed_args.fixed_ip_address is not None:
|
|
368
390
|
query['fixed_ip_address'] = parsed_args.fixed_ip_address
|
|
391
|
+
|
|
369
392
|
if parsed_args.floating_ip_address is not None:
|
|
370
393
|
query['floating_ip_address'] = parsed_args.floating_ip_address
|
|
394
|
+
|
|
371
395
|
if parsed_args.status:
|
|
372
396
|
query['status'] = parsed_args.status
|
|
397
|
+
|
|
373
398
|
if parsed_args.project is not None:
|
|
374
399
|
project = identity_common.find_project(
|
|
375
400
|
identity_client,
|
|
@@ -377,11 +402,15 @@ class ListFloatingIP(common.NetworkAndComputeLister):
|
|
|
377
402
|
parsed_args.project_domain,
|
|
378
403
|
)
|
|
379
404
|
query['project_id'] = project.id
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
405
|
+
|
|
406
|
+
if parsed_args.routers is not None:
|
|
407
|
+
router_ids = []
|
|
408
|
+
for router in parsed_args.routers:
|
|
409
|
+
router_id = network_client.find_router(
|
|
410
|
+
router, ignore_missing=False
|
|
411
|
+
).id
|
|
412
|
+
router_ids.append(router_id)
|
|
413
|
+
query['router_id'] = router_ids
|
|
385
414
|
|
|
386
415
|
_tag.get_tag_filtering_args(parsed_args, query)
|
|
387
416
|
|