Skip to content

Commit d0fd1ff

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Switch compute aggregate functions to SDK"
2 parents ba64338 + f36a34b commit d0fd1ff

4 files changed

Lines changed: 313 additions & 212 deletions

File tree

openstackclient/compute/v2/aggregate.py

Lines changed: 136 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import logging
2020

21+
from openstack import utils as sdk_utils
2122
from osc_lib.cli import format_columns
2223
from osc_lib.cli import parseractions
2324
from osc_lib.command import command
@@ -30,6 +31,25 @@
3031
LOG = logging.getLogger(__name__)
3132

3233

34+
_aggregate_formatters = {
35+
'Hosts': format_columns.ListColumn,
36+
'Metadata': format_columns.DictColumn,
37+
'hosts': format_columns.ListColumn,
38+
'metadata': format_columns.DictColumn,
39+
}
40+
41+
42+
def _get_aggregate_columns(item):
43+
# To maintain backwards compatibility we need to rename sdk props to
44+
# whatever OSC was using before
45+
column_map = {
46+
'metadata': 'properties',
47+
}
48+
hidden_columns = ['links', 'location']
49+
return utils.get_osc_show_columns_for_sdk_resource(
50+
item, column_map, hidden_columns)
51+
52+
3353
class AddAggregateHost(command.ShowOne):
3454
_description = _("Add host to aggregate")
3555

@@ -48,26 +68,18 @@ def get_parser(self, prog_name):
4868
return parser
4969

5070
def take_action(self, parsed_args):
51-
compute_client = self.app.client_manager.compute
71+
compute_client = self.app.client_manager.sdk_connection.compute
5272

53-
aggregate = utils.find_resource(
54-
compute_client.aggregates,
55-
parsed_args.aggregate,
56-
)
57-
data = compute_client.aggregates.add_host(aggregate, parsed_args.host)
58-
59-
info = {}
60-
info.update(data._info)
61-
62-
# Special mapping for columns to make the output easier to read:
63-
# 'metadata' --> 'properties'
64-
info.update(
65-
{
66-
'hosts': format_columns.ListColumn(info.pop('hosts')),
67-
'properties': format_columns.DictColumn(info.pop('metadata')),
68-
},
69-
)
70-
return zip(*sorted(info.items()))
73+
aggregate = compute_client.find_aggregate(
74+
parsed_args.aggregate, ignore_missing=False)
75+
76+
aggregate = compute_client.add_host_to_aggregate(
77+
aggregate.id, parsed_args.host)
78+
79+
display_columns, columns = _get_aggregate_columns(aggregate)
80+
data = utils.get_item_properties(
81+
aggregate, columns, formatters=_aggregate_formatters)
82+
return (display_columns, data)
7183

7284

7385
class CreateAggregate(command.ShowOne):
@@ -95,36 +107,25 @@ def get_parser(self, prog_name):
95107
return parser
96108

97109
def take_action(self, parsed_args):
98-
compute_client = self.app.client_manager.compute
110+
compute_client = self.app.client_manager.sdk_connection.compute
99111

100-
info = {}
101-
data = compute_client.aggregates.create(
102-
parsed_args.name,
103-
parsed_args.zone,
104-
)
105-
info.update(data._info)
112+
attrs = {'name': parsed_args.name}
113+
114+
if parsed_args.zone:
115+
attrs['availability_zone'] = parsed_args.zone
116+
117+
aggregate = compute_client.create_aggregate(**attrs)
106118

107119
if parsed_args.property:
108-
info.update(compute_client.aggregates.set_metadata(
109-
data,
120+
aggregate = compute_client.set_aggregate_metadata(
121+
aggregate.id,
110122
parsed_args.property,
111-
)._info)
112-
113-
# Special mapping for columns to make the output easier to read:
114-
# 'metadata' --> 'properties'
115-
hosts = None
116-
properties = None
117-
if 'hosts' in info.keys():
118-
hosts = format_columns.ListColumn(info.pop('hosts'))
119-
if 'metadata' in info.keys():
120-
properties = format_columns.DictColumn(info.pop('metadata'))
121-
info.update(
122-
{
123-
'hosts': hosts,
124-
'properties': properties,
125-
},
126-
)
127-
return zip(*sorted(info.items()))
123+
)
124+
125+
display_columns, columns = _get_aggregate_columns(aggregate)
126+
data = utils.get_item_properties(
127+
aggregate, columns, formatters=_aggregate_formatters)
128+
return (display_columns, data)
128129

129130

130131
class DeleteAggregate(command.Command):
@@ -141,13 +142,14 @@ def get_parser(self, prog_name):
141142
return parser
142143

