1- # Copyright 2012-2013 OpenStack, LLC.
1+ # Copyright 2012-2013 OpenStack Foundation
22#
33# Licensed under the Apache License, Version 2.0 (the "License"); you may
44# not use this file except in compliance with the License. You may obtain
1313# under the License.
1414#
1515
16- """Server action implementations"""
16+ """Compute v2 Server action implementations"""
1717
1818import logging
1919import os
2525
2626from novaclient .v1_1 import servers
2727from openstackclient .common import exceptions
28+ from openstackclient .common import parseractions
2829from openstackclient .common import utils
2930
3031
31- def _format_servers_list_networks (server ):
32- """Return a string containing the networks a server is attached to.
32+ def _format_servers_list_networks (networks ):
33+ """Return a formatted string of a server's networks
3334
34- :param server: a single Server resource
35+ :param server: a Server.networks field
3536 :rtype: a string of formatted network addresses
3637 """
3738 output = []
38- for (network , addresses ) in server . networks .items ():
39+ for (network , addresses ) in networks .items ():
3940 if not addresses :
4041 continue
4142 addresses_csv = ', ' .join (addresses )
@@ -73,7 +74,12 @@ def _prep_server_detail(compute_client, server):
7374
7475 # NOTE(dtroyer): novaclient splits these into separate entries...
7576 # Format addresses in a useful way
76- info ['addresses' ] = _format_servers_list_networks (server )
77+ info ['addresses' ] = _format_servers_list_networks (server .networks )
78+
79+ # Map 'metadata' field to 'properties'
80+ info .update (
81+ {'properties' : utils .format_dict (info .pop ('metadata' ))}
82+ )
7783
7884 # Remove values that are long and not too useful
7985 info .pop ('links' , None )
@@ -116,7 +122,7 @@ def _wait_for_status(poll_fn, obj_id, final_ok_states, poll_period=5,
116122
117123
118124class CreateServer (show .ShowOne ):
119- """Create server command """
125+ """Create a new server """
120126
121127 log = logging .getLogger (__name__ + '.CreateServer' )
122128
@@ -150,9 +156,8 @@ def get_parser(self, prog_name):
150156 parser .add_argument (
151157 '--property' ,
152158 metavar = '<key=value>' ,
153- action = 'append' ,
154- default = [],
155- help = 'Property to store for this server '
159+ action = parseractions .KeyValueAction ,
160+ help = 'Set a property on this server '
156161 '(repeat for multiple values)' )
157162 parser .add_argument (
158163 '--file' ,
@@ -228,8 +233,6 @@ def take_action(self, parsed_args):
228233
229234 boot_args = [parsed_args .server_name , image , flavor ]
230235
231- meta = dict (v .split ('=' , 1 ) for v in parsed_args .property )
232-
233236 files = {}
234237 for f in parsed_args .file :
235238 dst , src = f .split ('=' , 1 )
@@ -288,7 +291,7 @@ def take_action(self, parsed_args):
288291 config_drive = parsed_args .config_drive
289292
290293 boot_kwargs = dict (
291- meta = meta ,
294+ meta = parsed_args . property ,
292295 files = files ,
293296 reservation_id = None ,
294297 min_count = parsed_args .min ,
@@ -337,7 +340,7 @@ def take_action(self, parsed_args):
337340
338341
339342class ListServer (lister .Lister ):
340- """List server command """
343+ """List servers """
341344
342345 log = logging .getLogger (__name__ + '.ListServer' )
343346
@@ -385,6 +388,11 @@ def get_parser(self, prog_name):
385388 action = 'store_true' ,
386389 default = bool (int (os .environ .get ("ALL_TENANTS" , 0 ))),
387390 help = 'display information from all tenants (admin only)' )
391+ parser .add_argument (
392+ '--long' ,
393+ action = 'store_true' ,
394+ default = False ,
395+ help = 'Additional fields are listed in output' )
388396 return parser
389397
390398 def take_action (self , parsed_args ):
@@ -403,13 +411,43 @@ def take_action(self, parsed_args):
403411 'all_tenants' : parsed_args .all_tenants ,
404412 }
405413 self .log .debug ('search options: %s' , search_opts )
406- # FIXME(dhellmann): Consider adding other columns
407- columns = ('ID' , 'Name' , 'Status' , 'Networks' )
414+
415+ if parsed_args .long :
416+ columns = (
417+ 'ID' ,
418+ 'Name' ,
419+ 'Status' ,
420+ 'Networks' ,
421+ 'OS-EXT-AZ:availability_zone' ,
422+ 'OS-EXT-SRV-ATTR:host' ,
423+ 'Metadata' ,
424+ )
425+ column_headers = (
426+ 'ID' ,
427+ 'Name' ,
428+ 'Status' ,
429+ 'Networks' ,
430+ 'Availability Zone' ,
431+ 'Host' ,
432+ 'Properties' ,
433+ )
434+ mixed_case_fields = [
435+ 'OS-EXT-AZ:availability_zone' ,
436+ 'OS-EXT-SRV-ATTR:host' ,
437+ ]
438+ else :
439+ columns = ('ID' , 'Name' , 'Status' , 'Networks' )
440+ column_headers = columns
441+ mixed_case_fields = []
408442 data = compute_client .servers .list (search_opts = search_opts )
409- return (columns ,
443+ return (column_headers ,
410444 (utils .get_item_properties (
411445 s , columns ,
412- formatters = {'Networks' : _format_servers_list_networks },
446+ mixed_case_fields = mixed_case_fields ,
447+ formatters = {
448+ 'Networks' : _format_servers_list_networks ,
449+ 'Metadata' : utils .format_dict ,
450+ },
413451 ) for s in data ))
414452
415453
0 commit comments