1
2
3
4
5
6
7
8
9
10
11 __doc__ = """zenmib
12 The zenmib program converts MIBs into python data structures and then
13 (by default) adds the data to the Zenoss DMD. Essentially, zenmib is a
14 wrapper program around the smidump program, whose output (python code) is
15 then executed "inside" the Zope database.
16
17 Overview of terms:
18 SNMP Simple Network Management Protocol
19 A network protocol originally based on UDP which allows a management
20 application (ie SNMP manager) to contact and get information from a
21 device (ie router, computer, network-capable toaster). The software
22 on the device that is capable of understanding SNMP and responding
23 appropriately is called an SNMP agent.
24
25 MIB Management of Information Base
26 A description of what a particular SNMP agent provides and what
27 traps it sends. A MIB is a part of a tree structure based on a root
28 MIB. Since a MIB is a rooted tree, it allows for delegation of areas
29 under the tree to different organizations.
30
31 ASN Abstract Syntax Notation
32 The notation used to construct a MIB.
33
34 OID Object IDentifier
35 A MIB is constructed of unique identifiers
36
37
38 Background information:
39 http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol
40 Overview of SNMP.
41
42 http://www.ibr.cs.tu-bs.de/projects/libsmi/index.html?lang=en
43 The libsmi project is the creator of smidump. There are several
44 interesting sub-projects available.
45
46 http://net-snmp.sourceforge.net/
47 Homepage for Net-SNMP which is used by Zenoss for SNMP management.
48
49 http://www.et.put.poznan.pl/snmp/asn1/asn1.html
50 An overview of Abstract Syntax Notation (ASN), the language in
51 which MIBs are written.
52 """
53
54 import os
55 import os.path
56 import sys
57 import re
58 from subprocess import Popen, PIPE
59 import tempfile
60 import urllib
61 import tarfile
62 import zipfile
63 from urlparse import urlsplit
64 from collections import OrderedDict
65
66 import Globals
67 import transaction
68
69 from Products.ZenUtils.ZCmdBase import ZCmdBase
70 from Products.ZenUtils.Utils import zenPath
71 from zExceptions import BadRequest
72
73
74 CHUNK_SIZE = 50
75
76
78 """
79 A MIB file has the meta-data for a MIB inside of it.
80 """
81 - def __init__(self, fileName, fileContents=""):
82 self.fileName = fileName
83 self.mibs = []
84 self.mibToDeps = {}
85 self.fileContents = self.removeMibComments(fileContents)
86 self.mibDefinitions = self.splitFileToMIBs(self.fileContents)
87 self.mapMibToDependents(self.mibDefinitions)
88
89
90 self.fileContents = ""
91 self.mibDefinitions = ""
92
197
199 """
200 Isolates each MIB definition in fileContents into a separate string
201
202 @param fileContents: the complete contents of a MIB file
203 @type fileContents: string
204 @return: MIB definition strings
205 @rtype: list of strings
206 """
207 if fileContents is None:
208 return []
209
210 DEFINITIONS = re.compile(r'([A-Za-z-0-9]+\s+DEFINITIONS'
211 '(\s+EXPLICIT TAGS|\s+IMPLICIT TAGS|\s+AUTOMATIC TAGS|\s*)'
212 '(\s+EXTENSIBILITY IMPLIED|\s*)\s*::=\s*BEGIN)')
213
214 definitionSpans = []
215 for definitionMatch in DEFINITIONS.finditer(fileContents):
216 definitionSpans.append(list(definitionMatch.span()))
217
218
219 if len(definitionSpans) > 1:
220 definitionSpans[-2][1] = definitionSpans[-1][0]
221
222
223
224 mibDefinitions = []
225 if definitionSpans:
226
227 definitionSpans[-1][1] = len(fileContents)
228 for definitionSpan in definitionSpans:
229 mibDefinitions.append(
230 fileContents[definitionSpan[0]:definitionSpan[1]])
231
232 return mibDefinitions
233
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 IMPORTS = re.compile(r'\sIMPORTS\s.+;', re.DOTALL)
251 DEPENDENCIES = re.compile(
252 r'\sFROM\s+(?P<dependency>[A-Za-z-0-9]+)')
253
254 for definition in mibDefinitions:
255 mibName = re.split(r'([A-Za-z0-9-]+)', definition)[1]
256 dependencies = set()
257 importsMatch = IMPORTS.search(definition)
258 if importsMatch:
259 imports = importsMatch.group()
260 for dependencyMatch in DEPENDENCIES.finditer(imports):
261 dependencies.add(dependencyMatch.group('dependency'))
262 self.mibs.append(mibName)
263 self.mibToDeps[mibName] = dependencies
264
266 """
267 Given an URL, filename or archive (eg zip, tar), extract the files from
268 the package and return a list of filenames.
269 """
270 - def __init__(self, log, downloaddir, extractdir):
271 """
272 Initialize the packagae manager.
273
274 @parameter log: logging object
275 @type log: logging class object
276 @parameter downloaddir: directory name to store downloads
277 @type downloaddir: string
278 @parameter extractdir: directory name to store downloads
279 @type extractdir: string
280 """
281 self.log = log
282 self.downloaddir = downloaddir
283 if self.downloaddir[-1] != '/':
284 self.downloaddir += '/'
285 self.extractdir = extractdir
286 if self.extractdir[-1] != '/':
287 self.extractdir += '/'
288
290 """
291 Download and extract the list of filenames.
292 """
293 try:
294 localFile = self.download(url)
295 except Exception:
296 self.log.error("Problems downloading the file from %s: %s" % (
297 url, sys.exc_info()[1] ) )
298 return []
299 self.log.debug("Will attempt to load %s", localFile)
300 try:
301 return self.processPackage(localFile)
302 except IOError, ex:
303 self.log.error("Unable to process '%s' because: %s",
304 localFile, str(ex))
305 sys.exit(1)
306
308 """
309 Download the package from the given URL, or if it's a filename,
310 return the filename.
311 """
312 urlParts = urlsplit(url)
313 schema = urlParts[0]
314 path = urlParts[2]
315 if not schema:
316 return os.path.abspath(url)
317 file = path.split(os.sep)[-1]
318 os.makedirs(self.downloaddir)
319 downloadFile = os.path.join(self.downloaddir, file)
320 self.log.debug("Downloading to file '%s'", downloadFile)
321 filename, _ = urllib.urlretrieve(url, downloadFile)
322 return filename
323
325 """
326 Figure out what type of file we have and extract out any
327 files and then enumerate the file names.
328 """
329 self.log.debug("Determining file type of %s" % pkgFileName)
330 if zipfile.is_zipfile(pkgFileName):
331 return self.unbundlePackage(pkgFileName, self.unzip)
332
333 elif tarfile.is_tarfile(pkgFileName):
334 return self.unbundlePackage(pkgFileName, self.untar)
335
336 elif os.path.isdir(pkgFileName):
337 return self.processDir(pkgFileName)
338
339 else:
340 return [ os.path.abspath(pkgFileName) ]
341
343 """
344 Unzip the given file into the current directory and return
345 the directory in which files can be loaded.
346 """
347 pkgZip= zipfile.ZipFile(file, 'r')
348 if pkgZip.testzip() != None:
349 self.log.error("File %s is corrupted -- please download again", file)
350 return
351
352 for file in pkgZip.namelist():
353 self.log.debug("Unzipping file/dir %s..." % file)
354 try:
355 if re.search(r'/$', file) != None:
356 os.makedirs(file)
357 else:
358 contents = pkgZip.read(file)
359 try:
360 unzipped = open(file, "w")
361 except IOError:
362 os.makedirs(os.path.dirname(file))
363 unzipped = open(file, "w")
364 unzipped.write(contents)
365 unzipped.close()
366 except (SystemExit, KeyboardInterrupt): raise
367 except:
368 self.log.error("Error in extracting %s because %s" % (
369 file, sys.exc_info()[1] ) )
370 return
371
372 return os.getcwd()
373
375 """
376 Given a tar file, extract from the tar into the current directory.
377 """
378 try:
379 self.log.debug("Extracting files from tar...")
380 pkgTar = tarfile.open(file, 'r')
381 for tarInfo in pkgTar:
382 pkgTar.extract(tarInfo)
383 pkgTar.close()
384 except (SystemExit, KeyboardInterrupt): raise
385 except:
386 self.log.error("Error in un-tarring %s because %s" % ( file,
387 sys.exc_info()[1] ) )
388 return
389 return os.getcwd()
390
392 """
393 Note all of the files in a directory.
394 """
395 fileList = []
396 self.log.debug("Enumerating files in %s", dir)
397 if not os.path.isdir(dir):
398 self.log.debug("%s is not a directory", dir)
399 return []
400 for directoryName, _, fileNames in os.walk(dir):
401 for fileName in fileNames:
402 fileList.append(os.path.join(directoryName, fileName))
403 return fileList
404
406 """
407 Extract the files and then add to the list of files.
408 """
409 self.makeExtractionDir()
410 baseDir = unpackageMethod(package)
411 if baseDir is not None:
412 return self.processDir(baseDir)
413 return []
414
416 """
417 Create an uniquely named extraction directory starting from a base
418 extraction directory.
419 """
420 try:
421 if not os.path.isdir(self.extractdir):
422 os.makedirs(self.extractdir)
423 extractDir = tempfile.mkdtemp(prefix=self.extractdir)
424 except (SystemExit, KeyboardInterrupt): raise
425 except:
426 self.log.error("Error in creating temp dir because %s",
427 sys.exc_info()[1] )
428 sys.exit(1)
429 os.chdir(extractDir)
430
432 """
433 Remove any clutter left over from the installation.
434 """
435 self.cleanupDir(self.downloaddir)
436 self.cleanupDir(self.extractdir)
437
439 for root, dirs, files in os.walk(dirName, topdown=False):
440 if root == os.sep:
441 break
442 for name in files:
443 os.remove(os.path.join(root, name))
444 for name in dirs:
445 try:
446 os.removedirs(os.path.join(root, name))
447 except OSError:
448 pass
449 try:
450 os.removedirs(dirName)
451 except OSError:
452 pass
453
454
456 """
457 Wrapper around the smidump utilities used to convert MIB definitions into
458 python code which is in turn loaded into the DMD tree.
459 """
461 """
462 Scan the MIB file to determine what MIBs are defined in the file and
463 what their dependencies are.
464
465 @param fileName: MIB fileName
466 @type fileName: string
467 @return: dependencyDict, indexDict
468 dependencyDict - a dictionary that associates MIB definitions
469 found in fileName with their dependencies
470 indexDict - a dictionary that associates MIB definitions with their
471 ordinal position within fileName}
472 @rtype:
473 dependencyDict = {mibName: [string list of MIB definition names
474 that mibName is dependant on]}
475 indexDict = {mibname: number}
476 """
477
478 self.log.debug("Processing %s", fileName)
479 file = open(fileName)
480 fileContents = file.read()
481 file.close()
482 return MibFile(fileName, fileContents)
483
485 """
486 Populates the self.mibToMibFile instance object with data.
487 Exit the program if we're missing any files.
488
489 @param importFileNames: fully qualified file names of MIB files to import
490 @type importFileNames: list of strings
491 @param depFileNames: fully qualified file names of all MIB files
492 @type depFileNames: list of strings
493 @return: mibFileObjects of files to import
494 @rtype: MibFile
495 """
496 self.log.debug("Collecting MIB meta-data and creating depedency map.")
497 toImportMibFileObjs = []
498 for fileName in depFileNames.union(importFileNames):
499 try:
500 mibFileObj = self.makeMibFileObj(fileName)
501 except IOError:
502 self.log.error("Couldn't open file %s", fileName)
503 continue
504
505 mibDependencies = mibFileObj.mibToDeps
506 if not mibDependencies:
507 self.log.warn("Unable to parse information from "
508 "%s -- skipping", fileName)
509 continue
510
511 if fileName in importFileNames:
512 toImportMibFileObjs.append(mibFileObj)
513
514 for mibName, dependencies in mibDependencies.items():
515 self.mibToMibFile[mibName] = mibFileObj
516 return toImportMibFileObjs
517
519 """
520 smidump needs to know the list of dependent files for a MIB file in
521 order to properly resolve external references.
522
523 @param mibFileObj: MibFile object
524 @type mibFileObj: MibFile
525 @return: list of dependency fileNames
526 @rtype: list of strings
527 """
528 dependencies = []
529 dependencyFileNames = OrderedDict()
530
531 def dependencySearch(mibName):
532 """
533 Create a list of files required by a MIB definition.
534
535 @param mibName: name of MIB definition
536 @type mibName: string
537 """
538 dependencies.append(mibName)
539 mibFileObj = self.mibToMibFile.get(mibName)
540 if not mibFileObj:
541 self.log.warn("Unable to find a file that defines %s", mibName)
542 return
543
544 dependencyFileNames[mibFileObj.fileName] = None
545 for dependency in mibFileObj.mibToDeps[mibName]:
546 if dependency not in dependencies:
547 dependencySearch(dependency)
548
549 for mibName in mibFileObj.mibs:
550 dependencySearch(mibName)
551
552 if mibFileObj.fileName in dependencyFileNames:
553 del dependencyFileNames[mibFileObj.fileName]
554 names = dependencyFileNames.keys()
555 names.reverse()
556 return names
557
559 """
560 Stores the smidump-generated Python code to a file.
561 """
562 if not os.path.exists(self.options.pythoncodedir):
563 self.options.keeppythoncode = False
564 self.log.warn('The directory %s to store converted MIB file code '
565 'does not exist.' % self.options.pythoncodedir)
566 return
567 try:
568 pythonFileName = os.path.join(self.options.pythoncodedir,
569 os.path.basename(fileName) ) + '.py'
570 pythonFile = open(pythonFileName, 'w')
571 pythonFile.write(pythonCode)
572 pythonFile.close()
573 except (SystemExit, KeyboardInterrupt): raise
574 except:
575 self.log.warn('Could not output converted MIB to %s' %
576 pythonFileName)
577
580 """
581 Use the smidump program to convert a MIB into Python code.
582
583 One major caveat: smidump by default only outputs the last MIB
584 definition in a file. For that matter, it always outputs the last MIB
585 definition in a file whether it is requested or not. Therefore, if
586 there are multiple MIB definitions in a file, all but the last must be
587 explicitly named on the command line. If you name the last, it will
588 come out twice. We don't want that.
589
590 OK, so we need to determine if there are multiple MIB definitions
591 in fileName and then add all but the last to the command line. That
592 works except the resulting python code will create a dictionary
593 for each MIB definition, all of them named MIB. Executing the code is
594 equivalent to running a=1; a=2; a=3. You only wind up with a=3.
595 Therefore, we separate each dictionary definition into its own string
596 and return a list of strings so each one can be executed individually.
597
598 @param fileName: name of the file containing MIB definitions
599 @type fileName: string
600 @param dependencyFileNames: list of fileNames that fileName is
601 dependent on
602 @type dependencyFileNames: list of strings
603 @param mibNamesInFile: names of MIB definitions in file
604 @type mibNamesInFile: list of strings
605 @return: list of dictionaries. Each dictionary containing the contents
606 of a MIB definition. [ {'mibName': MIB data} ]
607 @rtype: list
608 """
609 dumpCommand = ['smidump', '--keep-going', '--format', 'python']
610 for dependencyFileName in dependencyFileNames:
611
612 dumpCommand.append('--preload')
613 dumpCommand.append(dependencyFileName)
614 dumpCommand.append(fileName)
615
616
617
618 if len(mibNamesInFile) > 1:
619 dumpCommand += mibNamesInFile[:-1]
620
621 self.log.debug('Running %s', ' '.join(dumpCommand))
622 sys.stdout.flush()
623 proc = Popen(dumpCommand, stdout=PIPE, stderr=PIPE, close_fds=True)
624
625
626
627
628 pythonCode = ''
629 warnings = ''
630 while proc.poll() is None:
631 output, err = proc.communicate()
632 pythonCode += output
633 warnings += err
634
635 if proc.poll() != 0 or proc.returncode:
636 if warnings.strip():
637 self.log.error(warnings)
638 return None
639
640 if warnings:
641 self.log.debug("Found warnings while trying to import MIB:\n%s" \
642 % warnings)
643
644 if self.options.keeppythoncode:
645 self.savePythonCode(pythonCode, fileName)
646
647 return self.evalPythonToMibs(pythonCode, fileName)
648
650 """
651 Evaluate the code and return an array of MIB dictionaries.
652 """
653 def executePythonCode(pythonCode, name):
654 """
655 Executes the python code generated smidump
656
657 @param pythonCode: Code generated by smidump
658 @type pythonCode: string
659 @return: a dictionary which contains one key: MIB
660 @rtype: dictionary
661 """
662 result = {}
663 try:
664 exec pythonCode in result
665 except (SystemExit, KeyboardInterrupt): raise
666 except:
667 self.log.exception("Unable to import Pythonized-MIB: %s",
668 name)
669 return result.get('MIB', None)
670
671
672
673
674 smiMibDelim = 'MIB = {'
675 mibCodeParts = pythonCode.split(smiMibDelim)
676 mibDicts = []
677 if len(mibCodeParts) > 1:
678 for mibCodePart in mibCodeParts[1:]:
679 mibDict = executePythonCode(smiMibDelim + mibCodePart, name)
680 if mibDict is not None:
681 mibDicts.append(mibDict)
682 else:
683 mibDict = executePythonCode(pythonCode, name)
684 if mibDict is not None:
685 mibDicts = [mibDict]
686
687 return mibDicts
688
690 """
691 Read the file named in the command-line option, evaluate it, and add
692 it to our list of MIBs.
693 """
694 pythonMibs = []
695 for fileName in set(self.options.evalSavedPython):
696 try:
697 pythonCode = open(fileName).read()
698 except IOError:
699 self.log.warn("Unable to open '%s' -- skipping",
700 fileName)
701 continue
702 pythonMibs += self.evalPythonToMibs(pythonCode, fileName)
703
704 self.loadPythonMibs(pythonMibs)
705
706
708 """
709 Populate a dictionary containing the MIB definitions that have been
710 loaded into the DMD Mibs directory
711
712 @param dmdMibDict: maps a MIB definition to the path where
713 it is located with in the DMD.
714 Format:
715 {'mibName': 'DMD path where mibName is stored'}
716 Example: MIB-Dell-10892 is located in the DMD tree at
717 Mibs/SITE/Dell, Directory entry is
718 {'MIB-Dell-10892': '/SITE/Dell'] }
719 @param mibOrganizer: the DMD directory to be searched
720 @type mibOrganizer: MibOrganizer
721 """
722 organizerPath = mibOrganizer.getOrganizerName()
723
724
725
726
727 for mibModule in mibOrganizer.mibs.objectItems():
728 mibName = mibModule[0]
729 if mibName not in dmdMibDict:
730 dmdMibDict[mibName] = organizerPath
731 else:
732 self.log.warn('\nFound two copies of %s:'
733 ' %s and %s' %
734 (mibName, dmdMibDict[mibName],
735 mibOrganizer.getOrganizerName()))
736
737
738 for childOrganizer in mibOrganizer.children():
739 self.getDmdMibDict(dmdMibDict, childOrganizer)
740
742 """
743 Add the different MIB leaves (ie nodes, notifications) into the DMD.
744
745 @paramater leafType: 'nodes', 'notifications'
746 @type leafType: string
747 @paramater pythonMib: dictionary of nodes and notifications
748 @type pythonMib: dictionary
749 @paramater mibModule: class containing functions to load leaves
750 @type mibModule: class
751 @return: number of leaves added
752 @rtype: int
753 """
754 entriesAdded = 0
755 functor = { 'nodes':mibModule.createMibNode,
756 'notifications':mibModule.createMibNotification,
757 }.get(leafType, None)
758 if not functor or leafType not in pythonMib:
759 return entriesAdded
760
761 mibName = pythonMib['moduleName']
762
763 for name, values in pythonMib[leafType].items():
764 try:
765 functor(name, **values)
766 entriesAdded += 1
767 except BadRequest:
768 try:
769 self.log.warn("Unable to add %s id '%s' as this"
770 " name is reserved for use by Zope",
771 leafType, name)
772 newName = '_'.join([name, mibName])
773 self.log.warn("Trying to add %s '%s' as '%s'",
774 leafType, name, newName)
775 functor(newName, **values)
776 entriesAdded += 1
777 self.log.warn("Renamed '%s' to '%s' and added to"
778 " MIB %s", name, newName, leafType)
779 except (SystemExit, KeyboardInterrupt): raise
780 except:
781 self.log.warn("Unable to add %s id '%s' -- skipping",
782 leafType, name)
783 else:
784 if not entriesAdded % CHUNK_SIZE:
785 self.commit("Loaded MIB %s into the DMD" % mibName)
786 self.commit("Loaded MIB %s into the DMD" % mibName)
787 return entriesAdded
788
790 """
791 Attempt to load the MIB definitions in fileName into DMD
792
793 @param fileName: name of the MIB file to be loaded
794 @type fileName: string
795 @return: whether the MIB load was successful or not
796 @rtype: boolean
797 """
798 fileName = mibFileObj.fileName
799 self.log.debug('Attempting to load %s' % fileName)
800
801
802
803 mibNamesInFile = mibFileObj.mibs
804 for mibName in mibNamesInFile:
805 if mibName in dmdMibDict:
806 dmdMibPath = dmdMibDict[mibName]
807 self.log.warn('MIB definition %s found in %s is already '
808 'loaded at %s.' % (mibName, fileName, dmdMibPath))
809
810
811
812 dependencyFileNames = self.getDependencyFileNames(mibFileObj)
813
814
815
816
817 pythonMibs = self.generatePythonFromMib(fileName, dependencyFileNames,
818 mibNamesInFile)
819 if not pythonMibs:
820 return False
821
822 self.loadPythonMibs(pythonMibs)
823 return True
824
826 if not self.options.nocommit:
827 self.log.debug('Committing a batch of objects')
828 trans = transaction.get()
829 trans.setUser('zenmib')
830 trans.note(message)
831 trans.commit()
832 self.syncdb()
833
835 """
836 Walk through the MIB dictionaries and add the MIBs to the DMD.
837 """
838
839 MIB_MOD_ATTS = ('language', 'contact', 'description')
840
841 self.syncdb()
842
843
844 for pythonMib in pythonMibs:
845 mibName = pythonMib['moduleName']
846
847
848
849
850
851 mibModule = self.dmd.Mibs.createMibModule(
852 mibName, self.options.path)
853
854 def gen():
855 for key, val in pythonMib[mibName].iteritems():
856 if key in MIB_MOD_ATTS:
857 yield key, val
858
859 for i, attr in enumerate(gen()):
860 setattr(mibModule, *attr)
861 if not i % CHUNK_SIZE:
862 self.commit("Loaded MIB %s into the DMD" % mibName)
863 self.commit("Loaded MIB %s into the DMD" % mibName)
864
865 nodesAdded = self.addMibEntries('nodes', pythonMib, mibModule)
866 trapsAdded = self.addMibEntries('notifications', pythonMib, mibModule)
867 self.log.info("Parsed %d nodes and %d notifications from %s",
868 nodesAdded, trapsAdded, mibName)
869
870
871 msg = "Loaded MIB %s into the DMD" % mibName
872 self.commit(msg)
873 if not self.options.nocommit:
874 self.log.info(msg)
875
876
878 """
879 Use command line parameters to create a list of files containing MIB
880 definitions that will be used as a reference list for the files being
881 loaded into the DMD
882
883 @return: set of file names
884 @rtype: set
885 """
886 defaultMibDepDirs = [ 'ietf', 'iana', 'irtf', 'tubs', 'site' ]
887 mibDepFileNames = set()
888 for subdir in defaultMibDepDirs:
889 depDir = os.path.join(self.options.mibdepsdir, subdir)
890 mibDepFileNames.update(self.pkgMgr.processDir(depDir))
891 return mibDepFileNames
892
894 """
895 Uses command-line parameters to create a list of files containing MIB
896 definitions that are to be loaded into the DMD
897
898 @return: list of file names that are to be loaded into the DMD
899 @rtype: list
900 """
901 loadFileNames = []
902 if self.args:
903 for fileName in self.args:
904 loadFileNames.extend(self.pkgMgr.downloadExtract(fileName))
905 else:
906 loadFileNames = self.pkgMgr.processDir(self.options.mibsdir)
907
908 if loadFileNames:
909 self.log.debug("Will attempt to load the following files: %s",
910 loadFileNames)
911 else:
912 self.log.error("No MIB files to load!")
913 sys.exit(1)
914
915 return set(loadFileNames)
916
918 """
919 Main loop of the program
920 """
921 if self.options.evalSavedPython:
922 self.evalAddSavedPythonCode()
923 return
924
925
926 if not os.path.exists(self.options.mibsdir):
927 self.log.error("The directory %s doesn't exist!" %
928 self.options.mibsdir )
929 sys.exit(1)
930
931 self.pkgMgr = PackageManager(self.log, self.options.downloaddir,
932 self.options.extractdir)
933 self.mibToMibFile = {}
934
935 requestedFiles = self.getMibsToImport()
936 mibDepFileNames = self.getAllMibDepFileNames()
937 mibFileObjs = self.populateDependencyMap(requestedFiles, mibDepFileNames)
938
939
940 dmdMibDict = {}
941 self.getDmdMibDict(dmdMibDict, self.dmd.Mibs)
942
943
944 self.log.info("Found %d MIBs to import.", len(mibFileObjs))
945 loadedMibFiles = 0
946 for mibFileObj in mibFileObjs:
947 try:
948 if self.loadMibFile(mibFileObj, dmdMibDict):
949 loadedMibFiles += 1
950 except Exception:
951 self.log.exception("Failed to load MIB: %s", mibFileObj.fileName)
952
953 action = "Loaded"
954 if self.options.nocommit:
955 action = "Processed"
956
957 self.log.info("%s %d MIB file(s)" % (action, loadedMibFiles))
958 self.pkgMgr.cleanup()
959
960 sys.exit(0)
961
963 """
964 Command-line options
965 """
966 ZCmdBase.buildOptions(self)
967 self.parser.add_option('--mibsdir',
968 dest='mibsdir', default=zenPath('share/mibs/site'),
969 help="Directory of input MIB files [ default: %default ]")
970 self.parser.add_option('--mibdepsdir',
971 dest='mibdepsdir', default=zenPath('share/mibs'),
972 help="Directory of input MIB files [ default: %default ]")
973 self.parser.add_option('--path',
974 dest='path', default="/",
975 help="Path to load MIB into the DMD")
976 self.parser.add_option('--nocommit', action='store_true',
977 dest='nocommit', default=False,
978 help="Don't commit the MIB to the DMD after loading")
979 self.parser.add_option('--keeppythoncode', action='store_true',
980 dest='keeppythoncode', default=False,
981 help="Don't commit the MIB to the DMD after loading")
982 self.parser.add_option('--pythoncodedir', dest='pythoncodedir',
983 default=tempfile.gettempdir() + "/mib_pythoncode/",
984 help="This is the directory where the converted MIB will be output. " \
985 "[ default: %default ]")
986 self.parser.add_option('--downloaddir', dest='downloaddir',
987 default=tempfile.gettempdir() + "/mib_downloads/",
988 help="This is the directory where the MIB will be downloaded. " \
989 "[ default: %default ]")
990 self.parser.add_option('--extractdir', dest='extractdir',
991 default=tempfile.gettempdir() + "/mib_extract/",
992 help="This is the directory where unzipped MIB files will be stored. " \
993 "[ default: %default ]")
994 self.parser.add_option('--evalSavedPython', dest='evalSavedPython',
995 default=[], action='append',
996 help="Execute the Python code previously generated" \
997 " and saved.")
998
999
1000 if __name__ == '__main__':
1001 zm = ZenMib()
1002 zm.main()
1003