143144
def take_action(self, parsed_args):
144-
compute_client = self.app.client_manager.compute
145+
compute_client = self.app.client_manager.sdk_connection.compute
145146
result = 0
146147
for a in parsed_args.aggregate:
147148
try:
148-
data = utils.find_resource(
149-
compute_client.aggregates, a)
150-
compute_client.aggregates.delete(data.id)
149+
aggregate = compute_client.find_aggregate(
150+
a, ignore_missing=False)
151+
compute_client.delete_aggregate(
152+
aggregate.id, ignore_missing=False)
151153
except Exception as e:
152154
result += 1
153155
LOG.error(_("Failed to delete aggregate with name or "
@@ -175,15 +177,15 @@ def get_parser(self, prog_name):
175177
return parser
176178

177179
def take_action(self, parsed_args):
178-
compute_client = self.app.client_manager.compute
180+
compute_client = self.app.client_manager.sdk_connection.compute
179181

180-
data = compute_client.aggregates.list()
182+
aggregates = list(compute_client.aggregates())
181183

182184
if parsed_args.long:
183185
# Remove availability_zone from metadata because Nova doesn't
184-
for d in data:
185-
if 'availability_zone' in d.metadata:
186-
d.metadata.pop('availability_zone')
186+
for aggregate in aggregates:
187+
if 'availability_zone' in aggregate.metadata:
188+
aggregate.metadata.pop('availability_zone')
187189
# This is the easiest way to change column headers
188190
column_headers = (
189191
"ID",
@@ -204,14 +206,11 @@ def take_action(self, parsed_args):
204206
"Availability Zone",
205207
)
206208

207-
return (column_headers,
208-
(utils.get_item_properties(
209-
s, columns,
210-
formatters={
211-
'Hosts': format_columns.ListColumn,
212-
'Metadata': format_columns.DictColumn,
213-
},
214-
) for s in data))
209+
data = (
210+
utils.get_item_properties(
211+
s, columns, formatters=_aggregate_formatters
212+
) for s in aggregates)
213+
return (column_headers, data)
215214

216215

217216
class RemoveAggregateHost(command.ShowOne):
@@ -232,29 +231,18 @@ def get_parser(self, prog_name):
232231
return parser
233232

234233
def take_action(self, parsed_args):
235-
compute_client = self.app.client_manager.compute
234+
compute_client = self.app.client_manager.sdk_connection.compute
236235

237-
aggregate = utils.find_resource(
238-
compute_client.aggregates,
239-
parsed_args.aggregate,
240-
)
241-
data = compute_client.aggregates.remove_host(
242-
aggregate,
243-
parsed_args.host,
244-
)
236+
aggregate = compute_client.find_aggregate(
237+
parsed_args.aggregate, ignore_missing=False)
245238

246-
info = {}
247-
info.update(data._info)
239+
aggregate = compute_client.remove_host_from_aggregate(
240+
aggregate.id, parsed_args.host)
248241

249-
# Special mapping for columns to make the output easier to read:
250-
# 'metadata' --> 'properties'
251-
info.update(
252-
{
253-
'hosts': format_columns.ListColumn(info.pop('hosts')),
254-
'properties': format_columns.DictColumn(info.pop('metadata')),
255-
},
256-
)
257-
return zip(*sorted(info.items()))
242+
display_columns, columns = _get_aggregate_columns(aggregate)
243+
data = utils.get_item_properties(
244+
aggregate, columns, formatters=_aggregate_formatters)
245+
return (display_columns, data)
258246

259247

260248
class SetAggregate(command.Command):
@@ -296,39 +284,31 @@ def get_parser(self, prog_name):
296284

297285
def take_action(self, parsed_args):
298286

299-
compute_client = self.app.client_manager.compute
300-
aggregate = utils.find_resource(
301-
compute_client.aggregates,
302-
parsed_args.aggregate,
303-
)
287+
compute_client = self.app.client_manager.sdk_connection.compute
288+
aggregate = compute_client.find_aggregate(
289+
parsed_args.aggregate, ignore_missing=False)
304290

305291
kwargs = {}
306292
if parsed_args.name:
307293
kwargs['name'] = parsed_args.name
308294
if parsed_args.zone:
309295
kwargs['availability_zone'] = parsed_args.zone
310296
if kwargs:
311-
compute_client.aggregates.update(
312-
aggregate,
313-
kwargs
314-
)
297+
compute_client.update_aggregate(aggregate.id, **kwargs)
315298

316299
set_property = {}
317300
if parsed_args.no_property:
318-
# NOTE(RuiChen): "availability_zone" is removed from response of
319-
# aggregate show and create commands, don't see it
320-
# anywhere, so pop it, avoid the unexpected server
321-
# exception(can't unset the availability zone from
322-
# aggregate metadata in nova).
301+
# NOTE(RuiChen): "availability_zone" can not be unset from
302+
# properties. It is already excluded from show and create output.
323303
set_property.update({key: None
324304
for key in aggregate.metadata.keys()
325305
if key != 'availability_zone'})
326306
if parsed_args.property:
327307
set_property.update(parsed_args.property)
328308

329309
if set_property:
330-
compute_client.aggregates.set_metadata(
331-
aggregate,
310+
compute_client.set_aggregate_metadata(
311+
aggregate.id,
332312
set_property
333313
)
334314

@@ -347,31 +327,18 @@ def get_parser(self, prog_name):
347327

348328
def take_action(self, parsed_args):
349329

350-
compute_client = self.app.client_manager.compute
351-
data = utils.find_resource(
352-
compute_client.aggregates,
353-
parsed_args.aggregate,
354-
)
330+
compute_client = self.app.client_manager.sdk_connection.compute
331+
aggregate = compute_client.find_aggregate(
332+
parsed_args.aggregate, ignore_missing=False)
333+
355334
# Remove availability_zone from metadata because Nova doesn't
356-
if 'availability_zone' in data.metadata:
357-
data.metadata.pop('availability_zone')
358-
359-
# Special mapping for columns to make the output easier to read:
360-
# 'metadata' --> 'properties'
361-
data._info.update(
362-
{
363-
'hosts': format_columns.ListColumn(
364-
data._info.pop('hosts')
365-
),
366-
'properties': format_columns.DictColumn(
367-
data._info.pop('metadata')
368-
),
369-
},
370-
)
335+
if 'availability_zone' in aggregate.metadata:
336+
aggregate.metadata.pop('availability_zone')
371337

372-
info = {}
373-
info.update(data._info)
374-
return zip(*sorted(info.items()))
338+
display_columns, columns = _get_aggregate_columns(aggregate)
339+
data = utils.get_item_properties(
340+
aggregate, columns, formatters=_aggregate_formatters)
341+
return (display_columns, data)
375342

376343

377344
class UnsetAggregate(command.Command):
@@ -394,14 +361,56 @@ def get_parser(self, prog_name):
394361
return parser
395362

396363
def take_action(self, parsed_args):
397-
compute_client = self.app.client_manager.compute
398-
aggregate = utils.find_resource(
399-
compute_client.aggregates,
400-
parsed_args.aggregate)
364+
compute_client = self.app.client_manager.sdk_connection.compute
365+
aggregate = compute_client.find_aggregate(
366+
parsed_args.aggregate, ignore_missing=False)
401367

402368
unset_property = {}
403369
if parsed_args.property:
404370
unset_property.update({key: None for key in parsed_args.property})
405371
if unset_property:
406-
compute_client.aggregates.set_metadata(aggregate,
407-
unset_property)
372+
compute_client.set_aggregate_metadata(
373+
aggregate, unset_property)
374+
375+
376+
class CacheImageForAggregate(command.Command):
377+
_description = _("Request image caching for aggregate")
378+
# NOTE(gtema): According to stephenfin and dansmith there is no and will
379+
# not be anything to return.
380+
381+
def get_parser(self, prog_name):
382+
parser = super(CacheImageForAggregate, self).get_parser(prog_name)
383+
parser.add_argument(
384+
'aggregate',
385+
metavar='<aggregate>',
386+
help=_("Aggregate (name or ID)")
387+
)
388+
parser.add_argument(
389+
'image',
390+
metavar='<image>',
391+
nargs='+',
392+
help=_("Image ID to request caching for aggregate (name or ID). "
393+
"May be specified multiple times.")
394+
)
395+
return parser
396+
397+
def take_action(self, parsed_args):
398+
compute_client = self.app.client_manager.sdk_connection.compute
399+
400+
if not sdk_utils.supports_microversion(compute_client, '2.81'):
401+
msg = _(
402+
'This operation requires server support for '
403+
'API microversion 2.81'
404+
)
405+
raise exceptions.CommandError(msg)
406+
407+
aggregate = compute_client.find_aggregate(
408+
parsed_args.aggregate, ignore_missing=False)
409+
410+
images = []
411+
for img in parsed_args.image:
412+
image = self.app.client_manager.sdk_connection.image.find_image(
413+
img, ignore_missing=False)
414+
images.append(image.id)
415+
416+
compute_client.aggregate_precache_images(aggregate.id, images)

0 commit comments

Comments
 (0)