@@ -2204,15 +2204,19 @@ def take_action(self, parsed_args):
22042204 # flavor name is given, map it to ID.
22052205 flavor_id = None
22062206 if parsed_args .flavor :
2207- flavor_id = utils .find_resource (compute_client .flavors ,
2208- parsed_args .flavor ).id
2207+ flavor_id = utils .find_resource (
2208+ compute_client .flavors ,
2209+ parsed_args .flavor ,
2210+ ).id
22092211
22102212 # Nova only supports list servers searching by image ID. So if a
22112213 # image name is given, map it to ID.
22122214 image_id = None
22132215 if parsed_args .image :
2214- image_id = image_client .find_image (parsed_args .image ,
2215- ignore_missing = False ).id
2216+ image_id = image_client .find_image (
2217+ parsed_args .image ,
2218+ ignore_missing = False ,
2219+ ).id
22162220
22172221 search_opts = {
22182222 'reservation_id' : parsed_args .reservation_id ,
@@ -2320,95 +2324,93 @@ def take_action(self, parsed_args):
23202324 try :
23212325 iso8601 .parse_date (search_opts ['changes-since' ])
23222326 except (TypeError , iso8601 .ParseError ):
2327+ msg = _ ('Invalid changes-since value: %s' )
23232328 raise exceptions .CommandError (
2324- _ ('Invalid changes-since value: %s' ) %
2325- search_opts ['changes-since' ]
2329+ msg % search_opts ['changes-since' ]
23262330 )
23272331
2332+ columns = (
2333+ 'id' ,
2334+ 'name' ,
2335+ 'status' ,
2336+ )
2337+ column_headers = (
2338+ 'ID' ,
2339+ 'Name' ,
2340+ 'Status' ,
2341+ )
2342+
23282343 if parsed_args .long :
2329- columns = (
2330- 'ID' ,
2331- 'Name' ,
2332- 'Status' ,
2344+ columns += (
23332345 'OS-EXT-STS:task_state' ,
23342346 'OS-EXT-STS:power_state' ,
2335- 'Networks' ,
2336- 'Image Name' ,
2337- 'Image ID' ,
2338- 'Flavor Name' ,
2339- 'Flavor ID' ,
2340- 'OS-EXT-AZ:availability_zone' ,
2341- 'OS-EXT-SRV-ATTR:host' ,
2342- 'Metadata' ,
23432347 )
2344- column_headers = (
2345- 'ID' ,
2346- 'Name' ,
2347- 'Status' ,
2348+ column_headers += (
23482349 'Task State' ,
23492350 'Power State' ,
2350- 'Networks' ,
2351+ )
2352+
2353+ columns += ('networks' ,)
2354+ column_headers += ('Networks' ,)
2355+
2356+ if parsed_args .long :
2357+ columns += (
2358+ 'image_name' ,
2359+ 'image_id' ,
2360+ )
2361+ column_headers += (
23512362 'Image Name' ,
23522363 'Image ID' ,
2364+ )
2365+ else :
2366+ if parsed_args .no_name_lookup :
2367+ columns += ('image_id' ,)
2368+ else :
2369+ columns += ('image_name' ,)
2370+ column_headers += ('Image' ,)
2371+
2372+ if parsed_args .long :
2373+ columns += (
2374+ 'flavor_name' ,
2375+ 'flavor_id' ,
2376+ )
2377+ column_headers += (
23532378 'Flavor Name' ,
23542379 'Flavor ID' ,
2355- 'Availability Zone' ,
2356- 'Host' ,
2357- 'Properties' ,
23582380 )
2359- mixed_case_fields = [
2360- 'OS-EXT-STS:task_state' ,
2361- 'OS-EXT-STS:power_state' ,
2362- 'OS-EXT-AZ:availability_zone' ,
2363- 'OS-EXT-SRV-ATTR:host' ,
2364- ]
23652381 else :
23662382 if parsed_args .no_name_lookup :
2367- columns = (
2368- 'ID' ,
2369- 'Name' ,
2370- 'Status' ,
2371- 'Networks' ,
2372- 'Image ID' ,
2373- 'Flavor ID' ,
2374- )
2383+ columns += ('flavor_id' ,)
23752384 else :
2376- columns = (
2377- 'ID' ,
2378- 'Name' ,
2379- 'Status' ,
2380- 'Networks' ,
2381- 'Image Name' ,
2382- 'Flavor Name' ,
2383- )
2384- column_headers = (
2385- 'ID' ,
2386- 'Name' ,
2387- 'Status' ,
2388- 'Networks' ,
2389- 'Image' ,
2390- 'Flavor' ,
2385+ columns += ('flavor_name' ,)
2386+ column_headers += ('Flavor' ,)
2387+
2388+ if parsed_args .long :
2389+ columns += (
2390+ 'OS-EXT-AZ:availability_zone' ,
2391+ 'OS-EXT-SRV-ATTR:host' ,
2392+ 'metadata' ,
2393+ )
2394+ column_headers += (
2395+ 'Availability Zone' ,
2396+ 'Host' ,
2397+ 'Properties' ,
23912398 )
2392- mixed_case_fields = []
23932399
23942400 marker_id = None
23952401
23962402 # support for additional columns
23972403 if parsed_args .columns :
2398- # convert tuple to list to edit them
2399- column_headers = list (column_headers )
2400- columns = list (columns )
2401-
24022404 for c in parsed_args .columns :
24032405 if c in ('Project ID' , 'project_id' ):
2404- columns . append ('tenant_id' )
2405- column_headers . append ('Project ID' )
2406+ columns += ('tenant_id' , )
2407+ column_headers += ('Project ID' , )
24062408 if c in ('User ID' , 'user_id' ):
2407- columns . append ('user_id' )
2408- column_headers . append ('User ID' )
2409+ columns += ('user_id' , )
2410+ column_headers += ('User ID' , )
24092411 if c in ('Created At' , 'created_at' ):
2410- columns . append ('created' )
2411- column_headers . append ('Created At' )
2412+ columns += ('created' , )
2413+ column_headers += ('Created At' , )
24122414
24132415 # convert back to tuple
24142416 column_headers = tuple (column_headers )
@@ -2422,25 +2424,29 @@ def take_action(self, parsed_args):
24222424 if parsed_args .deleted :
24232425 marker_id = parsed_args .marker
24242426 else :
2425- marker_id = utils .find_resource (compute_client .servers ,
2426- parsed_args .marker ).id
2427+ marker_id = utils .find_resource (
2428+ compute_client .servers ,
2429+ parsed_args .marker ,
2430+ ).id
24272431
2428- data = compute_client .servers .list (search_opts = search_opts ,
2429- marker = marker_id ,
2430- limit = parsed_args .limit )
2432+ data = compute_client .servers .list (
2433+ search_opts = search_opts ,
2434+ marker = marker_id ,
2435+ limit = parsed_args .limit )
24312436
24322437 images = {}
24332438 flavors = {}
24342439 if data and not parsed_args .no_name_lookup :
2435- # Create a dict that maps image_id to image object.
2436- # Needed so that we can display the "Image Name" column.
2437- # "Image Name" is not crucial, so we swallow any exceptions.
2438- # The 'image' attribute can be an empty string if the server was
2439- # booted from a volume.
2440+ # create a dict that maps image_id to image object, which is used
2441+ # to display the "Image Name" column. Note that 'image.id' can be
2442+ # empty for BFV instances and 'image' can be missing entirely if
2443+ # there are infra failures
24402444 if parsed_args .name_lookup_one_by_one or image_id :
2441- for i_id in set (filter (lambda x : x is not None ,
2442- (s .image .get ('id' ) for s in data
2443- if s .image ))):
2445+ for i_id in set (
2446+ s .image ['id' ] for s in data
2447+ if s .image and s .image .get ('id' )
2448+ ):
2449+ # "Image Name" is not crucial, so we swallow any exceptions
24442450 try :
24452451 images [i_id ] = image_client .get_image (i_id )
24462452 except Exception :
@@ -2453,12 +2459,17 @@ def take_action(self, parsed_args):
24532459 except Exception :
24542460 pass
24552461
2456- # Create a dict that maps flavor_id to flavor object.
2457- # Needed so that we can display the "Flavor Name" column.
2458- # "Flavor Name" is not crucial, so we swallow any exceptions.
2462+ # create a dict that maps flavor_id to flavor object, which is used
2463+ # to display the "Flavor Name" column. Note that 'flavor.id' is not
2464+ # present on microversion 2.47 or later and 'flavor' won't be
2465+ # present if there are infra failures
24592466 if parsed_args .name_lookup_one_by_one or flavor_id :
2460- for f_id in set (filter (lambda x : x is not None ,
2461- (s .flavor .get ('id' ) for s in data ))):
2467+ for f_id in set (
2468+ s .flavor ['id' ] for s in data
2469+ if s .flavor and s .flavor .get ('id' )
2470+ ):
2471+ # "Flavor Name" is not crucial, so we swallow any
2472+ # exceptions
24622473 try :
24632474 flavors [f_id ] = compute_client .flavors .get (f_id )
24642475 except Exception :
@@ -2482,6 +2493,7 @@ def take_action(self, parsed_args):
24822493 # processing of the image and flavor informations.
24832494 if not hasattr (s , 'image' ) or not hasattr (s , 'flavor' ):
24842495 continue
2496+
24852497 if 'id' in s .image :
24862498 image = images .get (s .image ['id' ])
24872499 if image :
@@ -2494,6 +2506,7 @@ def take_action(self, parsed_args):
24942506 # able to grep for boot-from-volume servers when using the CLI.
24952507 s .image_name = IMAGE_STRING_FOR_BFV
24962508 s .image_id = IMAGE_STRING_FOR_BFV
2509+
24972510 if 'id' in s .flavor :
24982511 flavor = flavors .get (s .flavor ['id' ])
24992512 if flavor :
@@ -2512,11 +2525,16 @@ def take_action(self, parsed_args):
25122525 (
25132526 utils .get_item_properties (
25142527 s , columns ,
2515- mixed_case_fields = mixed_case_fields ,
2528+ mixed_case_fields = (
2529+ 'OS-EXT-STS:task_state' ,
2530+ 'OS-EXT-STS:power_state' ,
2531+ 'OS-EXT-AZ:availability_zone' ,
2532+ 'OS-EXT-SRV-ATTR:host' ,
2533+ ),
25162534 formatters = {
25172535 'OS-EXT-STS:power_state' : PowerStateColumn ,
2518- 'Networks ' : format_columns .DictListColumn ,
2519- 'Metadata ' : format_columns .DictColumn ,
2536+ 'networks ' : format_columns .DictListColumn ,
2537+ 'metadata ' : format_columns .DictColumn ,
25202538 },
25212539 ) for s in data
25222540 ),
0 commit comments