Skip to content

Commit 1cb56a6

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Added capabilities/options to 'openstack flavor list' command to match capabilities already provided by 'nova flavor-list':"
2 parents 0cc3955 + 6d46781 commit 1cb56a6

3 files changed

Lines changed: 344 additions & 6 deletions

File tree

‎doc/source/command-objects/flavor.rst‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ List flavors
8989
.. code:: bash
9090
9191
os flavor list
92+
[--public | --private | --all]
93+
[--long]
94+
95+
.. option:: --public
96+
97+
List only public flavors (default)
98+
99+
.. option:: --private
100+
101+
List only private flavors
102+
103+
.. option:: --all
104+
105+
List all flavors, whether public or private
106+
107+
.. option:: --long
108+
109+
List additional fields in output
92110

93111
flavor show
94112
-----------

‎openstackclient/compute/v2/flavor.py‎

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,36 @@ class ListFlavor(lister.Lister):
152152

153153
log = logging.getLogger(__name__ + ".ListFlavor")
154154

155+
def get_parser(self, prog_name):
156+
parser = super(ListFlavor, self).get_parser(prog_name)
157+
public_group = parser.add_mutually_exclusive_group()
158+
public_group.add_argument(
159+
"--public",
160+
dest="public",
161+
action="store_true",
162+
default=True,
163+
help="List only public flavors (default)",
164+
)
165+
public_group.add_argument(
166+
"--private",
167+
dest="public",
168+
action="store_false",
169+
help="List only private flavors",
170+
)
171+
public_group.add_argument(
172+
"--all",
173+
dest="all",
174+
action="store_true",
175+
default=False,
176+
help="List all flavors, whether public or private",
177+
)
178+
parser.add_argument(
179+
'--long',
180+
action='store_true',
181+
default=False,
182+
help='List additional fields in output')
183+
return parser
184+
155185
def take_action(self, parsed_args):
156186
self.log.debug("take_action(%s)", parsed_args)
157187
compute_client = self.app.client_manager.compute
@@ -161,16 +191,32 @@ def take_action(self, parsed_args):
161191
"RAM",
162192
"Disk",
163193
"Ephemeral",
164-
"Swap",
165194
"VCPUs",
166-
"RXTX Factor",
167195
"Is Public",
168-
"Extra Specs"
169196
)
170-
data = compute_client.flavors.list()
171-
return (columns,
197+
198+
# is_public is ternary - None means give all flavors,
199+
# True is public only and False is private only
200+
# By default Nova assumes True and gives admins public flavors
201+
# and flavors from their own projects only.
202+
is_public = None if parsed_args.all else parsed_args.public
203+
204+
data = compute_client.flavors.list(is_public=is_public)
205+
206+
if parsed_args.long:
207+
columns = columns + (
208+
"Swap",
209+
"RXTX Factor",
210+
"Properties",
211+
)
212+
for f in data:
213+
f.properties = f.get_keys()
214+
215+
column_headers = columns
216+
217+
return (column_headers,
172218
(utils.get_item_properties(
173-
s, columns,
219+
s, columns, formatters={'Properties': utils.format_dict},
174220
) for s in data))
175221

176222

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
# Copyright 2015 Symantec Corporation
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
import copy
17+
18+
from openstackclient.compute.v2 import flavor
19+
from openstackclient.tests.compute.v2 import fakes as compute_fakes
20+
from openstackclient.tests import fakes
21+
22+
23+
class FakeFlavorResource(fakes.FakeResource):
24+
25+
def get_keys(self):
26+
return {'property': 'value'}
27+
28+
29+
class TestFlavor(compute_fakes.TestComputev2):
30+
31+
def setUp(self):
32+
super(TestFlavor, self).setUp()
33+
34+
# Get a shortcut to the FlavorManager Mock
35+
self.flavors_mock = self.app.client_manager.compute.flavors
36+
self.flavors_mock.reset_mock()
37+
38+
39+
class TestFlavorList(TestFlavor):
40+
41+
def setUp(self):
42+
super(TestFlavorList, self).setUp()
43+
44+
self.flavors_mock.list.return_value = [
45+
FakeFlavorResource(
46+
None,
47+
copy.deepcopy(compute_fakes.FLAVOR),
48+
loaded=True,
49+
),
50+
]
51+
52+
# Get the command object to test
53+
self.cmd = flavor.ListFlavor(self.app, None)
54+
55+
def test_flavor_list_no_options(self):
56+
arglist = []
57+
verifylist = [
58+
('public', True),
59+
('all', False),
60+
('long', False),
61+
]
62+
63+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
64+
65+
# DisplayCommandBase.take_action() returns two tuples
66+
columns, data = self.cmd.take_action(parsed_args)
67+
68+
# Set expected values
69+
kwargs = {
70+
'is_public': True
71+
}
72+
73+
self.flavors_mock.list.assert_called_with(
74+
**kwargs
75+
)
76+
77+
collist = (
78+
'ID',
79+
'Name',
80+
'RAM',
81+
'Disk',
82+
'Ephemeral',
83+
'VCPUs',
84+
'Is Public',
85+
)
86+
self.assertEqual(collist, columns)
87+
datalist = ((
88+
compute_fakes.flavor_id,
89+
compute_fakes.flavor_name,
90+
compute_fakes.flavor_ram,
91+
'',
92+
'',
93+
compute_fakes.flavor_vcpus,
94+
''
95+
), )
96+
self.assertEqual(datalist, tuple(data))
97+
98+
def test_flavor_list_all_flavors(self):
99+
arglist = [
100+
'--all',
101+
]
102+
verifylist = [
103+
('all', True),
104+
]
105+
106+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
107+
108+
# DisplayCommandBase.take_action() returns two tuples
109+
columns, data = self.cmd.take_action(parsed_args)
110+
111+
# Set expected values
112+
kwargs = {
113+
'is_public': None
114+
}
115+
116+
self.flavors_mock.list.assert_called_with(
117+
**kwargs
118+
)
119+
120+
collist = (
121+
'ID',
122+
'Name',
123+
'RAM',
124+
'Disk',
125+
'Ephemeral',
126+
'VCPUs',
127+
'Is Public',
128+
)
129+
self.assertEqual(collist, columns)
130+
datalist = ((
131+
compute_fakes.flavor_id,
132+
compute_fakes.flavor_name,
133+
compute_fakes.flavor_ram,
134+
'',
135+
'',
136+
compute_fakes.flavor_vcpus,
137+
''
138+
), )
139+
self.assertEqual(datalist, tuple(data))
140+
141+
def test_flavor_list_private_flavors(self):
142+
arglist = [
143+
'--private',
144+
]
145+
verifylist = [
146+
('public', False),
147+
]
148+
149+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
150+
151+
# DisplayCommandBase.take_action() returns two tuples
152+
columns, data = self.cmd.take_action(parsed_args)
153+
154+
# Set expected values
155+
kwargs = {
156+
'is_public': False
157+
}
158+
159+
self.flavors_mock.list.assert_called_with(
160+
**kwargs
161+
)
162+
163+
collist = (
164+
'ID',
165+
'Name',
166+
'RAM',
167+
'Disk',
168+
'Ephemeral',
169+
'VCPUs',
170+
'Is Public',
171+
)
172+
self.assertEqual(collist, columns)
173+
datalist = ((
174+
compute_fakes.flavor_id,
175+
compute_fakes.flavor_name,
176+
compute_fakes.flavor_ram,
177+
'',
178+
'',
179+
compute_fakes.flavor_vcpus,
180+
''
181+
), )
182+
self.assertEqual(datalist, tuple(data))
183+
184+
def test_flavor_list_public_flavors(self):
185+
arglist = [
186+
'--public',
187+
]
188+
verifylist = [
189+
('public', True),
190+
]
191+
192+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
193+
194+
# DisplayCommandBase.take_action() returns two tuples
195+
columns, data = self.cmd.take_action(parsed_args)
196+
197+
# Set expected values
198+
kwargs = {
199+
'is_public': True
200+
}
201+
202+
self.flavors_mock.list.assert_called_with(
203+
**kwargs
204+
)
205+
206+
collist = (
207+
'ID',
208+
'Name',
209+
'RAM',
210+
'Disk',
211+
'Ephemeral',
212+
'VCPUs',
213+
'Is Public',
214+
)
215+
self.assertEqual(collist, columns)
216+
datalist = ((
217+
compute_fakes.flavor_id,
218+
compute_fakes.flavor_name,
219+
compute_fakes.flavor_ram,
220+
'',
221+
'',
222+
compute_fakes.flavor_vcpus,
223+
''
224+
), )
225+
self.assertEqual(datalist, tuple(data))
226+
227+
def test_flavor_list_long(self):
228+
arglist = [
229+
'--long',
230+
]
231+
verifylist = [
232+
('long', True),
233+
]
234+
235+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
236+
237+
# DisplayCommandBase.take_action() returns two tuples
238+
columns, data = self.cmd.take_action(parsed_args)
239+
240+
# Set expected values
241+
kwargs = {
242+
'is_public': True
243+
}
244+
245+
self.flavors_mock.list.assert_called_with(
246+
**kwargs
247+
)
248+
249+
collist = (
250+
'ID',
251+
'Name',
252+
'RAM',
253+
'Disk',
254+
'Ephemeral',
255+
'VCPUs',
256+
'Is Public',
257+
'Swap',
258+
'RXTX Factor',
259+
'Properties'
260+
)
261+
self.assertEqual(collist, columns)
262+
datalist = ((
263+
compute_fakes.flavor_id,
264+
compute_fakes.flavor_name,
265+
compute_fakes.flavor_ram,
266+
'',
267+
'',
268+
compute_fakes.flavor_vcpus,
269+
'',
270+
'',
271+
'',
272+
'property=\'value\''
273+
), )
274+
self.assertEqual(datalist, tuple(data))

0 commit comments

Comments
 (0)