Skip to content

Commit 7030c97

Browse files
tsvanduynjleveque
authored andcommitted
[show] show interface status added vlan and portchannels to command (#483)
1 parent a30d1a8 commit 7030c97

File tree

1 file changed

+241
-23
lines changed

1 file changed

+241
-23
lines changed

scripts/intfutil

+241-23
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import swsssdk
44
import sys
55
import re
6+
import types
67
from tabulate import tabulate
78
from natsort import natsorted
8-
9+
from swsssdk import ConfigDBConnector
10+
from pprint import pprint
911

1012

1113
# ========================== Common interface-utils logic ==========================
@@ -23,42 +25,84 @@ PORT_DESCRIPTION = "description"
2325
PORT_OPTICS_TYPE = "type"
2426
PORT_PFC_ASYM_STATUS = "pfc_asym"
2527

28+
def db_connect_configdb():
29+
"""
30+
Connect to configdb
31+
"""
32+
config_db = ConfigDBConnector()
33+
if config_db is None:
34+
return None
35+
config_db.connect()
36+
return config_db
37+
38+
def get_frontpanel_port_list(config_db):
39+
ports_dict = config_db.get_table('PORT')
40+
front_panel_ports_list = []
41+
for port in ports_dict.iterkeys():
42+
front_panel_ports_list.append(port)
43+
return front_panel_ports_list
44+
45+
46+
def get_interface_vlan_dict(config_db):
47+
"""
48+
Get info from REDIS ConfigDB and create interface to vlan mapping
49+
"""
50+
get_int_vlan_configdb_info = config_db.get_table('VLAN_MEMBER')
51+
int_list = []
52+
vlan_list = []
53+
for line in get_int_vlan_configdb_info:
54+
vlan_number = line[0]
55+
interface = line[1]
56+
int_list.append(interface)
57+
vlan_list.append(vlan_number)
58+
int_to_vlan_dict = dict(zip(int_list, vlan_list))
59+
return int_to_vlan_dict
60+
61+
62+
def config_db_vlan_port_keys_get(int_to_vlan_dict, front_panel_ports_list, intf_name):
63+
"""
64+
Get interface vlan value and return it.
65+
"""
66+
vlan = "routed"
67+
if intf_name in front_panel_ports_list:
68+
if intf_name in int_to_vlan_dict.keys():
69+
vlan = int_to_vlan_dict[intf_name]
70+
if "Vlan" in vlan:
71+
vlan = "trunk"
72+
return vlan
73+
2674

2775
def db_connect_appl():
2876
appl_db = swsssdk.SonicV2Connector(host='127.0.0.1')
2977
if appl_db is None:
3078
return None
31-
3279
appl_db.connect(appl_db.APPL_DB)
33-
3480
return appl_db
3581

3682

37-
def appl_db_keys_get(appl_db, intf_name):
38-
83+
def appl_db_keys_get(appl_db, front_panel_ports_list, intf_name):
84+
"""
85+
Get APPL_DB Keys
86+
"""
3987
if intf_name is None:
4088
appl_db_keys = appl_db.keys(appl_db.APPL_DB, "PORT_TABLE:*")
41-
elif intf_name.startswith('Ethernet'):
42-
appl_db_keys = appl_db.keys(appl_db.APPL_DB, "PORT_TABLE:%s" % intf_name)
89+
elif intf_name in front_panel_ports_list:
90+
appl_db_keys = db.keys(appl_db.APPL_DB, "PORT_TABLE:%s" % intf_name)
4391
else:
4492
return None
45-
4693
return appl_db_keys
4794

4895

4996
def appl_db_port_status_get(appl_db, intf_name, status_type):
5097
"""
5198
Get the port status
5299
"""
53-
54100
full_table_id = PORT_STATUS_TABLE_PREFIX + intf_name
55101
status = appl_db.get(appl_db.APPL_DB, full_table_id, status_type)
56102
if status is None:
57103
return "N/A"
58-
59104
if status_type == PORT_SPEED and status != "N/A":
60105
status = '{}G'.format(status[:-3])
61-
62106
return status
63107

64108

@@ -83,13 +127,153 @@ def state_db_port_optics_get(state_db, intf_name, type):
83127
return "N/A"
84128
return optics_type
85129

130+
def merge_dicts(x,y):
131+
# store a copy of x, but overwrite with y's values where applicable
132+
merged = dict(x,**y)
133+
xkeys = x.keys()
134+
# if the value of merged[key] was overwritten with y[key]'s value
135+
# then we need to put back any missing x[key] values
136+
for key in xkeys:
137+
# if this key is a dictionary, recurse
138+
if type(x[key]) is types.DictType and y.has_key(key):
139+
merged[key] = merge(x[key],y[key])
140+
return merged
141+
142+
def tuple_to_dict(tup, new_dict):
143+
"""
144+
From a tuple create a dictionary that uses the first item in the tuple as a key
145+
and the 2nd item in the tuple as a value.
146+
"""
147+
for a, b in tup:
148+
new_dict.setdefault(a, []).append(b)
149+
return new_dict
150+
151+
152+
def get_raw_portchannel_info(config_db):
153+
"""
154+
This function uses the redis config_db as input and gets the "PORTCHANNEL_MEMBER" table
155+
create
156+
>>> get_po_int_configdb_info = get_portchannel_info(config_db)
157+
>>> pprint(get_po_int_configdb_info)
158+
{('PortChannel0001', 'Ethernet108'): {},
159+
('PortChannel0001', 'Ethernet112'): {},
160+
('PortChannel0002', 'Ethernet116'): {},
161+
('PortChannel0003', 'Ethernet120'): {},
162+
('PortChannel0004', 'Ethernet124'): {}}
163+
This function returns a dictionary with the key being portchannels and interface tuple.
164+
"""
165+
get_raw_po_int_configdb_info = config_db.get_table('PORTCHANNEL_MEMBER')
166+
return get_raw_po_int_configdb_info # Return a dictionary with the key being the portchannel and interface
167+
168+
def get_portchannel_list(get_raw_po_int_configdb_info):
169+
"""
170+
>>> portchannel_list = get_portchannel_list(get_raw_po_int_configdb_info)
171+
>>> pprint(portchannel_list)
172+
['PortChannel0001', 'PortChannel0002', 'PortChannel0003', 'PortChannel0004']
173+
>>>
174+
"""
175+
portchannel_list = []
176+
for po in get_raw_po_int_configdb_info:
177+
portchannel = po[0]
178+
if portchannel not in portchannel_list:
179+
portchannel_list.append(portchannel)
180+
portchannel = portchannel_list.sort()
181+
return portchannel_list
182+
183+
def create_po_int_tuple_list(get_raw_po_int_configdb_info):
184+
"""
185+
>>> po_int_tuple = get_raw_po_int_configdb_info.keys()
186+
>>> pprint(po_int_tuple_list)
187+
[('PortChannel0001', 'Ethernet108'),
188+
('PortChannel0002', 'Ethernet116'),
189+
('PortChannel0004', 'Ethernet124'),
190+
('PortChannel0003', 'Ethernet120'),
191+
('PortChannel0001', 'Ethernet112')]
192+
>>>
193+
"""
194+
po_int_tuple_list = get_raw_po_int_configdb_info.keys()
195+
return po_int_tuple_list
196+
197+
def create_po_int_dict(po_int_tuple_list):
198+
"""
199+
This function takes the portchannel to interface tuple
200+
and converts that into a portchannel to interface dictionary
201+
with the portchannels as the key and the interfaces as the values.
202+
"""
203+
temp_dict = {}
204+
po_int_dict = tuple_to_dict(po_int_tuple_list, temp_dict)
205+
return po_int_dict
206+
207+
def create_int_to_portchannel_dict(po_int_tuple_list):
208+
"""
209+
This function takes the portchannel to interface tuple
210+
and converts that into an interface to portchannel dictionary
211+
with the interfaces as the key and the portchannels as the values.
212+
"""
213+
int_po_dict = {}
214+
for po, intf in po_int_tuple_list:
215+
int_po_dict.setdefault(intf, po)
216+
return int_po_dict
217+
218+
def po_speed_dict(po_int_dict, appl_db):
219+
"""
220+
This function takes the portchannel to interface dictionary
221+
and the appl_db and then creates a portchannel to speed
222+
dictionary.
223+
"""
224+
if po_int_dict:
225+
po_list = []
226+
for key, value in po_int_dict.iteritems():
227+
agg_speed_list = []
228+
po_list.append(key)
229+
if len(value) == 1:
230+
interface_speed = appl_db.get(appl_db.APPL_DB, "PORT_TABLE:" + value[0], "speed")
231+
interface_speed = '{}G'.format(interface_speed[:-3])
232+
po_list.append(interface_speed)
233+
elif len(value) > 1:
234+
for intf in value:
235+
temp_speed = appl_db.get(appl_db.APPL_DB, "PORT_TABLE:" + intf, "speed")
236+
temp_speed = int(temp_speed)
237+
agg_speed_list.append(temp_speed)
238+
interface_speed = sum(agg_speed_list)
239+
interface_speed = str(interface_speed)
240+
interface_speed = '{}G'.format(interface_speed[:-3])
241+
po_list.append(interface_speed)
242+
po_speed_dict = dict(po_list[i:i+2] for i in range(0, len(po_list), 2))
243+
return po_speed_dict
244+
else:
245+
po_speed_dict = {}
246+
return po_speed_dict
247+
248+
def appl_db_portchannel_status_get(appl_db, config_db, po_name, status_type, portchannel_speed_dict):
249+
"""
250+
Get the port status
251+
"""
252+
full_table_id = "LAG_TABLE:" + po_name
253+
po_table_id = "PORTCHANNEL|" + po_name
254+
#print(full_table_id)
255+
if status_type == "speed":
256+
status = portchannel_speed_dict[po_name]
257+
return status
258+
if status_type == "vlan":
259+
status = "routed"
260+
return status
261+
if status_type == "mtu":
262+
status = config_db.get(config_db.CONFIG_DB, po_table_id, status_type)
263+
return status
264+
status = appl_db.get(appl_db.APPL_DB, full_table_id, status_type)
265+
#print(status)
266+
if status is None:
267+
return "N/A"
268+
return status
269+
86270
# ========================== interface-status logic ==========================
87271

88-
header_stat = ['Interface', 'Lanes', 'Speed', 'MTU', 'Alias', 'Oper', 'Admin', 'Type', 'Asym PFC']
272+
header_stat = ['Interface', 'Lanes', 'Speed', 'MTU', 'Alias', 'Vlan', 'Oper', 'Admin', 'Type', 'Asym PFC']
89273

90274
class IntfStatus(object):
91275

92-
def display_intf_status(self, appl_db_keys):
276+
def display_intf_status(self, appl_db_keys, front_panel_ports_list, portchannel_speed_dict):
93277
"""
94278
Generate interface-status output
95279
"""
@@ -104,34 +288,65 @@ class IntfStatus(object):
104288
#
105289
for i in appl_db_keys:
106290
key = re.split(':', i, maxsplit=1)[-1].strip()
107-
if key and key.startswith('Ethernet'):
291+
if key in front_panel_ports_list:
108292
table.append((key,
109293
appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS),
110294
appl_db_port_status_get(self.appl_db, key, PORT_SPEED),
111295
appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS),
112296
appl_db_port_status_get(self.appl_db, key, PORT_ALIAS),
297+
config_db_vlan_port_keys_get(self.combined_int_to_vlan_po_dict, self.front_panel_ports_list, key),
113298
appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS),
114299
appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS),
115300
state_db_port_optics_get(self.state_db, key, PORT_OPTICS_TYPE),
116301
appl_db_port_status_get(self.appl_db, key, PORT_PFC_ASYM_STATUS)))
117-
118302
# Sorting and tabulating the result table.
303+
for po, value in portchannel_speed_dict.iteritems():
304+
if po:
305+
table.append((po,
306+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_LANES_STATUS, self.portchannel_speed_dict),
307+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_SPEED, self.portchannel_speed_dict),
308+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_MTU_STATUS, self.portchannel_speed_dict),
309+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_ALIAS, self.portchannel_speed_dict),
310+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, "vlan", self.portchannel_speed_dict),
311+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_OPER_STATUS, self.portchannel_speed_dict),
312+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_ADMIN_STATUS, self.portchannel_speed_dict),
313+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_OPTICS_TYPE, self.portchannel_speed_dict),
314+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_PFC_ASYM_STATUS, self.portchannel_speed_dict)))
315+
119316
sorted_table = natsorted(table)
120317
print tabulate(sorted_table, header_stat, tablefmt="simple", stralign='right')
121318

