@@ -77,6 +77,10 @@ def human_readable(self):
7777 except Exception :
7878 return 'N/A'
7979
80+ def machine_readable (self ):
81+ return {k : [i ['addr' ] for i in v if 'addr' in i ]
82+ for k , v in self ._value .items ()}
83+
8084
8185class HostColumn (cliff_columns .FormattableColumn ):
8286 """Generate a formatted string of a hostname."""
@@ -133,14 +137,61 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
133137 the latest details of a server after creating it.
134138 :rtype: a dict of server details
135139 """
140+ # Note: Some callers of this routine pass a novaclient server, and others
141+ # pass an SDK server. Column names may be different across those cases.
136142 info = server .to_dict ()
137143 if refresh :
138144 server = utils .find_resource (compute_client .servers , info ['id' ])
139145 info .update (server .to_dict ())
140146
147+ # Some commands using this routine were originally implemented with the
148+ # nova python wrappers, and were later migrated to use the SDK. Map the
149+ # SDK's property names to the original property names to maintain backward
150+ # compatibility for existing users. Data is duplicated under both the old
151+ # and new name so users can consume the data by either name.
152+ column_map = {
153+ 'access_ipv4' : 'accessIPv4' ,
154+ 'access_ipv6' : 'accessIPv6' ,
155+ 'admin_password' : 'adminPass' ,
156+ 'admin_password' : 'adminPass' ,
157+ 'volumes' : 'os-extended-volumes:volumes_attached' ,
158+ 'availability_zone' : 'OS-EXT-AZ:availability_zone' ,
159+ 'block_device_mapping' : 'block_device_mapping_v2' ,
160+ 'compute_host' : 'OS-EXT-SRV-ATTR:host' ,
161+ 'created_at' : 'created' ,
162+ 'disk_config' : 'OS-DCF:diskConfig' ,
163+ 'flavor_id' : 'flavorRef' ,
164+ 'has_config_drive' : 'config_drive' ,
165+ 'host_id' : 'hostId' ,
166+ 'fault' : 'fault' ,
167+ 'hostname' : 'OS-EXT-SRV-ATTR:hostname' ,
168+ 'hypervisor_hostname' : 'OS-EXT-SRV-ATTR:hypervisor_hostname' ,
169+ 'image_id' : 'imageRef' ,
170+ 'instance_name' : 'OS-EXT-SRV-ATTR:instance_name' ,
171+ 'is_locked' : 'locked' ,
172+ 'kernel_id' : 'OS-EXT-SRV-ATTR:kernel_id' ,
173+ 'launch_index' : 'OS-EXT-SRV-ATTR:launch_index' ,
174+ 'launched_at' : 'OS-SRV-USG:launched_at' ,
175+ 'power_state' : 'OS-EXT-STS:power_state' ,
176+ 'project_id' : 'tenant_id' ,
177+ 'ramdisk_id' : 'OS-EXT-SRV-ATTR:ramdisk_id' ,
178+ 'reservation_id' : 'OS-EXT-SRV-ATTR:reservation_id' ,
179+ 'root_device_name' : 'OS-EXT-SRV-ATTR:root_device_name' ,
180+ 'scheduler_hints' : 'OS-SCH-HNT:scheduler_hints' ,
181+ 'task_state' : 'OS-EXT-STS:task_state' ,
182+ 'terminated_at' : 'OS-SRV-USG:terminated_at' ,
183+ 'updated_at' : 'updated' ,
184+ 'user_data' : 'OS-EXT-SRV-ATTR:user_data' ,
185+ 'vm_state' : 'OS-EXT-STS:vm_state' ,
186+ }
187+
188+ info .update ({
189+ column_map [column ]: data for column , data in info .items ()
190+ if column in column_map })
191+
141192 # Convert the image blob to a name
142193 image_info = info .get ('image' , {})
143- if image_info :
194+ if image_info and any ( image_info . values ()) :
144195 image_id = image_info .get ('id' , '' )
145196 try :
146197 image = image_client .get_image (image_id )
@@ -188,7 +239,9 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
188239
189240 # NOTE(dtroyer): novaclient splits these into separate entries...
190241 # Format addresses in a useful way
191- info ['addresses' ] = format_columns .DictListColumn (server .networks )
242+ info ['addresses' ] = (
243+ AddressesColumn (info ['addresses' ]) if 'addresses' in info
244+ else format_columns .DictListColumn (info .get ('networks' )))
192245
193246 # Map 'metadata' field to 'properties'
194247 info ['properties' ] = format_columns .DictColumn (info .pop ('metadata' ))
@@ -4319,32 +4372,34 @@ def get_parser(self, prog_name):
43194372 return parser
43204373
43214374 def take_action (self , parsed_args ):
4322- compute_client = self .app .client_manager .compute
4323- server = utils .find_resource (
4324- compute_client .servers , parsed_args .server )
4375+ compute_client = self .app .client_manager .sdk_connection .compute
4376+
4377+ # Find by name or ID, then get the full details of the server
4378+ server = compute_client .find_server (
4379+ parsed_args .server , ignore_missing = False )
4380+ server = compute_client .get_server (server )
43254381
43264382 if parsed_args .diagnostics :
4327- (resp , data ) = server .diagnostics ()
4328- if not resp .status_code == 200 :
4329- self .app .stderr .write (_ (
4330- "Error retrieving diagnostics data\n "
4331- ))
4332- return ({}, {})
4383+ data = compute_client .get_server_diagnostics (server )
43334384 return zip (* sorted (data .items ()))
43344385
43354386 topology = None
43364387 if parsed_args .topology :
4337- if compute_client . api_version < api_versions . APIVersion ( '2.78' ):
4388+ if not sdk_utils . supports_microversion ( compute_client , '2.78' ):
43384389 msg = _ (
43394390 '--os-compute-api-version 2.78 or greater is required to '
43404391 'support the --topology option'
43414392 )
43424393 raise exceptions .CommandError (msg )
43434394
4344- topology = server .topology ( )
4395+ topology = server .fetch_topology ( compute_client )
43454396
43464397 data = _prep_server_detail (
4347- compute_client , self .app .client_manager .image , server ,
4398+ # TODO(dannosliwcd): Replace these clients with SDK clients after
4399+ # all callers of _prep_server_detail() are using the SDK.
4400+ self .app .client_manager .compute ,
4401+ self .app .client_manager .image ,
4402+ server ,
43484403 refresh = False )
43494404
43504405 if topology :
0 commit comments