def __init__(self, yin_path, yin_file, model_dir, verbose=False): """ YANG model initializer :param: yin_path (string) Directory path to the location of the YIN file (and python file) :param: yin_file (string) Name of the YIN file generated by 'pyang'. The name of the code-generated python file is extracted from the YIN file (module name). :param: model_dir (string) Directory name of where the model is. Used in constructing the import statement. :param: verbose (integer) Flag indicating if verbose output is to be presented """ self._yin = YINFile(os.path.join(yin_path, yin_file), verbose) self._verbose = verbose # Import the model self._import_models(model_dir)
class YangModel: """ This class wraps the yang model and helps to hide some of the ugly details needed to get this code-generated RESTCONF server working. """ _extmethods = None _yang_class = None _yin = None def __init__(self, yin_path, yin_file, model_dir, verbose=False): """ YANG model initializer :param: yin_path (string) Directory path to the location of the YIN file (and python file) :param: yin_file (string) Name of the YIN file generated by 'pyang'. The name of the code-generated python file is extracted from the YIN file (module name). :param: model_dir (string) Directory name of where the model is. Used in constructing the import statement. :param: verbose (integer) Flag indicating if verbose output is to be presented """ self._yin = YINFile(os.path.join(yin_path, yin_file), verbose) self._verbose = verbose # Import the model self._import_models(model_dir) def __str__(self): return "YangModel: %s" % self.name @property def name(self): """ Get the module name. @:returns: (string) YANG Model name """ return self._yin.module_name @property def package_name(self): """ Get the code-generated package name. The pyangbind package will replace hypens and spaces with underscores. @:returns: (string) Python code-generated module name """ return self.name.replace("-", "_").replace(" ", "_") def _import_models(self, model_dir): """ This method is responsible for accessing the code-generated class and building up a model that can be used to provide a simple RESTCONF server implementation of the model. :param: model_dir (string) Base directory name of where the model is. """ package = model_dir module = self.package_name _class = self.package_name try: if self._verbose > 0: print "Dynamic import -> from %s.%s import %s" % (package, module, _class) yang_module = __import__("%s.%s" % (package, module), fromlist=[_class]) yang_class = getattr(yang_module, _class) if self._verbose > 0: print "YANG class initially imported: %s" % yang_class # Construct the extmethods for all appropriate nodes in the class and then # reconstruct the class if needed with these method self._extmethods = self._yin.get_extmethods(yang_class().get()) # Now reconstruct the class and pass in these methods if self._extmethods is not None and len(self._extmethods) > 0: self._yang_class = getattr(yang_module, _class)(extmethods=self._extmethods) else: self._yang_class = yang_class except ImportError: print "Import Error while attempting to import class %s from %s.%s" % (_class, package, module) # Instantiate the models the first time so we can generate all the paths within # them so we can create extension methods that provide for RESTCONF required # methods ########################################################################### def _get_extmethods(self, element, path_base=""): """ A recursive function to convert a yang model into a extmethods dictionary :param element: (list of YANGDynClass) Child elements of a the model instance :param path_base: (dict) Existing dictionary of elements :return: (dict) A Pyangbind compatible extmethods dictionary """ extmethods = {} if element is None: return extmethods if isinstance(element, dict): # print '%s is a dictionary of length %d' % (element, len(element)) # yang_name = getattr(element, "yang_name") if hasattr(element, "yang_name") else None # is_container = hasattr(element, "get") for key, value in element.items(): path = path_base + "/" + key config = True yang_name = getattr(value, "yang_name") if hasattr(element, "yang_name") else None is_container = hasattr(value, "get") try: if value._is_leaf: # Protected, but I really need to know config = value.flags.writeable except AttributeError: pass # Was another dictionary item or did not have a writeable flag # Add this to our path extmethods[path] = config extmethods.update(self._get_extmethods(value, path_base=path)) return extmethods def _fix_extmethods(self, extmethods): """ Walk through the methods and fix up any parents that have no children that are writeable. """ # TODO: Need to implement return extmethods
class YangModel: """ This class wraps the yang model and helps to hide some of the ugly details needed to get this code-generated RESTCONF server working. """ _extmethods = None _yang_class = None _yin = None def __init__(self, yin_path, yin_file, model_dir, verbose=False): """ YANG model initializer :param: yin_path (string) Directory path to the location of the YIN file (and python file) :param: yin_file (string) Name of the YIN file generated by 'pyang'. The name of the code-generated python file is extracted from the YIN file (module name). :param: model_dir (string) Directory name of where the model is. Used in constructing the import statement. :param: verbose (integer) Flag indicating if verbose output is to be presented """ self._yin = YINFile(os.path.join(yin_path, yin_file), verbose) self._verbose = verbose # Import the model self._import_models(model_dir) def __str__(self): return 'YangModel: %s' % self.name @property def name(self): """ Get the module name. @:returns: (string) YANG Model name """ return self._yin.module_name @property def package_name(self): """ Get the code-generated package name. The pyangbind package will replace hypens and spaces with underscores. @:returns: (string) Python code-generated module name """ return self.name.replace('-', '_').replace(' ', '_') def _import_models(self, model_dir): """ This method is responsible for accessing the code-generated class and building up a model that can be used to provide a simple RESTCONF server implementation of the model. :param: model_dir (string) Base directory name of where the model is. """ package = model_dir module = self.package_name _class = self.package_name try: if self._verbose > 0: print 'Dynamic import -> from %s.%s import %s' % ( package, module, _class) yang_module = __import__('%s.%s' % (package, module), fromlist=[_class]) yang_class = getattr(yang_module, _class) if self._verbose > 0: print 'YANG class initially imported: %s' % yang_class # Construct the extmethods for all appropriate nodes in the class and then # reconstruct the class if needed with these method self._extmethods = self._yin.get_extmethods(yang_class().get()) # Now reconstruct the class and pass in these methods if self._extmethods is not None and len(self._extmethods) > 0: self._yang_class = getattr(yang_module, _class)(extmethods=self._extmethods) else: self._yang_class = yang_class except ImportError: print 'Import Error while attempting to import class %s from %s.%s' % ( _class, package, module) # Instantiate the models the first time so we can generate all the paths within # them so we can create extension methods that provide for RESTCONF required # methods ########################################################################### def _get_extmethods(self, element, path_base=''): """ A recursive function to convert a yang model into a extmethods dictionary :param element: (list of YANGDynClass) Child elements of a the model instance :param path_base: (dict) Existing dictionary of elements :return: (dict) A Pyangbind compatible extmethods dictionary """ extmethods = {} if element is None: return extmethods if isinstance(element, dict): # print '%s is a dictionary of length %d' % (element, len(element)) # yang_name = getattr(element, "yang_name") if hasattr(element, "yang_name") else None # is_container = hasattr(element, "get") for key, value in element.items(): path = path_base + '/' + key config = True yang_name = getattr(value, "yang_name") if hasattr( element, "yang_name") else None is_container = hasattr(value, "get") try: if value._is_leaf: # Protected, but I really need to know config = value.flags.writeable except AttributeError: pass # Was another dictionary item or did not have a writeable flag # Add this to our path extmethods[path] = config extmethods.update(self._get_extmethods(value, path_base=path)) return extmethods def _fix_extmethods(self, extmethods): """ Walk through the methods and fix up any parents that have no children that are writeable. """ # TODO: Need to implement return extmethods