122319

123320
def __init__(self, intf_name):
124-
321+
"""
322+
Class constructor method
323+
:param self:
324+
:param intf_name: string of interface
325+
:return:
326+
"""
125327
self.appl_db = db_connect_appl()
126328
self.state_db = db_connect_state()
329+
self.config_db = db_connect_configdb()
127330
if self.appl_db is None:
128331
return
129332
if self.state_db is None:
130333
return
131-
appl_db_keys = appl_db_keys_get(self.appl_db, intf_name)
334+
if self.config_db is None:
335+
return
336+
self.front_panel_ports_list = get_frontpanel_port_list(self.config_db)
337+
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, intf_name)
338+
self.int_to_vlan_dict = get_interface_vlan_dict(self.config_db)
339+
self.get_raw_po_int_configdb_info = get_raw_portchannel_info(self.config_db)
340+
self.portchannel_list = get_portchannel_list(self.get_raw_po_int_configdb_info)
341+
self.po_int_tuple_list = create_po_int_tuple_list(self.get_raw_po_int_configdb_info)
342+
self.po_int_dict = create_po_int_dict(self.po_int_tuple_list)
343+
self.int_po_dict = create_int_to_portchannel_dict(self.po_int_tuple_list)
344+
self.combined_int_to_vlan_po_dict = merge_dicts(self.int_to_vlan_dict, self.int_po_dict)
345+
self.portchannel_speed_dict = po_speed_dict(self.po_int_dict, self.appl_db)
346+
self.portchannel_keys = self.portchannel_speed_dict.keys()
132347
if appl_db_keys is None:
133348
return
134-
self.display_intf_status(appl_db_keys)
349+
self.display_intf_status(appl_db_keys, self.front_panel_ports_list, self.portchannel_speed_dict)
135350

