python-openstackclient 7.2.1__py3-none-any.whl → 7.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. openstackclient/common/limits.py +1 -1
  2. openstackclient/common/quota.py +7 -2
  3. openstackclient/compute/v2/server.py +38 -22
  4. openstackclient/compute/v2/usage.py +2 -2
  5. openstackclient/identity/common.py +22 -34
  6. openstackclient/identity/v3/credential.py +45 -28
  7. openstackclient/identity/v3/limit.py +15 -0
  8. openstackclient/identity/v3/region.py +23 -22
  9. openstackclient/identity/v3/registered_limit.py +18 -0
  10. openstackclient/identity/v3/role.py +287 -117
  11. openstackclient/identity/v3/role_assignment.py +1 -1
  12. openstackclient/identity/v3/service_provider.py +95 -45
  13. openstackclient/identity/v3/trust.py +114 -75
  14. openstackclient/image/v2/image.py +3 -0
  15. openstackclient/network/v2/network.py +33 -0
  16. openstackclient/network/v2/network_flavor_profile.py +1 -17
  17. openstackclient/network/v2/port.py +73 -19
  18. openstackclient/tests/functional/compute/v2/test_server.py +87 -1
  19. openstackclient/tests/functional/identity/v3/common.py +1 -1
  20. openstackclient/tests/functional/identity/v3/test_application_credential.py +2 -1
  21. openstackclient/tests/functional/identity/v3/test_role.py +24 -0
  22. openstackclient/tests/functional/identity/v3/test_role_assignment.py +8 -0
  23. openstackclient/tests/functional/identity/v3/test_service_provider.py +1 -5
  24. openstackclient/tests/functional/network/v2/test_port.py +28 -1
  25. openstackclient/tests/unit/compute/v2/fakes.py +0 -304
  26. openstackclient/tests/unit/compute/v2/test_aggregate.py +40 -31
  27. openstackclient/tests/unit/compute/v2/test_console.py +7 -3
  28. openstackclient/tests/unit/compute/v2/test_hypervisor.py +60 -53
  29. openstackclient/tests/unit/compute/v2/test_keypair.py +57 -69
  30. openstackclient/tests/unit/compute/v2/test_server.py +63 -5
  31. openstackclient/tests/unit/compute/v2/test_server_group.py +99 -105
  32. openstackclient/tests/unit/compute/v2/test_server_volume.py +12 -5
  33. openstackclient/tests/unit/compute/v2/test_service.py +83 -37
  34. openstackclient/tests/unit/compute/v2/test_usage.py +12 -7
  35. openstackclient/tests/unit/identity/v2_0/test_catalog.py +3 -6
  36. openstackclient/tests/unit/identity/v2_0/test_role.py +1 -2
  37. openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +2 -1
  38. openstackclient/tests/unit/identity/v2_0/test_token.py +6 -20
  39. openstackclient/tests/unit/identity/v3/test_catalog.py +2 -5
  40. openstackclient/tests/unit/identity/v3/test_credential.py +74 -63
  41. openstackclient/tests/unit/identity/v3/test_project.py +1 -3
  42. openstackclient/tests/unit/identity/v3/test_region.py +74 -96
  43. openstackclient/tests/unit/identity/v3/test_role.py +679 -603
  44. openstackclient/tests/unit/identity/v3/test_role_assignment.py +263 -1
  45. openstackclient/tests/unit/identity/v3/test_service_provider.py +159 -209
  46. openstackclient/tests/unit/identity/v3/test_token.py +5 -20
  47. openstackclient/tests/unit/identity/v3/test_trust.py +137 -155
  48. openstackclient/tests/unit/image/v2/test_image.py +6 -0
  49. openstackclient/tests/unit/network/v2/fakes.py +3 -0
  50. openstackclient/tests/unit/network/v2/test_network.py +25 -0
  51. openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +0 -35
  52. openstackclient/tests/unit/network/v2/test_port.py +129 -16
  53. openstackclient/tests/unit/utils.py +8 -2
  54. openstackclient/tests/unit/volume/v2/test_volume_backup.py +31 -13
  55. openstackclient/tests/unit/volume/v3/test_volume_backup.py +34 -13
  56. openstackclient/volume/v2/volume_backup.py +11 -2
  57. openstackclient/volume/v3/volume_backup.py +13 -2
  58. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.dist-info}/AUTHORS +2 -0
  59. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.dist-info}/METADATA +14 -16
  60. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.dist-info}/RECORD +65 -65
  61. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.dist-info}/WHEEL +1 -1
  62. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.dist-info}/entry_points.txt +0 -1
  63. python_openstackclient-7.3.0.dist-info/pbr.json +1 -0
  64. python_openstackclient-7.2.1.dist-info/pbr.json +0 -1
  65. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.dist-info}/LICENSE +0 -0
  66. {python_openstackclient-7.2.1.dist-info → python_openstackclient-7.3.0.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='enabled',
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='enabled',
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
- sp = service_client.federation.service_providers.create(
82
- id=parsed_args.service_provider_id,
83
- auth_url=parsed_args.auth_url,
84
- description=parsed_args.description,
85
- enabled=parsed_args.enabled,
86
- sp_url=parsed_args.service_provider_url,
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
- sp._info.pop('links', None)
90
- return zip(*sorted(sp._info.items()))
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.federation.service_providers.delete(i)
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.federation.service_providers.list()
137
-
138
- column_headers = ('ID', 'Enabled', 'Description', 'Auth URL')
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.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
- action='store_true',
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
- federation_client = self.app.client_manager.identity.federation
240
+ service_client = self.app.client_manager.sdk_connection.identity
196
241
 
197
- enabled = None
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
- federation_client.service_providers.update(
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
- enabled=enabled,
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 = utils.find_resource(
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
- id=parsed_args.service_provider,
280
+ ignore_missing=False,
230
281
  )
231
282
 
232
- service_provider._info.pop('links', None)
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 keystoneclient import exceptions as identity_exc
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='impersonate',
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
- trustor_id = common.find_user(
103
- identity_client, parsed_args.trustor, parsed_args.trustor_domain
104
- ).id
105
- trustee_id = common.find_user(
106
- identity_client, parsed_args.trustee, parsed_args.trustee_domain
107
- ).id
108
- project_id = common.find_project(
109
- identity_client, parsed_args.project, parsed_args.project_domain
110
- ).id
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.role:
150
+ for role in parsed_args.roles:
114
151
  try:
115
- role_id = utils.find_resource(
116
- identity_client.roles,
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
- trust = identity_client.trusts.create(
130
- trustee_id,
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
- # Format roles into something sensible
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 zip(*sorted(trust._info.items()))
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 = utils.find_resource(identity_client.trusts, trust)
169
- identity_client.trusts.delete(trust_obj.id)
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
- if auth_ref:
247
- user = common.find_user(identity_client, auth_ref.user_id)
248
- # We need two calls here as we want trusts with
249
- # either the trustor or the trustee set to current user
250
- # using a single call would give us trusts with both
251
- # trustee and trustor set to current user
252
- data1 = identity_client.trusts.list(trustor_user=user)
253
- data2 = identity_client.trusts.list(trustee_user=user)
254
- data = set(data1 + data2)
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
- trustor = common.find_user(
259
- identity_client,
260
- parsed_args.trustor,
261
- parsed_args.trustor_domain,
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
- trustee = common.find_user(
267
- identity_client,
268
- parsed_args.trustor,
269
- parsed_args.trustor_domain,
270
- )
271
-
272
- data = self.app.client_manager.identity.trusts.list(
273
- trustor_user=trustor,
274
- trustee_user=trustee,
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
- columns = (
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
- columns,
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 = utils.find_resource(identity_client.trusts, parsed_args.trust)
314
-
315
- trust._info.pop('roles_links', None)
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 zip(*sorted(trust._info.items()))
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>",