Skip to content

Commit 85c47b7

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Add support for setting volume-type-access"
2 parents 162c985 + be2d2a1 commit 85c47b7

5 files changed

Lines changed: 147 additions & 6 deletions

File tree

doc/source/command-objects/volume-type.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ Set volume type properties
8888
[--name <name>]
8989
[--description <description>]
9090
[--property <key=value> [...] ]
91+
[--project <project>]
92+
[--project-domain <project-domain>]
9193
<volume-type>
9294
9395
.. option:: --name <name>
@@ -102,6 +104,17 @@ Set volume type properties
102104

103105
.. versionadded:: 2
104106

107+
.. option:: --project <project>
108+
109+
Set volume type access to project (name or ID) (admin only)
110+
111+
*Volume version 2 only*
112+
113+
.. option:: --project-domain <project-domain>
114+
115+
Domain the project belongs to (name or ID).
116+
This can be used in case collisions between project names exist.
117+
105118
.. option:: --property <key=value>
106119

107120
Set a property on this volume type (repeat option to set multiple properties)

openstackclient/tests/volume/v2/fakes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ def __init__(self, **kwargs):
243243
self.backups.resource_class = fakes.FakeResource(None, {})
244244
self.volume_types = mock.Mock()
245245
self.volume_types.resource_class = fakes.FakeResource(None, {})
246+
self.volume_type_access = mock.Mock()
247+
self.volume_type_access.resource_class = fakes.FakeResource(None, {})
246248
self.restores = mock.Mock()
247249
self.restores.resource_class = fakes.FakeResource(None, {})
248250
self.qos_specs = mock.Mock()

openstackclient/tests/volume/v2/test_type.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import copy
1616

1717
from openstackclient.tests import fakes
18+
from openstackclient.tests.identity.v3 import fakes as identity_fakes
19+
from openstackclient.tests import utils as tests_utils
1820
from openstackclient.tests.volume.v2 import fakes as volume_fakes
1921
from openstackclient.volume.v2 import volume_type
2022

@@ -41,6 +43,13 @@ def setUp(self):
4143
self.types_mock = self.app.client_manager.volume.volume_types
4244
self.types_mock.reset_mock()
4345

46+
self.types_access_mock = (
47+
self.app.client_manager.volume.volume_type_access)
48+
self.types_access_mock.reset_mock()
49+
50+
self.projects_mock = self.app.client_manager.identity.projects
51+
self.projects_mock.reset_mock()
52+
4453

4554
class TestTypeCreate(TestType):
4655

@@ -211,6 +220,13 @@ def setUp(self):
211220
loaded=True,
212221
)
213222

223+
# Return a project
224+
self.projects_mock.get.return_value = fakes.FakeResource(
225+
None,
226+
copy.deepcopy(identity_fakes.PROJECT),
227+
loaded=True,
228+
)
229+
214230
# Get the command object to test
215231
self.cmd = volume_type.SetVolumeType(self.app, None)
216232

@@ -286,6 +302,56 @@ def test_type_set_property(self):
286302
self.assertIn('myprop', result)
287303
self.assertEqual('myvalue', result['myprop'])
288304

305+
def test_type_set_not_called_without_project_argument(self):
306+
arglist = [
307+
'--project', '',
308+
volume_fakes.type_id,
309+
]
310+
verifylist = [
311+
('project', ''),
312+
('volume_type', volume_fakes.type_id),
313+
]
314+
315+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
316+
317+
result = self.cmd.take_action(parsed_args)
318+
self.assertIsNone(result)
319+
320+
self.assertFalse(self.types_access_mock.add_project_access.called)
321+
322+
def test_type_set_failed_with_missing_volume_type_argument(self):
323+
arglist = [
324+
'--project', 'identity_fakes.project_id',
325+
]
326+
verifylist = [
327+
('project', 'identity_fakes.project_id'),
328+
]
329+
330+
self.assertRaises(tests_utils.ParserException,
331+
self.check_parser,
332+
self.cmd,
333+
arglist,
334+
verifylist)
335+
336+
def test_type_set_project_access(self):
337+
arglist = [
338+
'--project', identity_fakes.project_id,
339+
volume_fakes.type_id,
340+
]
341+
verifylist = [
342+
('project', identity_fakes.project_id),
343+
('volume_type', volume_fakes.type_id),
344+
]
345+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
346+
347+
result = self.cmd.take_action(parsed_args)
348+
self.assertIsNone(result)
349+
350+
self.types_access_mock.add_project_access.assert_called_with(
351+
volume_fakes.type_id,
352+
identity_fakes.project_id,
353+
)
354+
289355