136351

137352

@@ -143,7 +358,7 @@ header_desc = ['Interface', 'Oper', 'Admin', 'Alias', 'Description']
143358

144359
class IntfDescription(object):
145360

146-
def display_intf_description(self, appl_db_keys):
361+
def display_intf_description(self, appl_db_keys, front_panel_ports_list):
147362
"""
148363
Generate interface-description output
149364
"""
@@ -158,7 +373,7 @@ class IntfDescription(object):
158373
#
159374
for i in appl_db_keys:
160375
key = re.split(':', i, maxsplit=1)[-1].strip()
161-
if key and key.startswith('Ethernet'):
376+
if key in front_panel_ports_list:
162377
table.append((key,
163378
appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS),
164379
appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS),
@@ -171,15 +386,18 @@ class IntfDescription(object):
171386

172387
def __init__(self, intf_name):
173388

389+
self.config_db = db_connect_configdb()
174390
self.appl_db = db_connect_appl()
175391
if self.appl_db is None:
176392
return
177-
178-
appl_db_keys = appl_db_keys_get(self.appl_db, intf_name)
393+
if self.config_db is None:
394+
return
395+
self.front_panel_ports_list = get_frontpanel_port_list(self.config_db)
396+
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, intf_name)
179397
if appl_db_keys is None:
180398
return
181399

182-
self.display_intf_description(appl_db_keys)
400+
self.display_intf_description(appl_db_keys, self.front_panel_ports_list)
183401

184402

185403

0 commit comments

Comments
 (0)