python-openstackclient 7.1.2__py3-none-any.whl → 7.2.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/api/api.py +2 -1
- openstackclient/api/image_v2.py +1 -1
- openstackclient/api/object_store_v1.py +12 -20
- openstackclient/common/clientmanager.py +1 -1
- openstackclient/common/module.py +2 -2
- openstackclient/common/quota.py +4 -4
- openstackclient/compute/v2/flavor.py +1 -1
- openstackclient/compute/v2/server.py +123 -60
- openstackclient/compute/v2/server_backup.py +1 -1
- openstackclient/compute/v2/server_image.py +1 -1
- openstackclient/compute/v2/server_migration.py +11 -2
- openstackclient/compute/v2/usage.py +3 -3
- openstackclient/identity/common.py +4 -1
- openstackclient/identity/v2_0/project.py +1 -1
- openstackclient/identity/v2_0/role_assignment.py +1 -1
- openstackclient/identity/v2_0/user.py +2 -2
- openstackclient/identity/v3/access_rule.py +26 -14
- openstackclient/identity/v3/identity_provider.py +1 -1
- openstackclient/identity/v3/project.py +1 -1
- openstackclient/identity/v3/role_assignment.py +24 -3
- openstackclient/identity/v3/service.py +2 -1
- openstackclient/identity/v3/user.py +35 -15
- openstackclient/image/v2/image.py +13 -13
- openstackclient/image/v2/metadef_objects.py +6 -4
- openstackclient/network/common.py +8 -7
- openstackclient/network/v2/floating_ip.py +6 -2
- openstackclient/network/v2/floating_ip_port_forwarding.py +2 -2
- openstackclient/network/v2/l3_conntrack_helper.py +1 -1
- openstackclient/network/v2/ndp_proxy.py +1 -0
- openstackclient/network/v2/network_agent.py +2 -6
- openstackclient/network/v2/network_qos_rule.py +2 -5
- openstackclient/network/v2/network_trunk.py +5 -4
- openstackclient/network/v2/port.py +18 -3
- openstackclient/network/v2/router.py +7 -4
- openstackclient/network/v2/subnet_pool.py +2 -2
- openstackclient/shell.py +3 -2
- openstackclient/tests/functional/common/test_help.py +3 -9
- openstackclient/tests/functional/common/test_module.py +1 -1
- openstackclient/tests/functional/common/test_quota.py +2 -4
- openstackclient/tests/functional/compute/v2/common.py +1 -3
- openstackclient/tests/functional/compute/v2/test_hypervisor.py +3 -3
- openstackclient/tests/functional/compute/v2/test_keypair.py +2 -2
- openstackclient/tests/functional/compute/v2/test_server.py +1 -1
- openstackclient/tests/functional/identity/v2/common.py +31 -48
- openstackclient/tests/functional/identity/v2/test_catalog.py +1 -1
- openstackclient/tests/functional/identity/v2/test_ec2_credentials.py +2 -2
- openstackclient/tests/functional/identity/v2/test_endpoint.py +2 -2
- openstackclient/tests/functional/identity/v2/test_project.py +8 -8
- openstackclient/tests/functional/identity/v2/test_role.py +14 -34
- openstackclient/tests/functional/identity/v2/test_service.py +2 -2
- openstackclient/tests/functional/identity/v2/test_token.py +1 -1
- openstackclient/tests/functional/identity/v2/test_user.py +7 -9
- openstackclient/tests/functional/identity/v3/common.py +69 -110
- openstackclient/tests/functional/identity/v3/test_access_rule.py +86 -0
- openstackclient/tests/functional/identity/v3/test_application_credential.py +18 -44
- openstackclient/tests/functional/identity/v3/test_catalog.py +1 -1
- openstackclient/tests/functional/identity/v3/test_domain.py +9 -11
- openstackclient/tests/functional/identity/v3/test_endpoint.py +15 -27
- openstackclient/tests/functional/identity/v3/test_group.py +32 -93
- openstackclient/tests/functional/identity/v3/test_idp.py +3 -3
- openstackclient/tests/functional/identity/v3/test_limit.py +32 -32
- openstackclient/tests/functional/identity/v3/test_project.py +17 -26
- openstackclient/tests/functional/identity/v3/test_region.py +6 -7
- openstackclient/tests/functional/identity/v3/test_registered_limit.py +27 -36
- openstackclient/tests/functional/identity/v3/test_role.py +30 -60
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +33 -80
- openstackclient/tests/functional/identity/v3/test_service.py +7 -13
- openstackclient/tests/functional/identity/v3/test_service_provider.py +3 -3
- openstackclient/tests/functional/identity/v3/test_user.py +17 -34
- openstackclient/tests/functional/image/v2/test_image.py +1 -3
- openstackclient/tests/functional/network/v2/common.py +1 -3
- openstackclient/tests/functional/network/v2/test_default_security_group_rule.py +3 -8
- openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py +27 -31
- openstackclient/tests/functional/network/v2/test_network.py +9 -12
- openstackclient/tests/functional/network/v2/test_network_agent.py +15 -20
- openstackclient/tests/functional/network/v2/test_network_flavor.py +2 -2
- openstackclient/tests/functional/network/v2/test_network_ndp_proxy.py +17 -39
- openstackclient/tests/functional/network/v2/test_network_qos_rule.py +48 -63
- openstackclient/tests/functional/network/v2/test_network_qos_rule_type.py +1 -1
- openstackclient/tests/functional/network/v2/test_network_segment_range.py +2 -2
- openstackclient/tests/functional/network/v2/test_network_trunk.py +15 -25
- openstackclient/tests/functional/network/v2/test_port.py +28 -34
- openstackclient/tests/functional/network/v2/test_router.py +13 -19
- openstackclient/tests/functional/object/v1/test_object.py +4 -7
- openstackclient/tests/functional/volume/base.py +5 -17
- openstackclient/tests/functional/volume/v1/test_volume_type.py +11 -11
- openstackclient/tests/functional/volume/v2/test_volume_backup.py +1 -1
- openstackclient/tests/functional/volume/v2/test_volume_type.py +13 -15
- openstackclient/tests/functional/volume/v3/test_volume_type.py +13 -15
- openstackclient/tests/unit/api/test_compute_v2.py +0 -5
- openstackclient/tests/unit/api/test_object_store_v1.py +6 -4
- openstackclient/tests/unit/common/test_extension.py +24 -31
- openstackclient/tests/unit/compute/v2/test_host.py +0 -1
- openstackclient/tests/unit/compute/v2/test_server.py +124 -116
- openstackclient/tests/unit/identity/v3/test_access_rule.py +65 -64
- openstackclient/tests/unit/identity/v3/test_group.py +4 -10
- openstackclient/tests/unit/identity/v3/test_limit.py +2 -2
- openstackclient/tests/unit/identity/v3/test_service.py +0 -3
- openstackclient/tests/unit/identity/v3/test_user.py +4 -90
- openstackclient/tests/unit/image/v2/test_metadef_objects.py +1 -2
- openstackclient/tests/unit/image/v2/test_metadef_resource_type_association.py +2 -6
- openstackclient/tests/unit/integ/base.py +1 -1
- openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +3 -3
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +4 -4
- openstackclient/tests/unit/network/v2/test_local_ip_association.py +2 -2
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +12 -13
- openstackclient/tests/unit/network/v2/test_network_trunk.py +31 -35
- openstackclient/tests/unit/network/v2/test_port.py +40 -17
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +1 -1
- openstackclient/tests/unit/object/v1/test_object.py +1 -1
- openstackclient/tests/unit/utils.py +2 -2
- openstackclient/volume/client.py +1 -1
- openstackclient/volume/v1/volume.py +2 -2
- openstackclient/volume/v1/volume_backup.py +2 -2
- openstackclient/volume/v1/volume_snapshot.py +2 -2
- openstackclient/volume/v2/volume.py +2 -2
- openstackclient/volume/v2/volume_backup.py +2 -2
- openstackclient/volume/v2/volume_snapshot.py +2 -2
- openstackclient/volume/v2/volume_type.py +4 -4
- openstackclient/volume/v3/service.py +0 -1
- openstackclient/volume/v3/volume.py +3 -3
- openstackclient/volume/v3/volume_backup.py +2 -2
- openstackclient/volume/v3/volume_group.py +3 -7
- openstackclient/volume/v3/volume_type.py +6 -6
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/AUTHORS +3 -0
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/METADATA +2 -3
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/RECORD +132 -131
- python_openstackclient-7.2.0.dist-info/pbr.json +1 -0
- python_openstackclient-7.1.2.dist-info/pbr.json +0 -1
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/LICENSE +0 -0
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/entry_points.txt +0 -0
- {python_openstackclient-7.1.2.dist-info → python_openstackclient-7.2.0.dist-info}/top_level.txt +0 -0
openstackclient/api/api.py
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#
|
|
13
13
|
|
|
14
14
|
"""Base API Library"""
|
|
15
|
+
|
|
15
16
|
from keystoneauth1 import exceptions as ks_exceptions
|
|
16
17
|
from keystoneauth1 import session as ks_session
|
|
17
18
|
from osc_lib import exceptions
|
|
@@ -306,7 +307,7 @@ class BaseAPI(KeystoneSession):
|
|
|
306
307
|
except ks_exceptions.NotFound:
|
|
307
308
|
kwargs = {attr: value}
|
|
308
309
|
try:
|
|
309
|
-
ret = self.find_one("
|
|
310
|
+
ret = self.find_one(f"/{path}/detail", **kwargs)
|
|
310
311
|
except ks_exceptions.NotFound:
|
|
311
312
|
msg = _("%s not found") % value
|
|
312
313
|
raise exceptions.NotFound(msg)
|
openstackclient/api/image_v2.py
CHANGED
|
@@ -89,7 +89,7 @@ class APIv1(api.BaseAPI):
|
|
|
89
89
|
marker=None,
|
|
90
90
|
end_marker=None,
|
|
91
91
|
prefix=None,
|
|
92
|
-
**params
|
|
92
|
+
**params,
|
|
93
93
|
):
|
|
94
94
|
"""Get containers in an account
|
|
95
95
|
|
|
@@ -116,7 +116,7 @@ class APIv1(api.BaseAPI):
|
|
|
116
116
|
marker=marker,
|
|
117
117
|
end_marker=end_marker,
|
|
118
118
|
prefix=prefix,
|
|
119
|
-
**params
|
|
119
|
+
**params,
|
|
120
120
|
)
|
|
121
121
|
while listing:
|
|
122
122
|
marker = listing[-1]['name']
|
|
@@ -125,7 +125,7 @@ class APIv1(api.BaseAPI):
|
|
|
125
125
|
marker=marker,
|
|
126
126
|
end_marker=end_marker,
|
|
127
127
|
prefix=prefix,
|
|
128
|
-
**params
|
|
128
|
+
**params,
|
|
129
129
|
)
|
|
130
130
|
if listing:
|
|
131
131
|
data.extend(listing)
|
|
@@ -256,10 +256,7 @@ class APIv1(api.BaseAPI):
|
|
|
256
256
|
# object's name in the container.
|
|
257
257
|
object_name_str = name if name else object
|
|
258
258
|
|
|
259
|
-
full_url = "{}/{}"
|
|
260
|
-
urllib.parse.quote(container),
|
|
261
|
-
urllib.parse.quote(object_name_str),
|
|
262
|
-
)
|
|
259
|
+
full_url = f"{urllib.parse.quote(container)}/{urllib.parse.quote(object_name_str)}"
|
|
263
260
|
with open(object, 'rb') as f:
|
|
264
261
|
response = self.create(
|
|
265
262
|
full_url,
|
|
@@ -293,8 +290,7 @@ class APIv1(api.BaseAPI):
|
|
|
293
290
|
return
|
|
294
291
|
|
|
295
292
|
self.delete(
|
|
296
|
-
"
|
|
297
|
-
% (urllib.parse.quote(container), urllib.parse.quote(object))
|
|
293
|
+
f"{urllib.parse.quote(container)}/{urllib.parse.quote(object)}"
|
|
298
294
|
)
|
|
299
295
|
|
|
300
296
|
def object_list(
|
|
@@ -306,7 +302,7 @@ class APIv1(api.BaseAPI):
|
|
|
306
302
|
end_marker=None,
|
|
307
303
|
delimiter=None,
|
|
308
304
|
prefix=None,
|
|
309
|
-
**params
|
|
305
|
+
**params,
|
|
310
306
|
):
|
|
311
307
|
"""List objects in a container
|
|
312
308
|
|
|
@@ -341,7 +337,7 @@ class APIv1(api.BaseAPI):
|
|
|
341
337
|
end_marker=end_marker,
|
|
342
338
|
prefix=prefix,
|
|
343
339
|
delimiter=delimiter,
|
|
344
|
-
**params
|
|
340
|
+
**params,
|
|
345
341
|
)
|
|
346
342
|
while listing:
|
|
347
343
|
if delimiter:
|
|
@@ -355,7 +351,7 @@ class APIv1(api.BaseAPI):
|
|
|
355
351
|
end_marker=end_marker,
|
|
356
352
|
prefix=prefix,
|
|
357
353
|
delimiter=delimiter,
|
|
358
|
-
**params
|
|
354
|
+
**params,
|
|
359
355
|
)
|
|
360
356
|
if listing:
|
|
361
357
|
data.extend(listing)
|
|
@@ -395,8 +391,7 @@ class APIv1(api.BaseAPI):
|
|
|
395
391
|
|
|
396
392
|
response = self._request(
|
|
397
393
|
'GET',
|
|
398
|
-
"
|
|
399
|
-
% (urllib.parse.quote(container), urllib.parse.quote(object)),
|
|
394
|
+
f"{urllib.parse.quote(container)}/{urllib.parse.quote(object)}",
|
|
400
395
|
stream=True,
|
|
401
396
|
)
|
|
402
397
|
if response.status_code == 200:
|
|
@@ -431,8 +426,7 @@ class APIv1(api.BaseAPI):
|
|
|
431
426
|
headers = self._set_properties(properties, 'X-Object-Meta-%s')
|
|
432
427
|
if headers:
|
|
433
428
|
self.create(
|
|
434
|
-
"
|
|
435
|
-
% (urllib.parse.quote(container), urllib.parse.quote(object)),
|
|
429
|
+
f"{urllib.parse.quote(container)}/{urllib.parse.quote(object)}",
|
|
436
430
|
headers=headers,
|
|
437
431
|
)
|
|
438
432
|
|
|
@@ -455,8 +449,7 @@ class APIv1(api.BaseAPI):
|
|
|
455
449
|
headers = self._unset_properties(properties, 'X-Remove-Object-Meta-%s')
|
|
456
450
|
if headers:
|
|
457
451
|
self.create(
|
|
458
|
-
"
|
|
459
|
-
% (urllib.parse.quote(container), urllib.parse.quote(object)),
|
|
452
|
+
f"{urllib.parse.quote(container)}/{urllib.parse.quote(object)}",
|
|
460
453
|
headers=headers,
|
|
461
454
|
)
|
|
462
455
|
|
|
@@ -480,8 +473,7 @@ class APIv1(api.BaseAPI):
|
|
|
480
473
|
|
|
481
474
|
response = self._request(
|
|
482
475
|
'HEAD',
|
|
483
|
-
"
|
|
484
|
-
% (urllib.parse.quote(container), urllib.parse.quote(object)),
|
|
476
|
+
f"{urllib.parse.quote(container)}/{urllib.parse.quote(object)}",
|
|
485
477
|
)
|
|
486
478
|
|
|
487
479
|
data = {
|
|
@@ -101,7 +101,7 @@ class ClientManager(clientmanager.ClientManager):
|
|
|
101
101
|
# expect, delete fake token and endpoint, then try to
|
|
102
102
|
# load auth plugin again with user specified options.
|
|
103
103
|
# We know it looks ugly, but it's necessary.
|
|
104
|
-
if self._cli_options.config['auth']['token'] == 'x':
|
|
104
|
+
if self._cli_options.config['auth']['token'] == 'x': # noqa: S105
|
|
105
105
|
# restore original auth_type
|
|
106
106
|
self._cli_options.config['auth_type'] = self._original_auth_type
|
|
107
107
|
del self._cli_options.config['auth']['token']
|
openstackclient/common/module.py
CHANGED
|
@@ -111,8 +111,8 @@ class ListModule(command.ShowOne):
|
|
|
111
111
|
data[k] = mods[k].version.__version__
|
|
112
112
|
else:
|
|
113
113
|
data[k] = mods[k].__version__
|
|
114
|
-
except Exception:
|
|
114
|
+
except Exception: # noqa: S110
|
|
115
115
|
# Catch all exceptions, just skip it
|
|
116
|
-
pass
|
|
116
|
+
pass
|
|
117
117
|
|
|
118
118
|
return zip(*sorted(data.items()))
|
openstackclient/common/quota.py
CHANGED
|
@@ -176,7 +176,7 @@ def get_network_quotas(
|
|
|
176
176
|
default=False,
|
|
177
177
|
):
|
|
178
178
|
def _network_quota_to_dict(network_quota, detail=False):
|
|
179
|
-
if
|
|
179
|
+
if not isinstance(network_quota, dict):
|
|
180
180
|
dict_quota = network_quota.to_dict()
|
|
181
181
|
else:
|
|
182
182
|
dict_quota = network_quota
|
|
@@ -507,8 +507,8 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
507
507
|
)
|
|
508
508
|
for k, v, h in self._build_options_list():
|
|
509
509
|
parser.add_argument(
|
|
510
|
-
'
|
|
511
|
-
metavar='
|
|
510
|
+
f'--{v}',
|
|
511
|
+
metavar=f'<{v}>',
|
|
512
512
|
dest=k,
|
|
513
513
|
type=int,
|
|
514
514
|
help=h,
|
|
@@ -590,7 +590,7 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
590
590
|
parsed_args.volume_type
|
|
591
591
|
and k in IMPACT_VOLUME_TYPE_QUOTAS
|
|
592
592
|
):
|
|
593
|
-
k = k + '_
|
|
593
|
+
k = k + f'_{parsed_args.volume_type}'
|
|
594
594
|
volume_kwargs[k] = value
|
|
595
595
|
|
|
596
596
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
@@ -577,7 +577,7 @@ class UnsetFlavor(command.Command):
|
|
|
577
577
|
parsed_args.flavor, get_extra_specs=True, ignore_missing=False
|
|
578
578
|
)
|
|
579
579
|
except sdk_exceptions.ResourceNotFound as e:
|
|
580
|
-
raise exceptions.CommandError(
|
|
580
|
+
raise exceptions.CommandError(e.message)
|
|
581
581
|
|
|
582
582
|
result = 0
|
|
583
583
|
if parsed_args.properties:
|
|
@@ -670,7 +670,7 @@ class AddNetwork(command.Command):
|
|
|
670
670
|
|
|
671
671
|
|
|
672
672
|
class AddServerSecurityGroup(command.Command):
|
|
673
|
-
_description = _("Add security group to server")
|
|
673
|
+
_description = _("Add security group(s) to server")
|
|
674
674
|
|
|
675
675
|
def get_parser(self, prog_name):
|
|
676
676
|
parser = super().get_parser(prog_name)
|
|
@@ -680,9 +680,13 @@ class AddServerSecurityGroup(command.Command):
|
|
|
680
680
|
help=_('Server (name or ID)'),
|
|
681
681
|
)
|
|
682
682
|
parser.add_argument(
|
|
683
|
-
'
|
|
684
|
-
metavar='<group>',
|
|
685
|
-
|
|
683
|
+
'security_groups',
|
|
684
|
+
metavar='<security-group>',
|
|
685
|
+
nargs='+',
|
|
686
|
+
help=_(
|
|
687
|
+
'Security group(s) to add to the server (name or ID) '
|
|
688
|
+
'(repeat option to add multiple groups)'
|
|
689
|
+
),
|
|
686
690
|
)
|
|
687
691
|
return parser
|
|
688
692
|
|
|
@@ -694,14 +698,43 @@ class AddServerSecurityGroup(command.Command):
|
|
|
694
698
|
)
|
|
695
699
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
696
700
|
# the server handles both names and IDs for neutron SGs, so just
|
|
697
|
-
# pass things through
|
|
698
|
-
|
|
701
|
+
# pass things through if using neutron
|
|
702
|
+
security_groups = parsed_args.security_groups
|
|
699
703
|
else:
|
|
700
|
-
# however, if using nova-network then it needs
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
704
|
+
# however, if using nova-network then it needs names, not IDs
|
|
705
|
+
security_groups = []
|
|
706
|
+
for security_group in parsed_args.security_groups:
|
|
707
|
+
security_groups.append(
|
|
708
|
+
compute_v2.find_security_group(
|
|
709
|
+
compute_client, security_group
|
|
710
|
+
)['name']
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
errors = 0
|
|
714
|
+
for security_group in security_groups:
|
|
715
|
+
try:
|
|
716
|
+
compute_client.add_security_group_to_server(
|
|
717
|
+
server, security_group
|
|
718
|
+
)
|
|
719
|
+
except sdk_exceptions.HttpException as e:
|
|
720
|
+
errors += 1
|
|
721
|
+
LOG.error(
|
|
722
|
+
_(
|
|
723
|
+
"Failed to add security group with name or ID "
|
|
724
|
+
"'%(security_group)s' to server '%(server)s': %(e)s"
|
|
725
|
+
),
|
|
726
|
+
{
|
|
727
|
+
'security_group': security_group,
|
|
728
|
+
'server': server.id,
|
|
729
|
+
'e': e,
|
|
730
|
+
},
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
if errors > 0:
|
|
734
|
+
msg = _(
|
|
735
|
+
"%(errors)d of %(total)d security groups were not added."
|
|
736
|
+
) % {'errors': errors, 'total': len(security_groups)}
|
|
737
|
+
raise exceptions.CommandError(msg)
|
|
705
738
|
|
|
706
739
|
|
|
707
740
|
class AddServerVolume(command.ShowOne):
|
|
@@ -1328,6 +1361,7 @@ class CreateServer(command.ShowOne):
|
|
|
1328
1361
|
metavar='<security-group>',
|
|
1329
1362
|
action='append',
|
|
1330
1363
|
default=[],
|
|
1364
|
+
dest='security_groups',
|
|
1331
1365
|
help=_(
|
|
1332
1366
|
'Security group to assign to this server (name or ID) '
|
|
1333
1367
|
'(repeat option to set multiple groups)'
|
|
@@ -1504,7 +1538,7 @@ class CreateServer(command.ShowOne):
|
|
|
1504
1538
|
def take_action(self, parsed_args):
|
|
1505
1539
|
def _show_progress(progress):
|
|
1506
1540
|
if progress:
|
|
1507
|
-
self.app.stdout.write('\rProgress:
|
|
1541
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
1508
1542
|
self.app.stdout.flush()
|
|
1509
1543
|
|
|
1510
1544
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -1520,17 +1554,6 @@ class CreateServer(command.ShowOne):
|
|
|
1520
1554
|
|
|
1521
1555
|
if not image and parsed_args.image_properties:
|
|
1522
1556
|
|
|
1523
|
-
def emit_duplicated_warning(img):
|
|
1524
|
-
img_uuid_list = [str(image.id) for image in img]
|
|
1525
|
-
LOG.warning(
|
|
1526
|
-
'Multiple matching images: %(img_uuid_list)s\n'
|
|
1527
|
-
'Using image: %(chosen_one)s',
|
|
1528
|
-
{
|
|
1529
|
-
'img_uuid_list': img_uuid_list,
|
|
1530
|
-
'chosen_one': img_uuid_list[0],
|
|
1531
|
-
},
|
|
1532
|
-
)
|
|
1533
|
-
|
|
1534
1557
|
def _match_image(image_api, wanted_properties):
|
|
1535
1558
|
image_list = image_api.images()
|
|
1536
1559
|
images_matched = []
|
|
@@ -1568,7 +1591,15 @@ class CreateServer(command.ShowOne):
|
|
|
1568
1591
|
|
|
1569
1592
|
images = _match_image(image_client, parsed_args.image_properties)
|
|
1570
1593
|
if len(images) > 1:
|
|
1571
|
-
|
|
1594
|
+
img_uuid_list = [str(image.id) for image in images]
|
|
1595
|
+
LOG.warning(
|
|
1596
|
+
'Multiple matching images: %(img_uuid_list)s\n'
|
|
1597
|
+
'Using image: %(chosen_one)s',
|
|
1598
|
+
{
|
|
1599
|
+
'img_uuid_list': img_uuid_list,
|
|
1600
|
+
'chosen_one': img_uuid_list[0],
|
|
1601
|
+
},
|
|
1602
|
+
)
|
|
1572
1603
|
if images:
|
|
1573
1604
|
image = images[0]
|
|
1574
1605
|
else:
|
|
@@ -1948,21 +1979,22 @@ class CreateServer(command.ShowOne):
|
|
|
1948
1979
|
# 'auto' to maintain legacy behavior if a nic wasn't specified.
|
|
1949
1980
|
networks = 'auto'
|
|
1950
1981
|
|
|
1951
|
-
# Check security group exist and convert ID to name
|
|
1982
|
+
# Check security group(s) exist and convert ID to name
|
|
1952
1983
|
security_groups = []
|
|
1953
1984
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
1954
1985
|
network_client = self.app.client_manager.network
|
|
1955
|
-
for
|
|
1986
|
+
for security_group in parsed_args.security_groups:
|
|
1956
1987
|
sg = network_client.find_security_group(
|
|
1957
|
-
|
|
1988
|
+
security_group, ignore_missing=False
|
|
1958
1989
|
)
|
|
1959
1990
|
# Use security group ID to avoid multiple security group have
|
|
1960
1991
|
# same name in neutron networking backend
|
|
1961
1992
|
security_groups.append({'name': sg.id})
|
|
1962
|
-
else:
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1993
|
+
else: # nova-network
|
|
1994
|
+
for security_group in parsed_args.security_groups:
|
|
1995
|
+
sg = compute_v2.find_security_group(
|
|
1996
|
+
compute_client, security_group
|
|
1997
|
+
)
|
|
1966
1998
|
security_groups.append({'name': sg['name']})
|
|
1967
1999
|
|
|
1968
2000
|
hints = {}
|
|
@@ -2189,7 +2221,7 @@ class DeleteServer(command.Command):
|
|
|
2189
2221
|
def take_action(self, parsed_args):
|
|
2190
2222
|
def _show_progress(progress):
|
|
2191
2223
|
if progress:
|
|
2192
|
-
self.app.stdout.write('\rProgress:
|
|
2224
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
2193
2225
|
self.app.stdout.flush()
|
|
2194
2226
|
|
|
2195
2227
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -2648,7 +2680,7 @@ class ListServer(command.Lister):
|
|
|
2648
2680
|
'status': parsed_args.status,
|
|
2649
2681
|
'flavor': flavor_id,
|
|
2650
2682
|
'image': image_id,
|
|
2651
|
-
'
|
|
2683
|
+
'compute_host': parsed_args.host,
|
|
2652
2684
|
'project_id': project_id,
|
|
2653
2685
|
'all_projects': parsed_args.all_projects,
|
|
2654
2686
|
'user_id': user_id,
|
|
@@ -2915,10 +2947,10 @@ class ListServer(command.Lister):
|
|
|
2915
2947
|
for image_id in image_ids:
|
|
2916
2948
|
try:
|
|
2917
2949
|
images[image_id] = image_client.get_image(image_id)
|
|
2918
|
-
except Exception:
|
|
2950
|
+
except Exception: # noqa: S110
|
|
2919
2951
|
# retrieving image names is not crucial, so we swallow
|
|
2920
2952
|
# any exceptions
|
|
2921
|
-
pass
|
|
2953
|
+
pass
|
|
2922
2954
|
else:
|
|
2923
2955
|
try:
|
|
2924
2956
|
# some deployments can have *loads* of images so we only
|
|
@@ -2936,10 +2968,10 @@ class ListServer(command.Lister):
|
|
|
2936
2968
|
)
|
|
2937
2969
|
for i in images_list:
|
|
2938
2970
|
images[i.id] = i
|
|
2939
|
-
except Exception:
|
|
2971
|
+
except Exception: # noqa: S110
|
|
2940
2972
|
# retrieving image names is not crucial, so we swallow any
|
|
2941
2973
|
# exceptions
|
|
2942
|
-
pass
|
|
2974
|
+
pass
|
|
2943
2975
|
|
|
2944
2976
|
# create a dict that maps flavor_id to flavor object, which is used
|
|
2945
2977
|
# to display the "Flavor Name" column. Note that 'flavor.id' is not
|
|
@@ -2955,19 +2987,19 @@ class ListServer(command.Lister):
|
|
|
2955
2987
|
flavors[f_id] = compute_client.find_flavor(
|
|
2956
2988
|
f_id, ignore_missing=False
|
|
2957
2989
|
)
|
|
2958
|
-
except Exception:
|
|
2990
|
+
except Exception: # noqa: S110
|
|
2959
2991
|
# retrieving flavor names is not crucial, so we swallow
|
|
2960
2992
|
# any exceptions
|
|
2961
|
-
pass
|
|
2993
|
+
pass
|
|
2962
2994
|
else:
|
|
2963
2995
|
try:
|
|
2964
2996
|
flavors_list = compute_client.flavors(is_public=None)
|
|
2965
2997
|
for i in flavors_list:
|
|
2966
2998
|
flavors[i.id] = i
|
|
2967
|
-
except Exception:
|
|
2999
|
+
except Exception: # noqa: S110
|
|
2968
3000
|
# retrieving flavor names is not crucial, so we swallow any
|
|
2969
3001
|
# exceptions
|
|
2970
|
-
pass
|
|
3002
|
+
pass
|
|
2971
3003
|
|
|
2972
3004
|
# Populate image_name, image_id, flavor_name and flavor_id attributes
|
|
2973
3005
|
# of server objects so that we can display those columns.
|
|
@@ -3198,7 +3230,7 @@ revert to release the new server and restart the old one."""
|
|
|
3198
3230
|
def take_action(self, parsed_args):
|
|
3199
3231
|
def _show_progress(progress):
|
|
3200
3232
|
if progress:
|
|
3201
|
-
self.app.stdout.write('\rProgress:
|
|
3233
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
3202
3234
|
self.app.stdout.flush()
|
|
3203
3235
|
|
|
3204
3236
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -3350,7 +3382,7 @@ class RebootServer(command.Command):
|
|
|
3350
3382
|
def take_action(self, parsed_args):
|
|
3351
3383
|
def _show_progress(progress):
|
|
3352
3384
|
if progress:
|
|
3353
|
-
self.app.stdout.write('\rProgress:
|
|
3385
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
3354
3386
|
self.app.stdout.flush()
|
|
3355
3387
|
|
|
3356
3388
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -3555,7 +3587,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3555
3587
|
def take_action(self, parsed_args):
|
|
3556
3588
|
def _show_progress(progress):
|
|
3557
3589
|
if progress:
|
|
3558
|
-
self.app.stdout.write('\rProgress:
|
|
3590
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
3559
3591
|
self.app.stdout.flush()
|
|
3560
3592
|
|
|
3561
3593
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -3816,7 +3848,7 @@ host."""
|
|
|
3816
3848
|
def take_action(self, parsed_args):
|
|
3817
3849
|
def _show_progress(progress):
|
|
3818
3850
|
if progress:
|
|
3819
|
-
self.app.stdout.write('\rProgress:
|
|
3851
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
3820
3852
|
self.app.stdout.flush()
|
|
3821
3853
|
|
|
3822
3854
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -4017,9 +4049,13 @@ class RemoveServerSecurityGroup(command.Command):
|
|
|
4017
4049
|
help=_('Server (name or ID)'),
|
|
4018
4050
|
)
|
|
4019
4051
|
parser.add_argument(
|
|
4020
|
-
'
|
|
4021
|
-
metavar='<group>',
|
|
4022
|
-
|
|
4052
|
+
'security_groups',
|
|
4053
|
+
metavar='<security-group>',
|
|
4054
|
+
nargs='+',
|
|
4055
|
+
help=_(
|
|
4056
|
+
'Security group(s) to remove from server (name or ID) '
|
|
4057
|
+
'(repeat option to remove multiple groups)'
|
|
4058
|
+
),
|
|
4023
4059
|
)
|
|
4024
4060
|
return parser
|
|
4025
4061
|
|
|
@@ -4032,15 +4068,42 @@ class RemoveServerSecurityGroup(command.Command):
|
|
|
4032
4068
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
4033
4069
|
# the server handles both names and IDs for neutron SGs, so just
|
|
4034
4070
|
# pass things through
|
|
4035
|
-
|
|
4071
|
+
security_groups = parsed_args.security_groups
|
|
4036
4072
|
else:
|
|
4037
|
-
# however, if using nova-network then it needs
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4073
|
+
# however, if using nova-network then it needs names, not IDs
|
|
4074
|
+
security_groups = []
|
|
4075
|
+
for security_group in parsed_args.security_groups:
|
|
4076
|
+
security_groups.append(
|
|
4077
|
+
compute_v2.find_security_group(
|
|
4078
|
+
compute_client, security_group
|
|
4079
|
+
)['name']
|
|
4080
|
+
)
|
|
4081
|
+
|
|
4082
|
+
errors = 0
|
|
4083
|
+
for security_group in security_groups:
|
|
4084
|
+
try:
|
|
4085
|
+
compute_client.remove_security_group_from_server(
|
|
4086
|
+
server, security_group
|
|
4087
|
+
)
|
|
4088
|
+
except sdk_exceptions.HttpException as e:
|
|
4089
|
+
errors += 1
|
|
4090
|
+
LOG.error(
|
|
4091
|
+
_(
|
|
4092
|
+
"Failed to remove security group with name or ID "
|
|
4093
|
+
"'%(security_group)s' from server '%(server)s': %(e)s"
|
|
4094
|
+
),
|
|
4095
|
+
{
|
|
4096
|
+
'security_group': security_group,
|
|
4097
|
+
'server': server.id,
|
|
4098
|
+
'e': e,
|
|
4099
|
+
},
|
|
4100
|
+
)
|
|
4101
|
+
|
|
4102
|
+
if errors > 0:
|
|
4103
|
+
msg = _(
|
|
4104
|
+
"%(errors)d of %(total)d security groups were not removed."
|
|
4105
|
+
) % {'errors': errors, 'total': len(security_groups)}
|
|
4106
|
+
raise exceptions.CommandError(msg)
|
|
4044
4107
|
|
|
4045
4108
|
|
|
4046
4109
|
class RemoveServerVolume(command.Command):
|
|
@@ -4188,7 +4251,7 @@ release the new server and restart the old one."""
|
|
|
4188
4251
|
def take_action(self, parsed_args):
|
|
4189
4252
|
def _show_progress(progress):
|
|
4190
4253
|
if progress:
|
|
4191
|
-
self.app.stdout.write('\rProgress:
|
|
4254
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
4192
4255
|
self.app.stdout.flush()
|
|
4193
4256
|
|
|
4194
4257
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -4584,7 +4647,7 @@ class ShelveServer(command.Command):
|
|
|
4584
4647
|
def take_action(self, parsed_args):
|
|
4585
4648
|
def _show_progress(progress):
|
|
4586
4649
|
if progress:
|
|
4587
|
-
self.app.stdout.write('\rProgress:
|
|
4650
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
4588
4651
|
self.app.stdout.flush()
|
|
4589
4652
|
|
|
4590
4653
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -4872,7 +4935,7 @@ class SshServer(command.Command):
|
|
|
4872
4935
|
LOG.debug(f"ssh command: {cmd}")
|
|
4873
4936
|
# we intentionally pass through user-provided arguments and run this in
|
|
4874
4937
|
# the user's shell
|
|
4875
|
-
os.system(cmd) #
|
|
4938
|
+
os.system(cmd) # noqa: S605
|
|
4876
4939
|
|
|
4877
4940
|
|
|
4878
4941
|
class StartServer(command.Command):
|
|
@@ -5181,7 +5244,7 @@ class UnshelveServer(command.Command):
|
|
|
5181
5244
|
def take_action(self, parsed_args):
|
|
5182
5245
|
def _show_progress(progress):
|
|
5183
5246
|
if progress:
|
|
5184
|
-
self.app.stdout.write('\rProgress:
|
|
5247
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
5185
5248
|
self.app.stdout.flush()
|
|
5186
5249
|
|
|
5187
5250
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -68,7 +68,7 @@ class CreateServerBackup(command.ShowOne):
|
|
|
68
68
|
def take_action(self, parsed_args):
|
|
69
69
|
def _show_progress(progress):
|
|
70
70
|
if progress:
|
|
71
|
-
self.app.stderr.write('\rProgress:
|
|
71
|
+
self.app.stderr.write(f'\rProgress: {progress}')
|
|
72
72
|
self.app.stderr.flush()
|
|
73
73
|
|
|
74
74
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -69,7 +69,7 @@ class CreateServerImage(command.ShowOne):
|
|
|
69
69
|
def take_action(self, parsed_args):
|
|
70
70
|
def _show_progress(progress):
|
|
71
71
|
if progress:
|
|
72
|
-
self.app.stdout.write('\rProgress:
|
|
72
|
+
self.app.stdout.write(f'\rProgress: {progress}')
|
|
73
73
|
self.app.stdout.flush()
|
|
74
74
|
|
|
75
75
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
@@ -253,8 +253,17 @@ def _get_migration_by_uuid(compute_client, server_id, migration_uuid):
|
|
|
253
253
|
if migration.uuid == migration_uuid:
|
|
254
254
|
return migration
|
|
255
255
|
else:
|
|
256
|
-
msg = _(
|
|
257
|
-
|
|
256
|
+
msg = _(
|
|
257
|
+
'In-progress live migration %(migration)s is not found for '
|
|
258
|
+
'server %(server)s'
|
|
259
|
+
)
|
|
260
|
+
raise exceptions.CommandError(
|
|
261
|
+
msg
|
|
262
|
+
% {
|
|
263
|
+
'migration': migration_uuid,
|
|
264
|
+
'server': server_id,
|
|
265
|
+
}
|
|
266
|
+
)
|
|
258
267
|
|
|
259
268
|
|
|
260
269
|
class ShowMigration(command.ShowOne):
|
|
@@ -60,7 +60,7 @@ class CountColumn(cliff_columns.FormattableColumn):
|
|
|
60
60
|
|
|
61
61
|
class FloatColumn(cliff_columns.FormattableColumn):
|
|
62
62
|
def human_readable(self):
|
|
63
|
-
return float("
|
|
63
|
+
return float(f"{self._value:.2f}")
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
def _formatters(project_cache):
|
|
@@ -180,9 +180,9 @@ class ListUsage(command.Lister):
|
|
|
180
180
|
try:
|
|
181
181
|
for p in self.app.client_manager.identity.projects.list():
|
|
182
182
|
project_cache[p.id] = p
|
|
183
|
-
except Exception:
|
|
183
|
+
except Exception: # noqa: S110
|
|
184
184
|
# Just forget it if there's any trouble
|
|
185
|
-
pass
|
|
185
|
+
pass
|
|
186
186
|
|
|
187
187
|
if parsed_args.formatter == 'table' and len(usage_list) > 0:
|
|
188
188
|
self.app.stdout.write(
|
|
@@ -34,7 +34,7 @@ def find_service_in_list(service_list, service_id):
|
|
|
34
34
|
if service.id == service_id:
|
|
35
35
|
return service
|
|
36
36
|
raise exceptions.CommandError(
|
|
37
|
-
"No service with a type, name or ID of '
|
|
37
|
+
f"No service with a type, name or ID of '{service_id}' exists."
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
|
|
@@ -204,6 +204,7 @@ def find_group(identity_client, name_or_id, domain_name_or_id=None):
|
|
|
204
204
|
identity_client.groups, name_or_id, groups.Group
|
|
205
205
|
)
|
|
206
206
|
else:
|
|
207
|
+
domain_id = find_domain(identity_client, domain_id).id
|
|
207
208
|
return _find_identity_resource(
|
|
208
209
|
identity_client.groups,
|
|
209
210
|
name_or_id,
|
|
@@ -219,6 +220,7 @@ def find_project(identity_client, name_or_id, domain_name_or_id=None):
|
|
|
219
220
|
identity_client.projects, name_or_id, projects.Project
|
|
220
221
|
)
|
|
221
222
|
else:
|
|
223
|
+
domain_id = find_domain(identity_client, domain_id).id
|
|
222
224
|
return _find_identity_resource(
|
|
223
225
|
identity_client.projects,
|
|
224
226
|
name_or_id,
|
|
@@ -234,6 +236,7 @@ def find_user(identity_client, name_or_id, domain_name_or_id=None):
|
|
|
234
236
|
identity_client.users, name_or_id, users.User
|
|
235
237
|
)
|
|
236
238
|
else:
|
|
239
|
+
domain_id = find_domain(identity_client, domain_id).id
|
|
237
240
|
return _find_identity_resource(
|
|
238
241
|
identity_client.users, name_or_id, users.User, domain_id=domain_id
|
|
239
242
|
)
|