2
2
config_mgmt.py provides classes for configuration validation and for Dynamic
3
3
Port Breakout.
4
4
'''
5
+
6
+ import os
5
7
import re
8
+ import shutil
6
9
import syslog
10
+ import tempfile
11
+ import yang as ly
7
12
from json import load
8
13
from sys import flags
9
14
from time import sleep as tsleep
@@ -46,34 +51,38 @@ def __init__(self, source="configDB", debug=False, allowTablesWithoutYang=True):
46
51
try :
47
52
self .configdbJsonIn = None
48
53
self .configdbJsonOut = None
54
+ self .source = source
49
55
self .allowTablesWithoutYang = allowTablesWithoutYang
50
56
51
57
# logging vars
52
58
self .SYSLOG_IDENTIFIER = "ConfigMgmt"
53
59
self .DEBUG = debug
54
60
55
- self .sy = sonic_yang .SonicYang (YANG_DIR , debug = debug )
56
- # load yang models
57
- self .sy .loadYangModel ()
58
- # load jIn from config DB or from config DB json file.
59
- if source .lower () == 'configdb' :
60
- self .readConfigDB ()
61
- # treat any other source as file input
62
- else :
63
- self .readConfigDBJson (source )
64
- # this will crop config, xlate and load.
65
- self .sy .loadData (self .configdbJsonIn )
66
-
67
- # Raise if tables without YANG models are not allowed but exist.
68
- if not allowTablesWithoutYang and len (self .sy .tablesWithOutYang ):
69
- raise Exception ('Config has tables without YANG models' )
61
+ self .__init_sonic_yang ()
70
62
71
63
except Exception as e :
72
64
self .sysLog (doPrint = True , logLevel = syslog .LOG_ERR , msg = str (e ))
73
65
raise Exception ('ConfigMgmt Class creation failed' )
74
66
75
67
return
76
68
69
+ def __init_sonic_yang (self ):
70
+ self .sy = sonic_yang .SonicYang (YANG_DIR , debug = self .DEBUG )
71
+ # load yang models
72
+ self .sy .loadYangModel ()
73
+ # load jIn from config DB or from config DB json file.
74
+ if self .source .lower () == 'configdb' :
75
+ self .readConfigDB ()
76
+ # treat any other source as file input
77
+ else :
78
+ self .readConfigDBJson (self .source )
79
+ # this will crop config, xlate and load.
80
+ self .sy .loadData (self .configdbJsonIn )
81
+
82
+ # Raise if tables without YANG models are not allowed but exist.
83
+ if not self .allowTablesWithoutYang and len (self .sy .tablesWithOutYang ):
84
+ raise Exception ('Config has tables without YANG models' )
85
+
77
86
def __del__ (self ):
78
87
pass
79
88
@@ -213,6 +222,69 @@ def writeConfigDB(self, jDiff):
213
222
214
223
return
215
224
225
+ def add_module (self , yang_module_str ):
226
+ """
227
+ Validate and add new YANG module to the system.
228
+
229
+ Parameters:
230
+ yang_module_str (str): YANG module in string representation.
231
+
232
+ Returns:
233
+ None
234
+ """
235
+
236
+ module_name = self .get_module_name (yang_module_str )
237
+ module_path = os .path .join (YANG_DIR , '{}.yang' .format (module_name ))
238
+ if os .path .exists (module_path ):
239
+ raise Exception ('{} already exists' .format (module_name ))
240
+ with open (module_path , 'w' ) as module_file :
241
+ module_file .write (yang_module_str )
242
+ try :
243
+ self .__init_sonic_yang ()
244
+ except Exception :
245
+ os .remove (module_path )
246
+ raise
247
+
248
+ def remove_module (self , module_name ):
249
+ """
250
+ Remove YANG module from the system and validate.
251
+
252
+ Parameters:
253
+ module_name (str): YANG module name.
254
+
255
+ Returns:
256
+ None
257
+ """
258
+
259
+ module_path = os .path .join (YANG_DIR , '{}.yang' .format (module_name ))
260
+ if not os .path .exists (module_path ):
261
+ return
262
+ temp = tempfile .NamedTemporaryFile (delete = False )
263
+ try :
264
+ shutil .move (module_path , temp .name )
265
+ self .__init_sonic_yang ()
266
+ except Exception :
267
+ shutil .move (temp .name , module_path )
268
+ raise
269
+
270
+ @staticmethod
271
+ def get_module_name (yang_module_str ):
272
+ """
273
+ Read yangs module name from yang_module_str
274
+
275
+ Parameters:
276
+ yang_module_str(str): YANG module string.
277
+
278
+ Returns:
279
+ str: Module name
280
+ """
281
+
282
+ # Instantiate new context since parse_module_mem() loads the module into context.
283
+ sy = sonic_yang .SonicYang (YANG_DIR )
284
+ module = sy .ctx .parse_module_mem (yang_module_str , ly .LYS_IN_YANG )
285
+ return module .name ()
286
+
287
+
216
288
# End of Class ConfigMgmt
217
289
218
290
class ConfigMgmtDPB (ConfigMgmt ):
@@ -417,8 +489,8 @@ def _deletePorts(self, ports=list(), force=False):
417
489
deps .extend (dep )
418
490
419
491
# No further action with no force and deps exist
420
- if force == False and deps :
421
- return configToLoad , deps , False ;
492
+ if not force and deps :
493
+ return configToLoad , deps , False
422
494
423
495
# delets all deps, No topological sort is needed as of now, if deletion
424
496
# of deps fails, return immediately
@@ -436,8 +508,8 @@ def _deletePorts(self, ports=list(), force=False):
436
508
self .sy .deleteNode (str (xPathPort ))
437
509
438
510
# Let`s Validate the tree now
439
- if self .validateConfigData ()== False :
440
- return configToLoad , deps , False ;
511
+ if not self .validateConfigData ():
512
+ return configToLoad , deps , False
441
513
442
514
# All great if we are here, Lets get the diff
443
515
self .configdbJsonOut = self .sy .getData ()
0 commit comments