def fetchSource(self, source, fetcherclass=None): """Fetch a related source before proceeding with the currect source. If fetcher is not defined, clone the current class""" if fetcherclass == None: fetcherclass = self.__class__ logger = logging.getLogger("pynt.input") # Check recursion depth if self.recursiondepth >= self.maxrecursiondepth: logger.warning("Maximum recursion depth %d reached for source %s") % (self.maxrecursiondepth, source) return False if source in self.sourcehierarchy: # source 1 fetches other source 2, which fetches source 3, which fetches source 1 logger.info("Loop prevention of source %s: %s" % (source,self.sourcehierarchy[self.sourcehierarchy.index(self.sourcehierarchy[-1]):])) return False if AlreadyFetched(source): logger.info("Skip source %s: it has already been fetched" % source) return False # create new fetcher assert(issubclass(fetcherclass, BaseRecursiveFetcher)) fetcher = fetcherclass(source) # set recursion depth fetcher.recursiondepth = self.recursiondepth + 1 fetcher.maxrecursiondepth = self.maxrecursiondepth # set source parent hierarchy fetcher.sourcehierarchy = self.sourcehierarchy + fetcher.sourcehierarchy # and -finally- fetch fetcher.fetch() return True
def fetchSource(self, source, fetcherclass=None): """Fetch a related source before proceeding with the currect source. If fetcher is not defined, clone the current class""" if fetcherclass == None: fetcherclass = self.__class__ logger = logging.getLogger("pynt.input") # Check recursion depth if self.recursiondepth >= self.maxrecursiondepth: logger.warning("Maximum recursion depth %d reached for source %s" ) % (self.maxrecursiondepth, source) return False if source in self.sourcehierarchy: # source 1 fetches other source 2, which fetches source 3, which fetches source 1 logger.info( "Loop prevention of source %s: %s" % (source, self.sourcehierarchy[self.sourcehierarchy. index(self.sourcehierarchy[-1]):])) return False if AlreadyFetched(source): logger.info("Skip source %s: it has already been fetched" % source) return False # create new fetcher assert (issubclass(fetcherclass, BaseRecursiveFetcher)) fetcher = fetcherclass(source) # set recursion depth fetcher.recursiondepth = self.recursiondepth + 1 fetcher.maxrecursiondepth = self.maxrecursiondepth # set source parent hierarchy fetcher.sourcehierarchy = self.sourcehierarchy + fetcher.sourcehierarchy # and -finally- fetch fetcher.fetch() return True
def DeviceMain(fetcherclass, hostname, argv=None): """ main() function. Parse command line arguments, fetch information from a device, parsing it into a memory structure (specified by pynt.elements) and write that to files in multiple formats """ (options, args) = GetOptions(argv) if len(args) > 0: # override hostname hostname = args[0] pynt.logger.SetLogLevel(options.verbosity) logger = logging.getLogger() identifier = hostname.split(".")[0] errorfile = os.path.join(options.outputdir, "%s-error.log" % identifier) # log of errors serialfile = os.path.join(options.outputdir, "%s-serial.pickle" % identifier) # memory dump debugfile = os.path.join(options.outputdir, "%s-debug.txt" % identifier) # human readable memory dump ndl24file = os.path.join(options.outputdir, "%s-config.rdf" % identifier) # All information in latest NDL staticfile = os.path.join( options.outputdir, "%s-interfaces.rdf" % identifier ) # Static interface configuration in NDL (no configuration info) ndl22file = os.path.join( options.outputdir, "%s-v22.rdf" % identifier) # NDL v2.2 deprecated version with all info devdotfile = os.path.join(options.outputdir, "%s-device.dot" % identifier) # Graph with vertices for devices ifdotfile = os.path.join(options.outputdir, "%s-interface.dot" % identifier) # Graph with vertices for interfaces iologfile = options.iologfile # file to log raw I/O communications with devices passwdfile = options.configfile # file with usernames and passwords errorlog = pynt.logger.Logger(errorfile, verbosity=options.verbosity) try: if options.simulate in ["pickle", "memory"]: if options.inputfilename: fetcher = pynt.input.serial.SerialInput(options.inputfilename) else: fetcher = pynt.input.serial.SerialInput(serialfile) else: namespaceuri = "http://%s#" % hostname identifier = hostname.split(".")[0].capitalize() fetcher = fetcherclass(hostname, nsuri=namespaceuri, identifier=identifier) if options.simulate in ["command"]: logger.log(25, "Performing simulated query on %s" % hostname) if options.inputfilename: fetcher.setSourceFile( options.inputfilename, hostname=hostname) # hostname is used to set prompt else: fetcher.setSourceFile( iologfile, hostname=hostname) # hostname is used to set prompt else: logger.log(25, "Performing live query on %s" % hostname) fetcher.setSourceHost(hostname, port=options.port) userpwd = pynt.input.usernames.GetLoginSettings( hostname, options.username, options.password, passwdfile) fetcher.io.setLoginCredentials(**userpwd) if iologfile: fetcher.io.setLogFile(iologfile) # fetches data from device and returns object structure. # The subject is something that can be passed on to BaseOutput.output(); # Typically a Device object or namespace. subject = fetcher.getSubject() if not options.simulate: out = pynt.output.serial.SerialOutput(serialfile) out.output(subject) out = pynt.output.debug.DebugOutput(debugfile) out.output() out = pynt.output.manualrdf.RDFOutput(ndl24file) out.setMetaData( "description", 'Configuration of the %s switch at Netherlight. This file is semi-dynamically generated by a cron job that logs in the devices and retrieves all information. You should expect this data to be stale for about 5 minutes. If you really need real-time data, then don\'t use NDL, but another mechanism (e.g. a routing protocol).' % subject.getName()) out.setMetaData("publicationdate", '2007-01-31') out.output(subject) #out.setOutputFile(None) # set to STDOUT #out.output(force10) out.setOutputFile(staticfile) out.setPrintConfigured(False) out.setMetaData( "description", 'Configuration of the %s switch at Netherlight. This file is automatically generated by a script that logs in the devices and all static information. This file does NOT contain dynamic information.' % subject.getName()) out.setMetaData("publicationdate", '2007-01-31') out.output(subject) out = pynt.output.manualrdf.RDFv22Output(ndl22file) out.output(subject) out = pynt.output.dot.DeviceGraphOutput(devdotfile) out.output(subject) out = pynt.output.dot.InterfaceGraphOutput(ifdotfile) out.output(subject) except: # *any* kind of exception, including user-interupts, etc. # the write functions are atomic, so those will be fine when an exception occurs errorlog.logException() (exceptionclass, exception, traceback) = sys.exc_info() logger.exception("") # We check if an error occured # if so, we do nothing, and keep the existing files. Those should still be valid. # However, if we previously also had errors, this is probably more fundamental. # In that case, we replace the -cache file with the -static file, effectively # removing all dynamic data from the RDF files. if errorlog.getCurErrorCount() and errorlog.getPrevErrorCount(): logger.info("Two errors in a row. Overwriting %s with %s" % (ndl24file, staticfile)) try: pynt.output.CopyFile(staticfile, ndl24file) except IOError: pass
def processDevice(self, hostname): try: identifier = self.devices_conf.get(hostname, "identifier") except: identifier = None if not identifier: identifier = hostname pynt.logger.SetLogLevel(self.options.verbosity) logger = logging.getLogger() errorfile = os.path.join(self.options.outputdir, "%s-error.log" % identifier) # log of errors serialfile = os.path.join(self.options.outputdir, "%s-serial.pickle" % identifier) # memory dump debugfile = os.path.join(self.options.outputdir, "%s-debug.txt" % identifier) # human readable memory dump ndl24file = os.path.join(self.options.outputdir, "%s-config.rdf" % identifier) # All information in latest NDL staticfile = os.path.join( self.options.outputdir, "%s-interfaces.rdf" % identifier ) # Static interface configuration in NDL (no configuration info) devdotfile = os.path.join( self.options.outputdir, "%s-device.dot" % identifier ) # Graph with vertices for devices ifdotfile = os.path.join( self.options.outputdir, "%s-interface.dot" % identifier ) # Graph with vertices for interfaces iologfile = self.options.iologfile # file to log raw I/O communications with devices passwdfile = self.options.configfile # file with usernames and passwords errorlog = pynt.logger.Logger(errorfile, verbosity=self.options.verbosity) inputfilename = os.path.join(self.options.inputdir, hostname) try: if self.options.simulate in ["pickle", "memory"]: if inputfilename: fetcher = pynt.input.serial.SerialInput(inputfilename) else: fetcher = pynt.input.serial.SerialInput(serialfile) else: fetcher = self.fetcherclass(hostname, identifier=identifier) if self.options.simulate in ["command"]: logger.log(25, "Performing simulated query on %s" % hostname) if inputfilename: fetcher.setSourceFile(inputfilename) else: fetcher.setSourceFile(iologfile) else: logger.log(25, "Performing live query on %s" % hostname) fetcher.setSourceHost(hostname, port=self.options.port) userpwd = pynt.input.usernames.GetLoginSettings( hostname, self.options.username, self.options.password, passwdfile ) fetcher.io.setLoginCredentials(**userpwd) if iologfile: fetcher.io.setLogFile(iologfile) # fetches data from device and returns object structure. # The subject is something that can be passed on to BaseOutput.output(); # Typically a Device object or namespace. subject = fetcher.getSubject() # if not self.options.simulate: # out = pynt.output.serial.SerialOutput(serialfile) # out.output(subject) # # out = pynt.output.debug.DebugOutput(debugfile) # out.output(subject) # # out = pynt.output.manualrdf.RDFOutput(ndl24file) # out.setMetaData("description", 'Configuration of the %s' % subject.getName()) # out.output(subject) # # out.setOutputFile(staticfile) # out.setPrintConfigured(False) # out.setMetaData("description", 'Configuration of the %s' % subject.getName()) # out.output(subject) # # out = pynt.output.dot.DeviceGraphOutput(devdotfile) # out.output(subject) # # out = pynt.output.dot.InterfaceGraphOutput(ifdotfile) # out.output(subject) except: # *any* kind of exception, including user-interupts, etc. # the write functions are atomic, so those will be fine when an exception occurs errorlog.logException() (exceptionclass, exception, traceback) = sys.exc_info() logger.exception("") # We check if an error occurred # if so, we do nothing, and keep the existing files. Those should still be valid. # However, if we previously also had errors, this is probably more fundamental. # In that case, we replace the -cache file with the -static file, effectively # removing all dynamic data from the RDF files. if errorlog.getCurErrorCount() and errorlog.getPrevErrorCount(): logger.info("Two errors in a row. Overwriting %s with %s" % (ndl24file, staticfile)) try: pynt.output.CopyFile(staticfile, ndl24file) except IOError: pass
def DeviceMain(fetcherclass, hostname, argv=None): """ main() function. Parse command line arguments, fetch information from a device, parsing it into a memory structure (specified by pynt.elements) and write that to files in multiple formats """ (options, args) = GetOptions(argv) if len(args) > 0: # override hostname hostname = args[0] pynt.logger.SetLogLevel(options.verbosity) logger = logging.getLogger() identifier = hostname.split(".")[0] errorfile = os.path.join(options.outputdir, "%s-error.log" % identifier) # log of errors serialfile = os.path.join(options.outputdir, "%s-serial.pickle" % identifier) # memory dump debugfile = os.path.join(options.outputdir, "%s-debug.txt" % identifier) # human readable memory dump ndl24file = os.path.join(options.outputdir, "%s-config.rdf" % identifier) # All information in latest NDL staticfile = os.path.join(options.outputdir, "%s-interfaces.rdf" % identifier) # Static interface configuration in NDL (no configuration info) ndl22file = os.path.join(options.outputdir, "%s-v22.rdf" % identifier) # NDL v2.2 deprecated version with all info devdotfile = os.path.join(options.outputdir, "%s-device.dot" % identifier) # Graph with vertices for devices ifdotfile = os.path.join(options.outputdir, "%s-interface.dot" % identifier) # Graph with vertices for interfaces iologfile = options.iologfile # file to log raw I/O communications with devices passwdfile = options.configfile # file with usernames and passwords errorlog = pynt.logger.Logger(errorfile, verbosity=options.verbosity) try: if options.simulate in ["pickle", "memory"]: if options.inputfilename: fetcher = pynt.input.serial.SerialInput(options.inputfilename) else: fetcher = pynt.input.serial.SerialInput(serialfile) else: namespaceuri = "http://%s#" % hostname identifier = hostname.split(".")[0].capitalize() fetcher = fetcherclass(hostname, nsuri=namespaceuri, identifier=identifier) if options.simulate in ["command"]: logger.log(25, "Performing simulated query on %s" % hostname) if options.inputfilename: fetcher.setSourceFile(options.inputfilename, hostname=hostname) # hostname is used to set prompt else: fetcher.setSourceFile(iologfile, hostname=hostname) # hostname is used to set prompt else: logger.log(25, "Performing live query on %s" % hostname) fetcher.setSourceHost(hostname, port=options.port) userpwd = pynt.input.usernames.GetLoginSettings(hostname, options.username, options.password, passwdfile) fetcher.io.setLoginCredentials(**userpwd) if iologfile: fetcher.io.setLogFile(iologfile) # fetches data from device and returns object structure. # The subject is something that can be passed on to BaseOutput.output(); # Typically a Device object or namespace. subject = fetcher.getSubject() if not options.simulate: out = pynt.output.serial.SerialOutput(serialfile) out.output(subject) out = pynt.output.debug.DebugOutput(debugfile) out.output() out = pynt.output.manualrdf.RDFOutput(ndl24file) out.setMetaData("description", 'Configuration of the %s switch at Netherlight. This file is semi-dynamically generated by a cron job that logs in the devices and retrieves all information. You should expect this data to be stale for about 5 minutes. If you really need real-time data, then don\'t use NDL, but another mechanism (e.g. a routing protocol).' % subject.getName()) out.setMetaData("publicationdate", '2007-01-31') out.output(subject) #out.setOutputFile(None) # set to STDOUT #out.output(force10) out.setOutputFile(staticfile) out.setPrintConfigured(False) out.setMetaData("description", 'Configuration of the %s switch at Netherlight. This file is automatically generated by a script that logs in the devices and all static information. This file does NOT contain dynamic information.' % subject.getName()) out.setMetaData("publicationdate", '2007-01-31') out.output(subject) out = pynt.output.manualrdf.RDFv22Output(ndl22file) out.output(subject) out = pynt.output.dot.DeviceGraphOutput(devdotfile) out.output(subject) out = pynt.output.dot.InterfaceGraphOutput(ifdotfile) out.output(subject) except: # *any* kind of exception, including user-interupts, etc. # the write functions are atomic, so those will be fine when an exception occurs errorlog.logException() (exceptionclass, exception, traceback) = sys.exc_info() logger.exception("") # We check if an error occured # if so, we do nothing, and keep the existing files. Those should still be valid. # However, if we previously also had errors, this is probably more fundamental. # In that case, we replace the -cache file with the -static file, effectively # removing all dynamic data from the RDF files. if errorlog.getCurErrorCount() and errorlog.getPrevErrorCount(): logger.info("Two errors in a row. Overwriting %s with %s" % (ndl24file, staticfile)) try: pynt.output.CopyFile(staticfile, ndl24file) except IOError: pass
def attachSource(self, source, subject): """Add a related (seeAlso) source to a subject. The given URL will NOT be fetched automatically. Instead, it will be added to an object.""" logger = logging.getLogger("pynt.input") logger.info("Add source %s to %s" % (source, subject)) subject.attachSource(source)