python-openstackclient 7.2.1__py3-none-any.whl → 7.3.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/limits.py +1 -1
- openstackclient/common/quota.py +7 -2
- openstackclient/compute/v2/server.py +38 -22
- openstackclient/compute/v2/usage.py +2 -2
- openstackclient/identity/common.py +22 -34
- openstackclient/identity/v3/credential.py +45 -28
- openstackclient/identity/v3/limit.py +15 -0
- openstackclient/identity/v3/region.py +23 -22
- openstackclient/identity/v3/registered_limit.py +18 -0
- openstackclient/identity/v3/role.py +287 -117
- openstackclient/identity/v3/role_assignment.py +1 -1
- openstackclient/identity/v3/service_provider.py +95 -45
- openstackclient/identity/v3/trust.py +114 -75
- openstackclient/image/v2/image.py +3 -0
- openstackclient/network/v2/network.py +33 -0
- openstackclient/network/v2/network_flavor_profile.py +1 -17
- openstackclient/network/v2/port.py +75 -20
- openstackclient/tests/functional/compute/v2/test_server.py +87 -1
- openstackclient/tests/functional/identity/v3/common.py +1 -1
- openstackclient/tests/functional/identity/v3/test_application_credential.py +2 -1
- openstackclient/tests/functional/identity/v3/test_role.py +24 -0
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +8 -0
- openstackclient/tests/functional/identity/v3/test_service_provider.py +1 -5
- openstackclient/tests/functional/network/v2/test_port.py +107 -1
- openstackclient/tests/unit/compute/v2/fakes.py +0 -304
- openstackclient/tests/unit/compute/v2/test_aggregate.py +40 -31
- openstackclient/tests/unit/compute/v2/test_console.py +7 -3
- openstackclient/tests/unit/compute/v2/test_hypervisor.py +60 -53
- openstackclient/tests/unit/compute/v2/test_keypair.py +57 -69
- openstackclient/tests/unit/compute/v2/test_server.py +63 -5
- openstackclient/tests/unit/compute/v2/test_server_group.py +99 -105
- openstackclient/tests/unit/compute/v2/test_server_volume.py +12 -5
- openstackclient/tests/unit/compute/v2/test_service.py +83 -37
- openstackclient/tests/unit/compute/v2/test_usage.py +12 -7
- openstackclient/tests/unit/identity/v2_0/test_catalog.py +3 -6
- openstackclient/tests/unit/identity/v2_0/test_role.py +1 -2
- openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +2 -1
- openstackclient/tests/unit/identity/v2_0/test_token.py +6 -20
- openstackclient/tests/unit/identity/v3/test_catalog.py +2 -5
- openstackclient/tests/unit/identity/v3/test_credential.py +74 -63
- openstackclient/tests/unit/identity/v3/test_project.py +1 -3
- openstackclient/tests/unit/identity/v3/test_region.py +74 -96
- openstackclient/tests/unit/identity/v3/test_role.py +679 -603
- openstackclient/tests/unit/identity/v3/test_role_assignment.py +263 -1
- openstackclient/tests/unit/identity/v3/test_service_provider.py +159 -209
- openstackclient/tests/unit/identity/v3/test_token.py +5 -20
- openstackclient/tests/unit/identity/v3/test_trust.py +137 -155
- openstackclient/tests/unit/image/v2/test_image.py +6 -0
- openstackclient/tests/unit/network/v2/fakes.py +3 -0
- openstackclient/tests/unit/network/v2/test_network.py +25 -0
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +0 -35
- openstackclient/tests/unit/network/v2/test_port.py +128 -15
- openstackclient/tests/unit/utils.py +8 -2
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +31 -13
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +34 -13
- openstackclient/volume/v2/volume_backup.py +11 -2
- openstackclient/volume/v3/volume_backup.py +13 -2
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/AUTHORS +2 -0
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/METADATA +14 -16
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/RECORD +65 -65
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/WHEEL +1 -1
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/entry_points.txt +0 -1
- python_openstackclient-7.3.1.dist-info/pbr.json +1 -0
- python_openstackclient-7.2.1.dist-info/pbr.json +0 -1
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/LICENSE +0 -0
- {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.1.dist-info}/top_level.txt +0 -0
|
@@ -25,6 +25,29 @@ from openstackclient.i18n import _
|
|
|
25
25
|
LOG = logging.getLogger(__name__)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
def _format_service_provider(sp):
|
|
29
|
+
column_headers = (
|
|
30
|
+
'id',
|
|
31
|
+
'enabled',
|
|
32
|
+
'description',
|
|
33
|
+
'auth_url',
|
|
34
|
+
'sp_url',
|
|
35
|
+
'relay_state_prefix',
|
|
36
|
+
)
|
|
37
|
+
columns = (
|
|
38
|
+
'id',
|
|
39
|
+
'is_enabled',
|
|
40
|
+
'description',
|
|
41
|
+
'auth_url',
|
|
42
|
+
'sp_url',
|
|
43
|
+
'relay_state_prefix',
|
|
44
|
+
)
|
|
45
|
+
return (
|
|
46
|
+
column_headers,
|
|
47
|
+
utils.get_item_properties(sp, columns),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
28
51
|
class CreateServiceProvider(command.ShowOne):
|
|
29
52
|
_description = _("Create new service provider")
|
|
30
53
|
|
|
@@ -62,14 +85,14 @@ class CreateServiceProvider(command.ShowOne):
|
|
|
62
85
|
enable_service_provider = parser.add_mutually_exclusive_group()
|
|
63
86
|
enable_service_provider.add_argument(
|
|
64
87
|
'--enable',
|
|
65
|
-
dest='
|
|
88
|
+
dest='is_enabled',
|
|
66
89
|
action='store_true',
|
|
67
90
|
default=True,
|
|
68
91
|
help=_('Enable the service provider (default)'),
|
|
69
92
|
)
|
|
70
93
|
enable_service_provider.add_argument(
|
|
71
94
|
'--disable',
|
|
72
|
-
dest='
|
|
95
|
+
dest='is_enabled',
|
|
73
96
|
action='store_false',
|
|
74
97
|
help=_('Disable the service provider'),
|
|
75
98
|
)
|
|
@@ -77,17 +100,27 @@ class CreateServiceProvider(command.ShowOne):
|
|
|
77
100
|
return parser
|
|
78
101
|
|
|
79
102
|
def take_action(self, parsed_args):
|
|
80
|
-
service_client = self.app.client_manager.identity
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
103
|
+
service_client = self.app.client_manager.sdk_connection.identity
|
|
104
|
+
|
|
105
|
+
kwargs = {}
|
|
106
|
+
|
|
107
|
+
kwargs = {'id': parsed_args.service_provider_id}
|
|
108
|
+
|
|
109
|
+
if parsed_args.is_enabled is not None:
|
|
110
|
+
kwargs['is_enabled'] = parsed_args.is_enabled
|
|
88
111
|
|
|
89
|
-
|
|
90
|
-
|
|
112
|
+
if parsed_args.description:
|
|
113
|
+
kwargs['description'] = parsed_args.description
|
|
114
|
+
|
|
115
|
+
if parsed_args.auth_url:
|
|
116
|
+
kwargs['auth_url'] = parsed_args.auth_url
|
|
117
|
+
|
|
118
|
+
if parsed_args.service_provider_url:
|
|
119
|
+
kwargs['sp_url'] = parsed_args.service_provider_url
|
|
120
|
+
|
|
121
|
+
sp = service_client.create_service_provider(**kwargs)
|
|
122
|
+
|
|
123
|
+
return _format_service_provider(sp)
|
|
91
124
|
|
|
92
125
|
|
|
93
126
|
class DeleteServiceProvider(command.Command):
|
|
@@ -104,11 +137,11 @@ class DeleteServiceProvider(command.Command):
|
|
|
104
137
|
return parser
|
|
105
138
|
|
|
106
139
|
def take_action(self, parsed_args):
|
|
107
|
-
service_client = self.app.client_manager.identity
|
|
140
|
+
service_client = self.app.client_manager.sdk_connection.identity
|
|
108
141
|
result = 0
|
|
109
142
|
for i in parsed_args.service_provider:
|
|
110
143
|
try:
|
|
111
|
-
service_client.
|
|
144
|
+
service_client.delete_service_provider(i)
|
|
112
145
|
except Exception as e:
|
|
113
146
|
result += 1
|
|
114
147
|
LOG.error(
|
|
@@ -132,24 +165,32 @@ class ListServiceProvider(command.Lister):
|
|
|
132
165
|
_description = _("List service providers")
|
|
133
166
|
|
|
134
167
|
def take_action(self, parsed_args):
|
|
135
|
-
service_client = self.app.client_manager.identity
|
|
136
|
-
data = service_client.
|
|
137
|
-
|
|
138
|
-
column_headers = (
|
|
168
|
+
service_client = self.app.client_manager.sdk_connection.identity
|
|
169
|
+
data = service_client.service_providers()
|
|
170
|
+
|
|
171
|
+
column_headers = (
|
|
172
|
+
'ID',
|
|
173
|
+
'Enabled',
|
|
174
|
+
'Description',
|
|
175
|
+
'Auth URL',
|
|
176
|
+
'Service Provider URL',
|
|
177
|
+
'Relay State Prefix',
|
|
178
|
+
)
|
|
179
|
+
columns = (
|
|
180
|
+
'id',
|
|
181
|
+
'is_enabled',
|
|
182
|
+
'description',
|
|
183
|
+
'auth_url',
|
|
184
|
+
'sp_url',
|
|
185
|
+
'relay_state_prefix',
|
|
186
|
+
)
|
|
139
187
|
return (
|
|
140
188
|
column_headers,
|
|
141
|
-
(
|
|
142
|
-
utils.get_item_properties(
|
|
143
|
-
s,
|
|
144
|
-
column_headers,
|
|
145
|
-
formatters={},
|
|
146
|
-
)
|
|
147
|
-
for s in data
|
|
148
|
-
),
|
|
189
|
+
(utils.get_item_properties(s, columns) for s in data),
|
|
149
190
|
)
|
|
150
191
|
|
|
151
192
|
|
|
152
|
-
class SetServiceProvider(command.
|
|
193
|
+
class SetServiceProvider(command.ShowOne):
|
|
153
194
|
_description = _("Set service provider properties")
|
|
154
195
|
|
|
155
196
|
def get_parser(self, prog_name):
|
|
@@ -181,33 +222,44 @@ class SetServiceProvider(command.Command):
|
|
|
181
222
|
enable_service_provider = parser.add_mutually_exclusive_group()
|
|
182
223
|
enable_service_provider.add_argument(
|
|
183
224
|
'--enable',
|
|
225
|
+
dest='is_enabled',
|
|
184
226
|
action='store_true',
|
|
227
|
+
default=None,
|
|
185
228
|
help=_('Enable the service provider'),
|
|
186
229
|
)
|
|
187
230
|
enable_service_provider.add_argument(
|
|
188
231
|
'--disable',
|
|
189
|
-
|
|
232
|
+
dest='is_enabled',
|
|
233
|
+
action='store_false',
|
|
234
|
+
default=None,
|
|
190
235
|
help=_('Disable the service provider'),
|
|
191
236
|
)
|
|
192
237
|
return parser
|
|
193
238
|
|
|
194
239
|
def take_action(self, parsed_args):
|
|
195
|
-
|
|
240
|
+
service_client = self.app.client_manager.sdk_connection.identity
|
|
196
241
|
|
|
197
|
-
|
|
198
|
-
if parsed_args.enable is True:
|
|
199
|
-
enabled = True
|
|
200
|
-
elif parsed_args.disable is True:
|
|
201
|
-
enabled = False
|
|
242
|
+
kwargs = {}
|
|
202
243
|
|
|
203
|
-
|
|
244
|
+
if parsed_args.is_enabled is not None:
|
|
245
|
+
kwargs['is_enabled'] = parsed_args.is_enabled
|
|
246
|
+
|
|
247
|
+
if parsed_args.description:
|
|
248
|
+
kwargs['description'] = parsed_args.description
|
|
249
|
+
|
|
250
|
+
if parsed_args.auth_url:
|
|
251
|
+
kwargs['auth_url'] = parsed_args.auth_url
|
|
252
|
+
|
|
253
|
+
if parsed_args.service_provider_url:
|
|
254
|
+
kwargs['sp_url'] = parsed_args.service_provider_url
|
|
255
|
+
|
|
256
|
+
service_provider = service_client.update_service_provider(
|
|
204
257
|
parsed_args.service_provider,
|
|
205
|
-
|
|
206
|
-
description=parsed_args.description,
|
|
207
|
-
auth_url=parsed_args.auth_url,
|
|
208
|
-
sp_url=parsed_args.service_provider_url,
|
|
258
|
+
**kwargs,
|
|
209
259
|
)
|
|
210
260
|
|
|
261
|
+
return _format_service_provider(service_provider)
|
|
262
|
+
|
|
211
263
|
|
|
212
264
|
class ShowServiceProvider(command.ShowOne):
|
|
213
265
|
_description = _("Display service provider details")
|
|
@@ -222,12 +274,10 @@ class ShowServiceProvider(command.ShowOne):
|
|
|
222
274
|
return parser
|
|
223
275
|
|
|
224
276
|
def take_action(self, parsed_args):
|
|
225
|
-
service_client = self.app.client_manager.identity
|
|
226
|
-
service_provider =
|
|
227
|
-
service_client.federation.service_providers,
|
|
277
|
+
service_client = self.app.client_manager.sdk_connection.identity
|
|
278
|
+
service_provider = service_client.find_service_provider(
|
|
228
279
|
parsed_args.service_provider,
|
|
229
|
-
|
|
280
|
+
ignore_missing=False,
|
|
230
281
|
)
|
|
231
282
|
|
|
232
|
-
service_provider
|
|
233
|
-
return zip(*sorted(service_provider._info.items()))
|
|
283
|
+
return _format_service_provider(service_provider)
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
"""Identity v3 Trust action implementations"""
|
|
15
15
|
|
|
16
16
|
import datetime
|
|
17
|
+
import itertools
|
|
17
18
|
import logging
|
|
18
19
|
|
|
19
|
-
from
|
|
20
|
+
from openstack import exceptions as sdk_exceptions
|
|
20
21
|
from osc_lib.command import command
|
|
21
22
|
from osc_lib import exceptions
|
|
22
23
|
from osc_lib import utils
|
|
@@ -28,6 +29,25 @@ from openstackclient.identity import common
|
|
|
28
29
|
LOG = logging.getLogger(__name__)
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
def _format_trust(trust):
|
|
33
|
+
columns = (
|
|
34
|
+
'expires_at',
|
|
35
|
+
'id',
|
|
36
|
+
'is_impersonation',
|
|
37
|
+
'project_id',
|
|
38
|
+
'redelegated_trust_id',
|
|
39
|
+
'redelegation_count',
|
|
40
|
+
'remaining_uses',
|
|
41
|
+
'roles',
|
|
42
|
+
'trustee_user_id',
|
|
43
|
+
'trustor_user_id',
|
|
44
|
+
)
|
|
45
|
+
return (
|
|
46
|
+
columns,
|
|
47
|
+
utils.get_item_properties(trust, columns),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
31
51
|
class CreateTrust(command.ShowOne):
|
|
32
52
|
_description = _("Create new trust")
|
|
33
53
|
|
|
@@ -52,6 +72,7 @@ class CreateTrust(command.ShowOne):
|
|
|
52
72
|
parser.add_argument(
|
|
53
73
|
'--role',
|
|
54
74
|
metavar='<role>',
|
|
75
|
+
dest='roles',
|
|
55
76
|
action='append',
|
|
56
77
|
default=[],
|
|
57
78
|
help=_(
|
|
@@ -62,7 +83,7 @@ class CreateTrust(command.ShowOne):
|
|
|
62
83
|
)
|
|
63
84
|
parser.add_argument(
|
|
64
85
|
'--impersonate',
|
|
65
|
-
dest='
|
|
86
|
+
dest='is_impersonation',
|
|
66
87
|
action='store_true',
|
|
67
88
|
default=False,
|
|
68
89
|
help=_(
|
|
@@ -92,58 +113,60 @@ class CreateTrust(command.ShowOne):
|
|
|
92
113
|
return parser
|
|
93
114
|
|
|
94
115
|
def take_action(self, parsed_args):
|
|
95
|
-
identity_client = self.app.client_manager.identity
|
|
116
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
117
|
+
|
|
118
|
+
kwargs = {}
|
|
96
119
|
|
|
97
120
|
# NOTE(stevemar): Find the two users, project and roles that
|
|
98
121
|
# are necessary for making a trust usable, the API dictates that
|
|
99
122
|
# trustee, project and role are optional, but that makes the trust
|
|
100
123
|
# pointless, and trusts are immutable, so let's enforce it at the
|
|
101
124
|
# client level.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
125
|
+
try:
|
|
126
|
+
trustor_id = identity_client.find_user(
|
|
127
|
+
parsed_args.trustor, parsed_args.trustor_domain
|
|
128
|
+
).id
|
|
129
|
+
kwargs['trustor_id'] = trustor_id
|
|
130
|
+
except sdk_exceptions.ForbiddenException:
|
|
131
|
+
kwargs['trustor_id'] = parsed_args.trustor
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
trustee_id = identity_client.find_user(
|
|
135
|
+
parsed_args.trustee, parsed_args.trustee_domain
|
|
136
|
+
).id
|
|
137
|
+
kwargs['trustee_id'] = trustee_id
|
|
138
|
+
except sdk_exceptions.ForbiddenException:
|
|
139
|
+
kwargs['trustee_id'] = parsed_args.trustee
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
project_id = identity_client.find_project(
|
|
143
|
+
parsed_args.project, parsed_args.project_domain
|
|
144
|
+
).id
|
|
145
|
+
kwargs['project_id'] = project_id
|
|
146
|
+
except sdk_exceptions.ForbiddenException:
|
|
147
|
+
kwargs['project_id'] = parsed_args.project
|
|
111
148
|
|
|
112
149
|
role_ids = []
|
|
113
|
-
for role in parsed_args.
|
|
150
|
+
for role in parsed_args.roles:
|
|
114
151
|
try:
|
|
115
|
-
role_id =
|
|
116
|
-
|
|
117
|
-
role,
|
|
118
|
-
).id
|
|
119
|
-
except identity_exc.Forbidden:
|
|
152
|
+
role_id = identity_client.find_role(role).id
|
|
153
|
+
except sdk_exceptions.ForbiddenException:
|
|
120
154
|
role_id = role
|
|
121
155
|
role_ids.append(role_id)
|
|
156
|
+
kwargs['roles'] = role_ids
|
|
122
157
|
|
|
123
|
-
expires_at = None
|
|
124
158
|
if parsed_args.expiration:
|
|
125
159
|
expires_at = datetime.datetime.strptime(
|
|
126
160
|
parsed_args.expiration, '%Y-%m-%dT%H:%M:%S'
|
|
127
161
|
)
|
|
162
|
+
kwargs['expires_at'] = expires_at
|
|
128
163
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
trustor_id,
|
|
132
|
-
impersonation=parsed_args.impersonate,
|
|
133
|
-
project=project_id,
|
|
134
|
-
role_ids=role_ids,
|
|
135
|
-
expires_at=expires_at,
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
trust._info.pop('roles_links', None)
|
|
139
|
-
trust._info.pop('links', None)
|
|
164
|
+
if parsed_args.is_impersonation:
|
|
165
|
+
kwargs['is_impersonation'] = parsed_args.is_impersonation
|
|
140
166
|
|
|
141
|
-
|
|
142
|
-
roles = trust._info.pop('roles')
|
|
143
|
-
msg = ' '.join(r['name'] for r in roles)
|
|
144
|
-
trust._info['roles'] = msg
|
|
167
|
+
trust = identity_client.create_trust(**kwargs)
|
|
145
168
|
|
|
146
|
-
return
|
|
169
|
+
return _format_trust(trust)
|
|
147
170
|
|
|
148
171
|
|
|
149
172
|
class DeleteTrust(command.Command):
|
|
@@ -160,13 +183,15 @@ class DeleteTrust(command.Command):
|
|
|
160
183
|
return parser
|
|
161
184
|
|
|
162
185
|
def take_action(self, parsed_args):
|
|
163
|
-
identity_client = self.app.client_manager.identity
|
|
186
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
164
187
|
|
|
165
188
|
errors = 0
|
|
166
189
|
for trust in parsed_args.trust:
|
|
167
190
|
try:
|
|
168
|
-
trust_obj =
|
|
169
|
-
|
|
191
|
+
trust_obj = identity_client.find_trust(
|
|
192
|
+
trust, ignore_missing=False
|
|
193
|
+
)
|
|
194
|
+
identity_client.delete_trust(trust_obj.id)
|
|
170
195
|
except Exception as e:
|
|
171
196
|
errors += 1
|
|
172
197
|
LOG.error(
|
|
@@ -220,7 +245,7 @@ class ListTrust(command.Lister):
|
|
|
220
245
|
return parser
|
|
221
246
|
|
|
222
247
|
def take_action(self, parsed_args):
|
|
223
|
-
identity_client = self.app.client_manager.identity
|
|
248
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
224
249
|
auth_ref = self.app.client_manager.auth_ref
|
|
225
250
|
|
|
226
251
|
if parsed_args.authuser and any(
|
|
@@ -243,38 +268,50 @@ class ListTrust(command.Lister):
|
|
|
243
268
|
raise exceptions.CommandError(msg)
|
|
244
269
|
|
|
245
270
|
if parsed_args.authuser:
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
271
|
+
# We need two calls here as we want trusts with
|
|
272
|
+
# either the trustor or the trustee set to current user
|
|
273
|
+
# using a single call would give us trusts with both
|
|
274
|
+
# trustee and trustor set to current user
|
|
275
|
+
data = list(
|
|
276
|
+
{
|
|
277
|
+
x.id: x
|
|
278
|
+
for x in itertools.chain(
|
|
279
|
+
identity_client.trusts(
|
|
280
|
+
trustor_user_id=auth_ref.user_id
|
|
281
|
+
),
|
|
282
|
+
identity_client.trusts(
|
|
283
|
+
trustee_user_id=auth_ref.user_id
|
|
284
|
+
),
|
|
285
|
+
)
|
|
286
|
+
}.values()
|
|
287
|
+
)
|
|
255
288
|
else:
|
|
256
289
|
trustor = None
|
|
257
290
|
if parsed_args.trustor:
|
|
258
|
-
|
|
259
|
-
identity_client
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
291
|
+
try:
|
|
292
|
+
trustor_id = identity_client.find_user(
|
|
293
|
+
parsed_args.trustor, parsed_args.trustor_domain
|
|
294
|
+
).id
|
|
295
|
+
trustor = trustor_id
|
|
296
|
+
except sdk_exceptions.ForbiddenException:
|
|
297
|
+
trustor = parsed_args.trustor
|
|
263
298
|
|
|
264
299
|
trustee = None
|
|
265
300
|
if parsed_args.trustee:
|
|
266
|
-
|
|
267
|
-
identity_client
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
301
|
+
try:
|
|
302
|
+
trustee_id = identity_client.find_user(
|
|
303
|
+
parsed_args.trustee, parsed_args.trustee_domain
|
|
304
|
+
).id
|
|
305
|
+
trustee = trustee_id
|
|
306
|
+
except sdk_exceptions.ForbiddenException:
|
|
307
|
+
trustee = parsed_args.trustee
|
|
308
|
+
|
|
309
|
+
data = identity_client.trusts(
|
|
310
|
+
trustor_user_id=trustor,
|
|
311
|
+
trustee_user_id=trustee,
|
|
275
312
|
)
|
|
276
313
|
|
|
277
|
-
|
|
314
|
+
column_headers = (
|
|
278
315
|
'ID',
|
|
279
316
|
'Expires At',
|
|
280
317
|
'Impersonation',
|
|
@@ -282,9 +319,17 @@ class ListTrust(command.Lister):
|
|
|
282
319
|
'Trustee User ID',
|
|
283
320
|
'Trustor User ID',
|
|
284
321
|
)
|
|
322
|
+
columns = (
|
|
323
|
+
'id',
|
|
324
|
+
'expires_at',
|
|
325
|
+
'is_impersonation',
|
|
326
|
+
'project_id',
|
|
327
|
+
'trustee_user_id',
|
|
328
|
+
'trustor_user_id',
|
|
329
|
+
)
|
|
285
330
|
|
|
286
331
|
return (
|
|
287
|
-
|
|
332
|
+
column_headers,
|
|
288
333
|
(
|
|
289
334
|
utils.get_item_properties(
|
|
290
335
|
s,
|
|
@@ -309,15 +354,9 @@ class ShowTrust(command.ShowOne):
|
|
|
309
354
|
return parser
|
|
310
355
|
|
|
311
356
|
def take_action(self, parsed_args):
|
|
312
|
-
identity_client = self.app.client_manager.identity
|
|
313
|
-
trust =
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
trust._info.pop('links', None)
|
|
317
|
-
|
|
318
|
-
# Format roles into something sensible
|
|
319
|
-
roles = trust._info.pop('roles')
|
|
320
|
-
msg = ' '.join(r['name'] for r in roles)
|
|
321
|
-
trust._info['roles'] = msg
|
|
357
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
358
|
+
trust = identity_client.find_trust(
|
|
359
|
+
parsed_args.trust, ignore_missing=False
|
|
360
|
+
)
|
|
322
361
|
|
|
323
|
-
return
|
|
362
|
+
return _format_trust(trust)
|
|
@@ -576,6 +576,9 @@ class CreateImage(command.ShowOne):
|
|
|
576
576
|
if parsed_args.filename:
|
|
577
577
|
fp.close()
|
|
578
578
|
|
|
579
|
+
# NOTE(pas-ha): create_image returns the image object as it was created
|
|
580
|
+
# before the data was uploaded, need a refresh to show the final state
|
|
581
|
+
image = image_client.get_image(image)
|
|
579
582
|
return _format_image(image)
|
|
580
583
|
|
|
581
584
|
def _take_action_volume(self, parsed_args):
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from cliff import columns as cliff_columns
|
|
16
16
|
from osc_lib.cli import format_columns
|
|
17
|
+
from osc_lib import exceptions
|
|
17
18
|
from osc_lib import utils
|
|
18
19
|
from osc_lib.utils import tags as _tag
|
|
19
20
|
|
|
@@ -349,6 +350,25 @@ class CreateNetwork(
|
|
|
349
350
|
),
|
|
350
351
|
)
|
|
351
352
|
|
|
353
|
+
vlan_qinq_grp = parser.add_mutually_exclusive_group()
|
|
354
|
+
vlan_qinq_grp.add_argument(
|
|
355
|
+
'--qinq-vlan',
|
|
356
|
+
action='store_true',
|
|
357
|
+
help=self.enhance_help_neutron(
|
|
358
|
+
_("Enable VLAN QinQ (S-Tag ethtype 0x8a88) " "for the network")
|
|
359
|
+
),
|
|
360
|
+
)
|
|
361
|
+
vlan_qinq_grp.add_argument(
|
|
362
|
+
'--no-qinq-vlan',
|
|
363
|
+
action='store_true',
|
|
364
|
+
help=self.enhance_help_neutron(
|
|
365
|
+
_(
|
|
366
|
+
"Disable VLAN QinQ (S-Tag ethtype 0x8a88) "
|
|
367
|
+
"for the network"
|
|
368
|
+
)
|
|
369
|
+
),
|
|
370
|
+
)
|
|
371
|
+
|
|
352
372
|
_add_additional_network_options(parser)
|
|
353
373
|
_tag.add_tag_option_to_parser_for_create(
|
|
354
374
|
parser, _('network'), enhance_help=self.enhance_help_neutron
|
|
@@ -372,6 +392,19 @@ class CreateNetwork(
|
|
|
372
392
|
attrs['vlan_transparent'] = True
|
|
373
393
|
if parsed_args.no_transparent_vlan:
|
|
374
394
|
attrs['vlan_transparent'] = False
|
|
395
|
+
|
|
396
|
+
if parsed_args.qinq_vlan:
|
|
397
|
+
attrs['vlan_qinq'] = True
|
|
398
|
+
if parsed_args.no_qinq_vlan:
|
|
399
|
+
attrs['vlan_qinq'] = False
|
|
400
|
+
|
|
401
|
+
if attrs.get('vlan_transparent') and attrs.get('vlan_qinq'):
|
|
402
|
+
msg = _(
|
|
403
|
+
"--transparent-vlan and --qinq-vlan can not be both enabled "
|
|
404
|
+
"for the network."
|
|
405
|
+
)
|
|
406
|
+
raise exceptions.CommandError(msg)
|
|
407
|
+
|
|
375
408
|
attrs.update(
|
|
376
409
|
self._parse_extra_properties(parsed_args.extra_properties)
|
|
377
410
|
)
|
|
@@ -18,7 +18,6 @@ from osc_lib import exceptions
|
|
|
18
18
|
from osc_lib import utils
|
|
19
19
|
|
|
20
20
|
from openstackclient.i18n import _
|
|
21
|
-
from openstackclient.identity import common as identity_common
|
|
22
21
|
from openstackclient.network import common
|
|
23
22
|
|
|
24
23
|
LOG = logging.getLogger(__name__)
|
|
@@ -29,7 +28,7 @@ def _get_columns(item):
|
|
|
29
28
|
'is_enabled': 'enabled',
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
hidden_columns = ['location', 'name', 'tenant_id']
|
|
31
|
+
hidden_columns = ['location', 'name', 'tenant_id', 'project_id']
|
|
33
32
|
return utils.get_osc_show_columns_for_sdk_resource(
|
|
34
33
|
item, column_map, hidden_columns
|
|
35
34
|
)
|
|
@@ -47,14 +46,6 @@ def _get_attrs(client_manager, parsed_args):
|
|
|
47
46
|
attrs['enabled'] = True
|
|
48
47
|
if parsed_args.disable:
|
|
49
48
|
attrs['enabled'] = False
|
|
50
|
-
if 'project' in parsed_args and parsed_args.project is not None:
|
|
51
|
-
identity_client = client_manager.identity
|
|
52
|
-
project_id = identity_common.find_project(
|
|
53
|
-
identity_client,
|
|
54
|
-
parsed_args.project,
|
|
55
|
-
parsed_args.project_domain,
|
|
56
|
-
).id
|
|
57
|
-
attrs['project_id'] = project_id
|
|
58
49
|
|
|
59
50
|
return attrs
|
|
60
51
|
|
|
@@ -68,12 +59,6 @@ class CreateNetworkFlavorProfile(
|
|
|
68
59
|
|
|
69
60
|
def get_parser(self, prog_name):
|
|
70
61
|
parser = super().get_parser(prog_name)
|
|
71
|
-
parser.add_argument(
|
|
72
|
-
'--project',
|
|
73
|
-
metavar="<project>",
|
|
74
|
-
help=_("Owner's project (name or ID)"),
|
|
75
|
-
)
|
|
76
|
-
identity_common.add_project_domain_option_to_parser(parser)
|
|
77
62
|
parser.add_argument(
|
|
78
63
|
'--description',
|
|
79
64
|
metavar="<description>",
|
|
@@ -212,7 +197,6 @@ class SetNetworkFlavorProfile(common.NeutronCommandWithExtraArgs):
|
|
|
212
197
|
metavar="<flavor-profile>",
|
|
213
198
|
help=_("Flavor profile to update (ID only)"),
|
|
214
199
|
)
|
|
215
|
-
identity_common.add_project_domain_option_to_parser(parser)
|
|
216
200
|
parser.add_argument(
|
|
217
201
|
'--description',
|
|
218
202
|
metavar="<description>",
|