290356
class TestTypeShow(TestType):
291357

openstackclient/volume/v2/volume_type.py

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
import six
1818

1919
from openstackclient.common import command
20+
from openstackclient.common import exceptions
2021
from openstackclient.common import parseractions
2122
from openstackclient.common import utils
23+
from openstackclient.identity import common as identity_common
2224

2325

2426
class CreateVolumeType(command.ShowOne):
@@ -156,33 +158,73 @@ def get_parser(self, prog_name):
156158
help='Set a property on this volume type '
157159
'(repeat option to set multiple properties)',
158160
)
161+
parser.add_argument(
162+
'--project',
163+
metavar='<project>',
164+
help='Set volume type access to project (name or ID) (admin only)',
165+
)
166+
identity_common.add_project_domain_option_to_parser(parser)
167+
159168
return parser
160169

161170
def take_action(self, parsed_args):
162171
volume_client = self.app.client_manager.volume
172+
identity_client = self.app.client_manager.identity
173+
163174
volume_type = utils.find_resource(
164175
volume_client.volume_types, parsed_args.volume_type)
165176

166177
if (not parsed_args.name
167178
and not parsed_args.description
168-
and not parsed_args.property):
179+
and not parsed_args.property
180+
and not parsed_args.project):
169181
self.app.log.error("No changes requested\n")
170182
return
171183

184+
result = 0
172185
kwargs = {}
173186
if parsed_args.name:
174187
kwargs['name'] = parsed_args.name
175188
if parsed_args.description:
176189
kwargs['description'] = parsed_args.description
177190

178191
if kwargs:
179-
volume_client.volume_types.update(
180-
volume_type.id,
181-
**kwargs
182-
)
192+
try:
193+
volume_client.volume_types.update(
194+
volume_type.id,
195+
**kwargs
196+
)
197+
except Exception as e:
198+
self.app.log.error("Failed to update volume type name or"
199+
" description: " + str(e))
200+
result += 1
183201

184202
if parsed_args.property:
185-
volume_type.set_keys(parsed_args.property)
203+
try:
204+
volume_type.set_keys(parsed_args.property)
205+
except Exception as e:
206+
self.app.log.error("Failed to set volume type property: " +
207+
str(e))
208+
result += 1
209+
210+
if parsed_args.project:
211+
project_info = None
212+
try:
213+
project_info = identity_common.find_project(
214+
identity_client,
215+
parsed_args.project,
216+
parsed_args.project_domain)
217+
218+
volume_client.volume_type_access.add_project_access(
219+
volume_type.id, project_info.id)
220+
except Exception as e:
221+
self.app.log.error("Failed to set volume type access to"
222+
" project: " + str(e))
223+
result += 1
224+
225+
if result > 0:
226+
raise exceptions.CommandError("Command Failed: One or more of the"
227+
" operations failed")
186228

187229

188230
class ShowVolumeType(command.ShowOne):
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
features:
3+
- |
4+
Added support for setting volume type access to project.
5+
6+
By default, volumes types are public.
7+
To create a private volume type, user needs to set is_public boolean
8+
field to false at volume type creation time.
9+
To control access to a private volume type, user needs to add access
10+
of a private volume type to project.
11+
12+
So, this feature enables user to add private volume type access to a
13+
project using below command
14+
15+
``volume type set --project <project> <volume_type>``.
16+
17+
[Bug 1554889 'https://bugs.launchpad.net/python-openstackclient/+bug/1554889'_]
18+

0 commit comments

Comments
 (0)