1
1
#!/usr/bin/env python3
2
2
3
3
import argparse
4
- from collections import OrderedDict , namedtuple
4
+ import click
5
5
import json
6
6
import os
7
7
import sys
8
+ import utilities_common .multi_asic as multi_asic_util
8
9
9
- from utilities_common import constants
10
- from utilities_common .cli import json_serial , UserCache
11
- from utilities_common .netstat import format_number_with_comma , table_as_json , ns_diff , format_prate
10
+ from collections import OrderedDict , namedtuple
11
+ from datetime import datetime , timezone , timedelta
12
12
from natsort import natsorted
13
- from tabulate import tabulate
14
13
from sonic_py_common import multi_asic
15
14
from swsscommon .swsscommon import APP_FABRIC_PORT_TABLE_NAME , COUNTERS_TABLE , COUNTERS_FABRIC_PORT_NAME_MAP , COUNTERS_FABRIC_QUEUE_NAME_MAP
16
- import utilities_common .multi_asic as multi_asic_util
15
+ from tabulate import tabulate
16
+ from utilities_common import constants
17
+ from utilities_common .cli import json_serial , UserCache
18
+ from utilities_common .netstat import format_number_with_comma , table_as_json , ns_diff , format_prate
17
19
18
20
# mock the redis for unit test purposes #
19
21
try :
@@ -280,6 +282,62 @@ class FabricQueueStat(FabricStat):
280
282
print (tabulate (table , queuestat_header , tablefmt = 'simple' , stralign = 'right' ))
281
283
print ()
282
284
285
+ class FabricCapacity (FabricStat ):
286
+ def __init__ (self , namespace , table_cnt , threshold ):
287
+ self .db = None
288
+ self .namespace = namespace
289
+ self .multi_asic = multi_asic_util .MultiAsic (constants .DISPLAY_ALL , namespace )
290
+ self .table_cnt = table_cnt
291
+ self .threshold = threshold
292
+
293
+ def capacity_print (self ):
294
+ # Connect to database
295
+ self .db = multi_asic .connect_to_all_dbs_for_ns (self .namespace )
296
+ # Get fabric capacity data from STATE_DB table FABRIC_CAPACITY_TABLE
297
+ # and store them in fabric_capacity_data
298
+ fabric_capacity_data = self .db .get_all (self .db .STATE_DB , "FABRIC_CAPACITY_TABLE|FABRIC_CAPACITY_DATA" )
299
+ operational_fap_capacity = 0
300
+ operational_fabric_capacity = 0
301
+ operational_fabric_links = 0 ;
302
+ total_fabric_links = 0 ;
303
+ ratio = 0
304
+ last_event = "None"
305
+ last_time = "Never"
306
+
307
+ # Get data from fabric_capacity_data
308
+ if "fabric_capacity" in fabric_capacity_data :
309
+ operational_fabric_capacity = int (fabric_capacity_data ['fabric_capacity' ])
310
+ operational_fabric_capacity = operational_fabric_capacity / 1000.0
311
+ if "number_of_links" in fabric_capacity_data :
312
+ total_fabric_links = int (fabric_capacity_data ['number_of_links' ])
313
+ if "operating_links" in fabric_capacity_data :
314
+ operational_fabric_links = int (fabric_capacity_data ['operating_links' ])
315
+ if "warning_threshold" in fabric_capacity_data :
316
+ th = fabric_capacity_data ['warning_threshold' ]
317
+ th = th + "%"
318
+ self .threshold .append (th )
319
+ if "last_event" in fabric_capacity_data :
320
+ last_event = fabric_capacity_data ['last_event' ]
321
+ if "last_event_time" in fabric_capacity_data :
322
+ last_time = fabric_capacity_data ['last_event_time' ]
323
+
324
+ # Calculate the ratio of number of operational links and all links
325
+ if total_fabric_links > 0 :
326
+ ratio = operational_fabric_links / total_fabric_links * 100
327
+
328
+ if last_time != "Never" :
329
+ dt = datetime .fromtimestamp (int (last_time ), timezone .utc )
330
+ td = datetime .now (timezone .utc ) - dt
331
+ td_without_ms = timedelta (seconds = td .seconds )
332
+ last_time = str (td_without_ms ) + " ago"
333
+
334
+ asic_name = "asic0"
335
+ if self .namespace :
336
+ asic_name = self .namespace
337
+
338
+ # Update the table to print
339
+ self .table_cnt .append ((asic_name , operational_fabric_links , total_fabric_links , ratio , last_event , last_time ))
340
+
283
341
class FabricReachability (FabricStat ):
284
342
def reachability_print (self ):
285
343
# Connect to database
@@ -355,6 +413,8 @@ Examples:
355
413
fabricstat -p -n asic0 -e
356
414
fabricstat -q
357
415
fabricstat -q -n asic0
416
+ fabricstat -c
417
+ fabricstat -c -n asic0
358
418
fabricstat -C
359
419
fabricstat -D
360
420
""" )
@@ -363,13 +423,15 @@ Examples:
363
423
parser .add_argument ('-r' ,'--reachability' , action = 'store_true' , help = 'Display reachability, otherwise port stat' )
364
424
parser .add_argument ('-n' ,'--namespace' , default = None , help = 'Display fabric ports counters for specific namespace' )
365
425
parser .add_argument ('-e' , '--errors' , action = 'store_true' , help = 'Display errors' )
426
+ parser .add_argument ('-c' ,'--capacity' ,action = 'store_true' , help = 'Display fabric capacity' )
366
427
parser .add_argument ('-i' ,'--isolation' , action = 'store_true' , help = 'Display fabric ports isolation status' )
367
428
parser .add_argument ('-C' ,'--clear' , action = 'store_true' , help = 'Copy & clear fabric counters' )
368
429
parser .add_argument ('-D' ,'--delete' , action = 'store_true' , help = 'Delete saved stats' )
369
430
370
431
args = parser .parse_args ()
371
432
queue = args .queue
372
433
reachability = args .reachability
434
+ capacity_status = args .capacity
373
435
isolation_status = args .isolation
374
436
namespace = args .namespace
375
437
errors_only = args .errors
@@ -410,14 +472,36 @@ Examples:
410
472
else :
411
473
stat .cnstat_print (cnstat_dict , errors_only )
412
474
413
- if namespace is None :
414
- # All asics or all fabric asics
415
- multi_asic = multi_asic_util .MultiAsic ()
416
- for ns in multi_asic .get_ns_list_based_on_options ():
417
- nsStat (ns , errors_only )
475
+ if capacity_status :
476
+ # show fabric capacity command
477
+ capacity_header = []
478
+ table_cnt = []
479
+ threshold = []
480
+ capacity_header = ["ASIC" , "Operating\n Links" , "Total #\n of Links" , "%" , "Last Event" , "Last Time" ]
481
+ if namespace is None :
482
+ # All asics or all fabric asics
483
+ multi_asic = multi_asic_util .MultiAsic ()
484
+ for ns in multi_asic .get_ns_list_based_on_options ():
485
+ stat = FabricCapacity (ns , table_cnt , threshold )
486
+ stat .capacity_print ()
487
+ else :
488
+ # Asic with namespace
489
+ stat = FabricCapacity (namespace , table_cnt , threshold )
490
+ stat .capacity_print ()
491
+
492
+ click .echo ("Monitored fabric capacity threshold: {}" .format (threshold [0 ]))
493
+ click .echo ()
494
+ click .echo (tabulate (table_cnt , capacity_header , tablefmt = 'simple' , stralign = 'right' ))
418
495
else :
419
- # Asic with namespace
420
- nsStat (namespace , errors_only )
496
+ # other show fabric commands
497
+ if namespace is None :
498
+ # All asics or all fabric asics
499
+ multi_asic = multi_asic_util .MultiAsic ()
500
+ for ns in multi_asic .get_ns_list_based_on_options ():
501
+ nsStat (ns , errors_only )
502
+ else :
503
+ # Asic with namespace
504
+ nsStat (namespace , errors_only )
421
505
422
506
if __name__ == "__main__" :
423
507
main ()
0 commit comments