Skip to content

Commit c7389bd

Browse files
authored
show linkmgrd status in show mux status (sonic-net#2254)
What I did Replace status in show mux status with APP DB MUX_CABLE_TABLE:<port_name>, which is written by linkmgrd and indicates linkmgrd's state transition. This change is required for active-active dualtor setup. In active-active setup, we care more about whether state transition happens on ToR side. In tests, we want to see if linkmgrd makes immediate reaction on link state changes. If we continue to use STATE DB entries, when gRPC is not available, we will get unknow in show mux status, which is not informatic and not the actual value we want to check. sign-off: Jing Zhang [email protected] How I did it Use APP DB entries instead of STATE DB. Move STATE DB to column SERVER_STATUS. How to verify it Unit tests with mock DB values. Tests on dual testbeds.
1 parent 7070794 commit c7389bd

File tree

3 files changed

+84
-35
lines changed

3 files changed

+84
-35
lines changed

show/muxcable.py

+36-17
Original file line numberDiff line numberDiff line change
@@ -401,13 +401,15 @@ def get_switch_name(config_db):
401401
sys.exit(STATUS_FAIL)
402402

403403

404-
def create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict, muxcable_health_dict, muxcable_metrics_dict, asic_index, port):
404+
def create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict, muxcable_grpc_dict, muxcable_health_dict, muxcable_metrics_dict, asic_index, port):
405405

406406
res_dict = {}
407407
status_value = get_value_for_key_in_dict(muxcable_info_dict[asic_index], port, "state", "MUX_CABLE_TABLE")
408408
port_name = platform_sfputil_helper.get_interface_alias(port, db)
409409
port_status_dict["MUX_CABLE"][port_name] = {}
410410
port_status_dict["MUX_CABLE"][port_name]["STATUS"] = status_value
411+
gRPC_value = get_value_for_key_in_dict(muxcable_grpc_dict[asic_index], port, "state", "MUX_CABLE_TABLE")
412+
port_status_dict["MUX_CABLE"][port_name]["SERVER_STATUS"] = gRPC_value
411413
health_value = get_value_for_key_in_dict(muxcable_health_dict[asic_index], port, "state", "MUX_LINKMGR_TABLE")
412414
port_status_dict["MUX_CABLE"][port_name]["HEALTH"] = health_value
413415
res_dict = get_hwmode_mux_direction_port(db, port)
@@ -428,14 +430,15 @@ def create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict, m
428430
last_switch_end_time = muxcable_metrics_dict[asic_index].get("linkmgrd_switch_active_end")
429431
port_status_dict["MUX_CABLE"][port_name]["LAST_SWITCHOVER_TIME"] = last_switch_end_time
430432

431-
def create_table_dump_per_port_status(db, print_data, muxcable_info_dict, muxcable_health_dict, muxcable_metrics_dict, asic_index, port):
433+
def create_table_dump_per_port_status(db, print_data, muxcable_info_dict, muxcable_grpc_dict, muxcable_health_dict, muxcable_metrics_dict, asic_index, port):
432434

433435
print_port_data = []
434436
res_dict = {}
435437

436438
res_dict = get_hwmode_mux_direction_port(db, port)
437439
status_value = get_value_for_key_in_dict(muxcable_info_dict[asic_index], port, "state", "MUX_CABLE_TABLE")
438440
#status_value = get_value_for_key_in_tbl(y_cable_asic_table, port, "status")
441+
gRPC_value = get_value_for_key_in_dict(muxcable_grpc_dict[asic_index], port, "state", "MUX_CABLE_TABLE")
439442
health_value = get_value_for_key_in_dict(muxcable_health_dict[asic_index], port, "state", "MUX_LINKMGR_TABLE")
440443

441444
last_switch_end_time = ""
@@ -447,6 +450,7 @@ def create_table_dump_per_port_status(db, print_data, muxcable_info_dict, muxcab
447450
port_name = platform_sfputil_helper.get_interface_alias(port, db)
448451
print_port_data.append(port_name)
449452
print_port_data.append(status_value)
453+
print_port_data.append(gRPC_value)
450454
print_port_data.append(health_value)
451455
if res_dict[2] == "False":
452456
hwstatus = "absent"
@@ -510,10 +514,13 @@ def status(db, port, json_output):
510514
port = platform_sfputil_helper.get_interface_name(port, db)
511515

512516
port_table_keys = {}
517+
appl_db_muxcable_tbl_keys = {}
513518
port_health_table_keys = {}
514519
port_metrics_table_keys = {}
515520
per_npu_statedb = {}
521+
per_npu_appl_db = {}
516522
muxcable_info_dict = {}
523+
muxcable_grpc_dict = {}
517524
muxcable_health_dict = {}
518525
muxcable_metrics_dict = {}
519526

@@ -525,6 +532,11 @@ def status(db, port, json_output):
525532
per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
526533
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)
527534

