44import click
55import swsssdk
66from tabulate import tabulate
7- from subprocess import Popen , PIPE
7+ from utilities_common import multi_asic as multi_asic_util
8+ from sonic_py_common import multi_asic
89
910class Crm :
10- def __init__ (self ):
11+ def __init__ (self , db = None ):
1112 self .cli_mode = None
1213 self .addr_family = None
1314 self .res_type = None
15+ self .db = None
16+ self .cfgdb = db
17+ self .multi_asic = multi_asic_util .MultiAsic ()
1418
19+ @multi_asic_util .run_on_multi_asic
1520 def config (self , attr , val ):
1621 """
1722 CRM handler for 'config' CLI commands.
1823 """
19- configdb = swsssdk .ConfigDBConnector ()
20- configdb .connect ()
21-
22- configdb .mod_entry ("CRM" , 'Config' , {attr : val })
24+ if self .cfgdb :
25+ self .config_db = self .cfgdb
26+ self .config_db .mod_entry ("CRM" , 'Config' , {attr : val })
2327
2428 def show_summary (self ):
2529 """
2630 CRM Handler to display general information.
2731 """
28- configdb = swsssdk .ConfigDBConnector ()
29- configdb .connect ()
32+
33+ configdb = self .cfgdb
34+ if configdb is None :
35+ # Get the namespace list
36+ namespaces = multi_asic .get_namespace_list ()
37+
38+ configdb = swsssdk .ConfigDBConnector (namespace = namespaces [0 ])
39+ configdb .connect ()
3040
3141 crm_info = configdb .get_entry ('CRM' , 'Config' )
3242
@@ -39,8 +49,14 @@ def show_thresholds(self, resource):
3949 """
4050 CRM Handler to display thresholds information.
4151 """
42- configdb = swsssdk .ConfigDBConnector ()
43- configdb .connect ()
52+
53+ configdb = self .cfgdb
54+ if configdb is None :
55+ # Get the namespace list
56+ namespaces = multi_asic .get_namespace_list ()
57+
58+ configdb = swsssdk .ConfigDBConnector (namespace = namespaces [0 ])
59+ configdb .connect ()
4460
4561 crm_info = configdb .get_entry ('CRM' , 'Config' )
4662
@@ -62,16 +78,11 @@ def show_thresholds(self, resource):
6278 print tabulate (data , headers = header , tablefmt = "simple" , missingval = "" )
6379 print '\n '
6480
65- def show_resources (self , resource ):
81+ def get_resources (self , resource ):
6682 """
67- CRM Handler to display resources information.
83+ CRM Handler to get resources information.
6884 """
69- countersdb = swsssdk .SonicV2Connector (host = '127.0.0.1' )
70- countersdb .connect (countersdb .COUNTERS_DB )
71-
72- crm_stats = countersdb .get_all (countersdb .COUNTERS_DB , 'CRM:STATS' )
73-
74- header = ("Resource Name" , "Used Count" , "Available Count" )
85+ crm_stats = self .db .get_all (self .db .COUNTERS_DB , 'CRM:STATS' )
7586 data = []
7687
7788 if crm_stats :
@@ -81,26 +92,18 @@ def show_resources(self, resource):
8192 data .append ([res , crm_stats ['crm_stats_' + res + "_used" ], crm_stats ['crm_stats_' + res + "_available" ]])
8293 else :
8394 data .append ([resource , crm_stats ['crm_stats_' + resource + "_used" ], crm_stats ['crm_stats_' + resource + "_available" ]])
84- else :
85- print '\n CRM counters are not ready. They would be populated after the polling interval.'
8695
87- print '\n '
88- print tabulate (data , headers = header , tablefmt = "simple" , missingval = "" )
89- print '\n '
96+ return data
9097
91- def show_acl_resources (self ):
98+ def get_acl_resources (self ):
9299 """
93- CRM Handler to display ACL recources information.
100+ CRM Handler to get ACL recources information.
94101 """
95- countersdb = swsssdk .SonicV2Connector (host = '127.0.0.1' )
96- countersdb .connect (countersdb .COUNTERS_DB )
97-
98- header = ("Stage" , "Bind Point" , "Resource Name" , "Used Count" , "Available Count" )
99102 data = []
100103
101104 for stage in ["INGRESS" , "EGRESS" ]:
102105 for bind_point in ["PORT" , "LAG" , "VLAN" , "RIF" , "SWITCH" ]:
103- crm_stats = countersdb . get_all (countersdb .COUNTERS_DB , 'CRM:ACL_STATS:{0}:{1}' .format (stage , bind_point ))
106+ crm_stats = self . db . get_all (self . db .COUNTERS_DB , 'CRM:ACL_STATS:{0}:{1}' .format (stage , bind_point ))
104107
105108 if crm_stats :
106109 for res in ["acl_group" , "acl_table" ]:
@@ -110,52 +113,102 @@ def show_acl_resources(self):
110113 crm_stats ['crm_stats_' + res + "_available" ]
111114 ])
112115
113- print '\n '
114- print tabulate (data , headers = header , tablefmt = "simple" , missingval = "" )
115- print '\n '
116-
117- def show_acl_table_resources (self ):
116+ return data
117+ def get_acl_table_resources (self ):
118118 """
119119 CRM Handler to display ACL table information.
120120 """
121- countersdb = swsssdk .SonicV2Connector (host = '127.0.0.1' )
122- countersdb .connect (countersdb .COUNTERS_DB )
123-
124- header = ("Table ID" , "Resource Name" , "Used Count" , "Available Count" )
125-
126121 # Retrieve all ACL table keys from CRM:ACL_TABLE_STATS
127- proc = Popen ("docker exec -i database redis-cli --raw -n 2 KEYS *CRM:ACL_TABLE_STATS*" , stdout = PIPE , stderr = PIPE , shell = True )
128- out , err = proc .communicate ()
129-
130- for key in out .splitlines () or [None ]:
131- data = []
122+ crm_acl_keys = self .db .keys (self .db .COUNTERS_DB , 'CRM:ACL_TABLE_STATS*' )
123+ data = []
132124
125+ for key in crm_acl_keys or [None ]:
133126 if key :
134127 id = key .replace ('CRM:ACL_TABLE_STATS:' , '' )
135128
136- crm_stats = countersdb . get_all (countersdb .COUNTERS_DB , key )
129+ crm_stats = self . db . get_all (self . db .COUNTERS_DB , key )
137130
138131 for res in ['acl_entry' , 'acl_counter' ]:
139132 if ('crm_stats_' + res + '_used' in crm_stats ) and ('crm_stats_' + res + '_available' in crm_stats ):
140133 data .append ([id , res , crm_stats ['crm_stats_' + res + '_used' ], crm_stats ['crm_stats_' + res + '_available' ]])
141134
142- print '\n '
143- print tabulate (data , headers = header , tablefmt = "simple" , missingval = "" )
144- print '\n '
135+ return data
145136
137+ @multi_asic_util .run_on_multi_asic
138+ def show_resources (self , resource ):
139+ """
140+ CRM Handler to display resources information.
141+ """
142+ if multi_asic .is_multi_asic ():
143+ header = (self .multi_asic .current_namespace .upper () + "\n \n Resource Name" , "\n \n Used Count" , "\n \n Available Count" )
144+ err_msg = '\n CRM counters are not ready for ' + self .multi_asic .current_namespace .upper () + '. They would be populated after the polling interval.'
145+ else :
146+ header = ("Resource Name" , "Used Count" , "Available Count" )
147+ err_msg = '\n CRM counters are not ready. They would be populated after the polling interval.'
148+
149+ data = []
150+ data = self .get_resources (resource )
151+
152+ if data :
153+ click .echo ()
154+ click .echo (tabulate (data , headers = header , tablefmt = "simple" , missingval = "" ))
155+ click .echo ()
156+ else :
157+ click .echo (err_msg )
158+
159+ @multi_asic_util .run_on_multi_asic
160+ def show_acl_resources (self ):
161+ """
162+ CRM Handler to display ACL recources information.
163+ """
164+
165+ if multi_asic .is_multi_asic ():
166+ header = (self .multi_asic .current_namespace .upper () + "\n \n Stage" , "\n \n Bind Point" , "\n \n Resource Name" , "\n \n Used Count" , "\n \n Available Count" )
167+ else :
168+ header = ("Stage" , "Bind Point" , "Resource Name" , "Used Count" , "Available Count" )
169+
170+ data = []
171+ data = self .get_acl_resources ()
172+
173+ click .echo ()
174+ click .echo (tabulate (data , headers = header , tablefmt = "simple" , missingval = "" ))
175+ click .echo ()
176+
177+ @multi_asic_util .run_on_multi_asic
178+ def show_acl_table_resources (self ):
179+ """
180+ CRM Handler to display ACL table information.
181+ """
182+ if multi_asic .is_multi_asic ():
183+ header = (self .multi_asic .current_namespace .upper () + "\n \n Table ID" , "\n \n Resource Name" , "\n \n Used Count" , "\n \n Available Count" )
184+ else :
185+ header = ("Table ID" , "Resource Name" , "Used Count" , "Available Count" )
186+
187+ data = []
188+ data = self .get_acl_table_resources ()
189+
190+ click .echo ()
191+ click .echo (tabulate (data , headers = header , tablefmt = "simple" , missingval = "" ))
192+ click .echo ()
146193
147194@click .group ()
148195@click .pass_context
149196def cli (ctx ):
150197 """
151198 Utility entry point.
152199 """
200+ # Use the db object if given as input.
201+ db = None if ctx .obj is None else ctx .obj .cfgdb
202+
153203 context = {
154- "crm" : Crm ()
204+ "crm" : Crm (db )
155205 }
156206
157207 ctx .obj = context
158208
209+ # Load the global config file database_global.json once.
210+ swsssdk .SonicDBConfig .load_sonic_global_db_config ()
211+
159212@cli .group ()
160213@click .pass_context
161214def config (ctx ):
0 commit comments