535+
per_npu_appl_db[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
536+
per_npu_appl_db[asic_id].connect(per_npu_appl_db[asic_id].APPL_DB)
537+
538+
appl_db_muxcable_tbl_keys[asic_id] = per_npu_appl_db[asic_id].keys(
539+
per_npu_appl_db[asic_id].APPL_DB, 'MUX_CABLE_TABLE:*')
528540
port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
529541
per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')
530542
port_health_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
@@ -546,17 +558,20 @@ def status(db, port, json_output):
546558
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port_name))
547559
sys.exit(STATUS_FAIL)
548560

549-
muxcable_info_dict[asic_index] = per_npu_statedb[asic_index].get_all(
561+
muxcable_info_dict[asic_index] = per_npu_appl_db[asic_id].get_all(
562+
per_npu_appl_db[asic_id].APPL_DB, 'MUX_CABLE_TABLE:{}'.format(port))
563+
muxcable_grpc_dict[asic_index] = per_npu_statedb[asic_index].get_all(
550564
per_npu_statedb[asic_index].STATE_DB, 'MUX_CABLE_TABLE|{}'.format(port))
551565
muxcable_health_dict[asic_index] = per_npu_statedb[asic_index].get_all(
552566
per_npu_statedb[asic_index].STATE_DB, 'MUX_LINKMGR_TABLE|{}'.format(port))
553567
muxcable_metrics_dict[asic_index] = per_npu_statedb[asic_index].get_all(
554568
per_npu_statedb[asic_index].STATE_DB, 'MUX_METRICS_TABLE|{}'.format(port))
569+
555570
if muxcable_info_dict[asic_index] is not None:
556-
logical_key = "MUX_CABLE_TABLE|{}".format(port)
571+
logical_key = "MUX_CABLE_TABLE:{}".format(port)
557572
logical_health_key = "MUX_LINKMGR_TABLE|{}".format(port)
558573
logical_metrics_key = "MUX_METRICS_TABLE|{}".format(port)
559-
if logical_key in port_table_keys[asic_index] and logical_health_key in port_health_table_keys[asic_index]:
574+
if logical_key in appl_db_muxcable_tbl_keys[asic_index] and logical_health_key in port_health_table_keys[asic_index]:
560575

561576
if logical_metrics_key not in port_metrics_table_keys[asic_index]:
562577
muxcable_metrics_dict[asic_index] = {}
@@ -565,18 +580,18 @@ def status(db, port, json_output):
565580
port_status_dict = {}
566581
port_status_dict["MUX_CABLE"] = {}
567582

568-
create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict,
583+
create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict, muxcable_grpc_dict,
569584
muxcable_health_dict, muxcable_metrics_dict, asic_index, port)
570585

571586
click.echo("{}".format(json.dumps(port_status_dict, indent=4)))
572587
sys.exit(STATUS_SUCCESSFUL)
573588
else:
574589
print_data = []
575590

576-
create_table_dump_per_port_status(db, print_data, muxcable_info_dict,
591+
create_table_dump_per_port_status(db, print_data, muxcable_info_dict, muxcable_grpc_dict,
577592
muxcable_health_dict, muxcable_metrics_dict, asic_index, port)
578593

579-
headers = ['PORT', 'STATUS', 'HEALTH', 'HWSTATUS', 'LAST_SWITCHOVER_TIME']
594+
headers = ['PORT', 'STATUS', 'SERVER_STATUS', 'HEALTH', 'HWSTATUS', 'LAST_SWITCHOVER_TIME']
580595

581596
click.echo(tabulate(print_data, headers=headers))
582597
sys.exit(STATUS_SUCCESSFUL)
@@ -595,38 +610,42 @@ def status(db, port, json_output):
595610
port_status_dict["MUX_CABLE"] = {}
596611
for namespace in namespaces:
597612
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
598-
for key in natsorted(port_table_keys[asic_id]):
599-
port = key.split("|")[1]
600-
muxcable_info_dict[asic_id] = per_npu_statedb[asic_id].get_all(
613+
for key in natsorted(appl_db_muxcable_tbl_keys[asic_id]):
614+
port = key.split(":")[1]
615+
muxcable_info_dict[asic_id] = per_npu_appl_db[asic_id].get_all(
616+
per_npu_appl_db[asic_id].APPL_DB, 'MUX_CABLE_TABLE:{}'.format(port))
617+
muxcable_grpc_dict[asic_id] = per_npu_statedb[asic_id].get_all(
601618
per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|{}'.format(port))
602619
muxcable_health_dict[asic_id] = per_npu_statedb[asic_id].get_all(
603620
per_npu_statedb[asic_id].STATE_DB, 'MUX_LINKMGR_TABLE|{}'.format(port))
604621
muxcable_metrics_dict[asic_id] = per_npu_statedb[asic_id].get_all(
605622
per_npu_statedb[asic_id].STATE_DB, 'MUX_METRICS_TABLE|{}'.format(port))
606623
if not muxcable_metrics_dict[asic_id]:
607624
muxcable_metrics_dict[asic_id] = {}
608-
create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict,
625+
create_json_dump_per_port_status(db, port_status_dict, muxcable_info_dict, muxcable_grpc_dict,
609626
muxcable_health_dict, muxcable_metrics_dict, asic_id, port)
610627

611628
click.echo("{}".format(json.dumps(port_status_dict, indent=4)))
612629
else:
613630
print_data = []
614631
for namespace in namespaces:
615632
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
616-
for key in natsorted(port_table_keys[asic_id]):
617-
port = key.split("|")[1]
633+
for key in natsorted(appl_db_muxcable_tbl_keys[asic_id]):
634+
port = key.split(":")[1]
635+
muxcable_info_dict[asic_id] = per_npu_appl_db[asic_id].get_all(
636+
per_npu_appl_db[asic_id].APPL_DB, 'MUX_CABLE_TABLE:{}'.format(port))
618637
muxcable_health_dict[asic_id] = per_npu_statedb[asic_id].get_all(
619638
per_npu_statedb[asic_id].STATE_DB, 'MUX_LINKMGR_TABLE|{}'.format(port))
620-
muxcable_info_dict[asic_id] = per_npu_statedb[asic_id].get_all(
639+
muxcable_grpc_dict[asic_id] = per_npu_statedb[asic_id].get_all(
621640
per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|{}'.format(port))
622641
muxcable_metrics_dict[asic_id] = per_npu_statedb[asic_id].get_all(
623642
per_npu_statedb[asic_id].STATE_DB, 'MUX_METRICS_TABLE|{}'.format(port))
624643
if not muxcable_metrics_dict[asic_id]:
625644
muxcable_metrics_dict[asic_id] = {}
626-
create_table_dump_per_port_status(db, print_data, muxcable_info_dict,
645+
create_table_dump_per_port_status(db, print_data, muxcable_info_dict, muxcable_grpc_dict,
627646
muxcable_health_dict, muxcable_metrics_dict, asic_id, port)
628647

629-
headers = ['PORT', 'STATUS', 'HEALTH', 'HWSTATUS','LAST_SWITCHOVER_TIME']
648+
headers = ['PORT', 'STATUS', 'SERVER_STATUS', 'HEALTH', 'HWSTATUS', 'LAST_SWITCHOVER_TIME']
630649
click.echo(tabulate(print_data, headers=headers))
631650

632651
sys.exit(STATUS_SUCCESSFUL)

tests/mock_tables/appl_db.json

+18
Original file line numberDiff line numberDiff line change
@@ -263,5 +263,23 @@
263263
},
264264
"VXLAN_REMOTE_VNI_TABLE:Vlan200:25.25.25.27": {
265265
"vni": "200"
266+
},
267+
"MUX_CABLE_TABLE:Ethernet32": {
268+
"state": "active"
269+
},
270+
"MUX_CABLE_TABLE:Ethernet0": {
271+
"state": "active"
272+
},
273+
"MUX_CABLE_TABLE:Ethernet4": {
274+
"state": "standby"
275+
},
276+
"MUX_CABLE_TABLE:Ethernet8": {
277+
"state": "standby"
278+
},
279+
"MUX_CABLE_TABLE:Ethernet16": {
280+
"state": "standby"
281+
},
282+
"MUX_CABLE_TABLE:Ethernet12": {
283+
"state": "active"
266284
}
267285
}

tests/muxcable_test.py

+30-18
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,25 @@
2525

2626

2727
tabular_data_status_output_expected = """\
28-
PORT STATUS HEALTH HWSTATUS LAST_SWITCHOVER_TIME
29-
---------- -------- --------- ------------ ---------------------------
30-
Ethernet0 active healthy inconsistent 2021-May-13 10:01:15.696728
31-
Ethernet4 standby healthy consistent
32-
Ethernet8 standby unhealthy consistent
33-
Ethernet12 unknown unhealthy inconsistent
34-
Ethernet16 standby healthy consistent
35-
Ethernet32 active healthy inconsistent
28+
PORT STATUS SERVER_STATUS HEALTH HWSTATUS LAST_SWITCHOVER_TIME
29+
---------- -------- --------------- --------- ------------ ---------------------------
30+
Ethernet0 active active healthy inconsistent 2021-May-13 10:01:15.696728
31+
Ethernet4 standby standby healthy consistent
32+
Ethernet8 standby standby unhealthy consistent
33+
Ethernet12 active unknown unhealthy inconsistent
34+
Ethernet16 standby standby healthy consistent
35+
Ethernet32 active active healthy inconsistent
3636
"""
3737

3838
tabular_data_status_output_expected_alias = """\
39-
PORT STATUS HEALTH HWSTATUS LAST_SWITCHOVER_TIME
40-
------ -------- --------- ------------ ---------------------------
41-
etp1 active healthy inconsistent 2021-May-13 10:01:15.696728
42-
etp2 standby healthy consistent
43-
etp3 standby unhealthy consistent
44-
etp4 unknown unhealthy inconsistent
45-
etp5 standby healthy consistent
46-
etp9 active healthy inconsistent
39+
PORT STATUS SERVER_STATUS HEALTH HWSTATUS LAST_SWITCHOVER_TIME
40+
------ -------- --------------- --------- ------------ ---------------------------
41+
etp1 active active healthy inconsistent 2021-May-13 10:01:15.696728
42+
etp2 standby standby healthy consistent
43+
etp3 standby standby unhealthy consistent
44+
etp4 active unknown unhealthy inconsistent
45+
etp5 standby standby healthy consistent
46+
etp9 active active healthy inconsistent
4747
"""
4848

4949

@@ -52,36 +52,42 @@
5252
"MUX_CABLE": {
5353
"Ethernet0": {
5454
"STATUS": "active",
55+
"SERVER_STATUS": "active",
5556
"HEALTH": "healthy",
5657
"HWSTATUS": "inconsistent",
5758
"LAST_SWITCHOVER_TIME": "2021-May-13 10:01:15.696728"
5859
},
5960
"Ethernet4": {
6061
"STATUS": "standby",
62+
"SERVER_STATUS": "standby",
6163
"HEALTH": "healthy",
6264
"HWSTATUS": "consistent",
6365
"LAST_SWITCHOVER_TIME": ""
6466
},
6567
"Ethernet8": {
6668
"STATUS": "standby",
69+
"SERVER_STATUS": "standby",
6770
"HEALTH": "unhealthy",
6871
"HWSTATUS": "consistent",
6972
"LAST_SWITCHOVER_TIME": ""
7073
},
7174
"Ethernet12": {
72-
"STATUS": "unknown",
75+
"STATUS": "active",
76+
"SERVER_STATUS": "unknown",
7377
"HEALTH": "unhealthy",
7478
"HWSTATUS": "inconsistent",
7579
"LAST_SWITCHOVER_TIME": ""
7680
},
7781
"Ethernet16": {
7882
"STATUS": "standby",
83+
"SERVER_STATUS": "standby",
7984
"HEALTH": "healthy",
8085
"HWSTATUS": "consistent",
8186
"LAST_SWITCHOVER_TIME": ""
8287
},
8388
"Ethernet32": {
8489
"STATUS": "active",
90+
"SERVER_STATUS": "active",
8591
"HEALTH": "healthy",
8692
"HWSTATUS": "inconsistent",
8793
"LAST_SWITCHOVER_TIME": ""
@@ -95,36 +101,42 @@
95101
"MUX_CABLE": {
96102
"etp1": {
97103
"STATUS": "active",
104+
"SERVER_STATUS": "active",
98105
"HEALTH": "healthy",
99106
"HWSTATUS": "inconsistent",
100107
"LAST_SWITCHOVER_TIME": "2021-May-13 10:01:15.696728"
101108
},
102109
"etp2": {
103110
"STATUS": "standby",
111+
"SERVER_STATUS": "standby",
104112
"HEALTH": "healthy",
105113
"HWSTATUS": "consistent",
106114
"LAST_SWITCHOVER_TIME": ""
107115
},
108116
"etp3": {
109117
"STATUS": "standby",
118+
"SERVER_STATUS": "standby",
110119
"HEALTH": "unhealthy",
111120
"HWSTATUS": "consistent",
112121
"LAST_SWITCHOVER_TIME": ""
113122
},
114123
"etp4": {
115-
"STATUS": "unknown",
124+
"STATUS": "active",
125+
"SERVER_STATUS": "unknown",
116126
"HEALTH": "unhealthy",
117127
"HWSTATUS": "inconsistent",
118128
"LAST_SWITCHOVER_TIME": ""
119129
},
120130
"etp5": {
121131
"STATUS": "standby",
132+
"SERVER_STATUS": "standby",
122133
"HEALTH": "healthy",
123134
"HWSTATUS": "consistent",
124135
"LAST_SWITCHOVER_TIME": ""
125136
},
126137
"etp9": {
127138
"STATUS": "active",
139+
"SERVER_STATUS": "active",
128140
"HEALTH": "healthy",
129141
"HWSTATUS": "inconsistent",
130142
"LAST_SWITCHOVER_TIME": ""

0 commit comments

Comments
 (0)