使用IPython下的Net-SNMP来管理类UNIX系统的教程
引言
对于简单网络管理协议(SNMP),大多数系统管理员都具有一定的使用经验,或者至少听说过它。如果您正在一个数据中心工作,那么您每天都可能采用某种方式与SNMP进行交互。有许多给人印象深刻的、同等规模的网络管理系统(NMS)或者网络监视系统使用了SNMP监视,但本文并不打算介绍这些系统。本文主要涉及的是通过Python?语言来研究SNMP,并亲自编写相关的代码。
一位朋友最近告诉我,有时候遇到的情况就像:只是希望沿着街道一路走到奶奶家,而不需要乘坐像SaturnV火箭一样飞快。有许多任务,如果利用或者配置大规模的NMS,就好像是一个SaturnV火箭,在填满液氧罐之前,先尝试一下使用Python,那么您将得到更好的服务。了解如何编写灵活的Python代码与SNMP进行交互,这可能是系统管理员可以获得的、最有趣且最高效的技能之一。尽管SNMP的设置和使用非常复杂,但本文中所讨论的内容将使它变得非常有趣。
安装和配置Net-SNMP
要学习本文中的内容,您需要在您的*nix计算机中安装最新的Python(即Python2.3或者更高版本)。在撰写本文时,Python2.5.1是Python的最新版本。您还需要IPython,以便以交互的方式使用带Python绑定的Net-SNMP库。Net-SNMP团队对各种操作系统中的支持进行了详细测试,具体包括AIX?、HP-UX?、GNU/Linux?分发版(如RedHat)、Windows?,甚至OSX?。
安装IPython是一项非常简单的工作。一个很好的选择是使用EasyInstall来管理Python包。通过运行ez_setup.py脚本,您可以很容易地安装任何Python包。例如,您只需要键入以下命令:
easy_installipython
其他可选的安装方式包括,使用您最喜欢的包管理系统、或者只需下载IPython并键入以下命令:
pythonsetup.pyinstall
请注意,干线(trunk)指的是版本控制系统中的根路径,其中保存了最近的代码副本。此外,干线还常常表示一个子版本和版本控制系统。有关更详细的内容,请参见参考资料部分中的子版本链接。
要学习本文中的内容,您需要确保您的客户端计算机、或者运行所有代码的计算机都安装了NET-SNMPVersion5.4.x或者更高版本,因为从这个源代码版本开始,包括了Python绑定。在大多数情况下,绑定的安装需要对源文件进行编译;然而,也可以使用RedHatPackageManagers(RPM)。如果你有兴趣和时间,那么可以从Net-SNMPWeb站点查看一下它的最新版本。
有许多编译选项可供使用,但主要的任务是对NET-SNMP进行正确编译,然后运行Python目录中的、独立的Python安装程序。另一个需要注意的问题是,当您进行编译并运行./configure的时候,它将运行本地计算机(正在编译代理的计算机)的配置脚本。您不应该使用该配置脚本,对于本文而言,您只需要创建一个简单的配置脚本。
对/etc/snmp/snmpd.conf中所存储的配置文件进行备份,并构建下面这个非常基本的配置:
syslocation"MyLocalMachine" syscontactme@localhost.com rocommunitypublic
保存它,并重新启动snmpd守护进程。在大多数*nix系统中,可以使用/etc/init.d/snmpdrestart来完成这项工作。
除非在不得已的情况下,否则最好不要对处于活动开发阶段的版本进行编译,因为这样做,您将需要自己动手修复有问题的代码。在CentOS5或者RedHatEnterpriseLinux5(RHEL5)中,您可以下载最新的、稳定的源文件RPM(在撰写本文之时,是5.4.1版本)。请注意,您还需要使用Python源文件来构建绑定。因此,如果您正在使用一台基于RedHat的计算机,那么请确保为特定的*nix操作系统安装了python-dev(或者其等价物)和PythonHeader文件。如果您在从源文件构建RPM的过程中,需要任何帮助的话,请参考官方的RedHat文档。从源文件构建包可能是一个非常复杂的主题,并且已经超出了本文的范围。如果您在使用Python绑定的时候遇到了麻烦,那么您应该在Net-SNMP邮件列表中请求帮助。
对代码进行分析
还等什么呢?假设您已经安装了Python绑定和IPython。现在,您已经做好了使用IPython的准备,并开始相关的工作。尽管在某些时候,您可能还需要浏览IPython文档。JeffRush是当前的PythonAdvocacyCoordinator,他为IPython提供了一些非常好的屏幕录像内容。好的,让我们开始进行编码。
让我们进行一次简单的查询,以便通过使用计算机的对象标识符(OID)值sysDescr来标识一台计算机。通过键入ipython启动IPython,然后执行这个交互式会话:
清单1.IPython示例
In[1]:importnetsnmp In[2]:oid=netsnmp.Varbind('sysDescr') In[3]:result=netsnmp.snmpwalk(oid, ...:Version=2, ...:DestHost="localhost", ...:Community="public") In[4]:result=netsnmp.snmpwalk(oid, Version=2, DestHost="localhost", Community="public") In[16]:result Out[16]:('Linuxlocalhost2.6.18-8.1.14.el5#1SMPThuSep27 18:58:54EDT2007i686',)
请注意,您所得到的result值与这里所显示的result值是不同的。如果您已经遵循了上面清单1中所显示的配置,那么所有其他的内容都应该是可用的。如果您对SNMP比较熟悉,那么您可能马上就能够明白这些内容的实际作用。
使用IPython来测试SNMP代码片段的好处之一是,它就好像是一个普通的Shell,并且许多基本的、交互式Shell的概念“都可以起作用”,但需要说明的是,它们是以python方式进行工作的。编写SNMP代码可能是一项非常单调乏味的活动,但是通过IPython来使用Net-SNMP库将使其变得非常有趣。
正如您所看到的,要将结果转换为Python数据类型,这项任务是非常简单的。这就是为什么IPython和Net-SNMP可以很好地在一起工作的原因。现在,对于编写自定义脚本来说,只需要以交互方式分析OID的组合以进行查询。在理想的情况下,需要运行一个大规模的、易于配置的NMS设置脚本,自动地将新的计算机集成到网络中。
当然,并不存在这种理想的情况,您需要了解如何将一些好的SNMP代码组合到一起,对于一名系统管理员来说,这是非常有用的。下面给出一个示例情况,假设您刚刚将一个高速DDR转换为正在运行UbuntuLinux的2TBRAID0服务器,因为您必须在一个小时的时间内解决问题,所以您不得不这样做。
现在,您遇到了很大的麻烦,并且您只有几分钟的时间来监视具体的问题,以了解是否需要开始发送简历、或者是否应该开始准备讲话并请求升职。让我们使用IPython中的编辑功能来编写脚本,并将它保存到文件中,然后在不离开IPython的情况下,在一个会话中运行它:edsnmpinput.py
清单2.IPython模块的创建
importnetsnmp classsnmpSessionBaseClass(object): """ABaseClassForaSNMPSession""" def__init__(self, oid="sysDescr", Version=2, DestHost="localhost", Community="public"): self.oid=oid self.Version=Version self.DestHost=DestHost self.Community=Community defquery(self): """CreatesSNMPquerysession""" try: result=netsnmp.snmpwalk(self.oid, Version=self.Version, DestHost=self.DestHost, Community=self.Community) except: importsys printsys.exc_info() result=None returnresult
对IPython进行自定义以使用正确的编辑器
通过编辑$HOME/.ipython/ipythonrc,您可以对Ipython进行自定义。首先需要进行自定义的内容之一是%edit命令,可以通过键入ed来调用该命令。在缺省情况下,它被设置为使用vi,但是您可以更改它,以便使用其他编辑器,包括Emacs。关于如何更改您的环境,本文给出了相应的指导。您还可以使用下面的命令来启动Ipython,以便以硬编码的形式指定使用某个特定的编辑器:ipython-editor=vim。
继续执行,将下面的代码剪切并粘贴到您刚刚创建的文件中。当保存这个文件时,IPython将自动地运行它,并将该类放置到您环境中相应的模块中。如果您键入who,那么您将看到与以下所示类似的内容:
In[2]:who netsnmpsnmpSessionBaseClass
这项操作的功能非常强大,因为您可以获得使用您最喜欢的文本编辑器(也许是Vim或者Emacs)的所有优点,然后在交互的IPythonShell会话中立即使用这些代码。请注意,如果您已经编写了一个模块,那么您还可以简单地键入并运行它,以获得相同的结果。执行和运行IPython中的模块,这就相当于运行其中的代码,并将其放入到IPython环境中。
以迭代的方式进行编码
现在通过使用IPython,可以将PythonShell、UNIXShell和您最喜欢的文本编辑器的最佳特性组合到一起。在与像SNMP库这样非常复杂的对象进行交互时,您需要使用可以获得的所有帮助,而在这个示例中,真正地展示了IPython的强大功能。
您可以动态地编写一些模块,并且您可以在稍后对其进行测试和使用。IPython可以与任何编程风格很好地融合在一起,包括测试驱动的开发(TDD)或者测试增强的开发(TED)。为了证明这种便利性,让我们转到您刚刚编写的模块。
既然已经有一个面向对象的SNMP接口,那么您就可以开始向本地计算机进行询问:
清单3.IPython迭代式编码
In[1]:runsnmpinput In[2]:who netsnmpsnmpSessionBaseClass In[3]:s=snmpSessionBaseClass() In[4]:s.query() Out[4]:('Linuxlocalhost2.6.18-8.1.14.el5#1SMPThuSep2718:58:54EDT2007i686',) In[5]:result=s.query() In[6]:len(result) Out[6]:1
通过使用这个模块获得相关的结果,这是非常容易的,但是您基本上只是在运行一个硬编码脚本,因此需要更改OID对象的值,以遍历系统子树:
清单4.更改OID对象的值
In[7]:s.oid Out[7]:'sysDescr' In[8]:s.oid=".1.3.6.1.2.1.1" In[9]:result=s.query() In[10]:printresult ('Linuxlocalhost2.6.18-8.1.14.el5#1SMPThuSep2718:58:54EDT2007i686', '.1.3.6.1.4.1.8072.3.2.10','121219','me@localhost.com', 'localhost','"MyLocal Machine"','0','.1.3.6.1.6.3.10.3.1.1','.1.3.6.1.6.3.11.3.1.1', '.1.3.6.1.6.3.15.2.1.1', '.1.3.6.1.6.3.1','.1.3.6.1.2.1.49','.1.3.6.1.2.1.4','.1.3.6.1.2.1.50', '.1.3.6.1.6.3.16.2.2.1', 'TheSNMPManagementArchitectureMIB.','TheMIBforMessageProcessingand Dispatching.','ThemanagementinformationdefinitionsfortheSNMP User-basedSecurityModel.','TheMIBmoduleforSNMPv2entities','The MIBmoduleformanagingTCPimplementations','TheMIBmodulefor managingIPandICMPimplementations','TheMIBmoduleformanaging UDPimplementations','View-basedAccess ControlModelforSNMP.','0','0','0','0','0','0','0','0')
正如您可以看到的,要使用这个模块并开始分析整个网络(一次一台计算机),这项任务是非常容易的。请仔细地进行分析,并确定需要在网络中进行查询的内容。这是IPython的另一个有趣的特性,有必要对其进行深入研究。IPython具有一个令人难以置信的特性,即允许您将Python代码片段作为后台进程来运行。幸运的是,进行这项操作非常简单。让我们再次运行相同的查询,但这一次将其作为后台进程运行(请参见清单5)。
清单5.IPython迭代式编码示例——后台进程
In[11]:bgs.query() Startingjob#0inaseparatethread. In[12]:jobs[0].status Out[12]:'Completed' In[16]:jobs[0].result Out[16]: ('Linuxlocalhost2.6.18-8.1.14.el5#1SMPThuSep2718:58:54EDT2007i686', '.1.3.6.1.4.1.8072.3.2.10','121219','me@localhost.com','localhost','"MyLocal Machine"','0','.1.3.6.1.6.3.10.3.1.1','.1.3.6.1.6.3.11.3.1.1', '.1.3.6.1.6.3.15.2.1.1','.1.3.6.1.6.3.1','.1.3.6.1.2.1.49', '.1.3.6.1.2.1.4','.1.3.6.1.2.1.50','.1.3.6.1.6.3.16.2.2.1', 'TheSNMPManagementArchitectureMIB.','TheMIBforMessageProcessingand Dispatching.','ThemanagementinformationdefinitionsfortheSNMPUser-based SecurityModel.','TheMIBmoduleforSNMPv2entities','TheMIBmodulefor managingTCPimplementations','TheMIBmoduleformanagingIPandICMP implementations','TheMIBmoduleformanagingUDPimplementations', 'View-basedAccessControlModelforSNMP.','0','0','0','0','0','0','0','0')
令人激动的是,IPython中的后台线程是一种非常有价值的功能,但它只能与支持异步线程的库一起工作。不幸的是,Net-SNMP是同步的。如果您对这一点感兴趣,那么可以通过将s.oid值更改为.iso来进行测试。在查询完成之前,您应该可以注意到,IPython解释器发生了“阻塞”或者“挂起”。尽管只是一个警告,但对整个.iso树的SNMP遍历可能会花费较长的时间,因此您可能会接受我的观点。
当然,还有另一种解决方案。您可以使用Python所提供的众多处理库中的其中一个,为这个阻塞的进程派生新的进程。PythonCheeseShop提供了一些第三方库。如果您正在使用easy_install,那么要安装一个包(如ParallelPython)并使用Net-SNMP来测试这个库,将是相当简单的,因此这将由您来决定。
easy_installhttp://www.parallelpython.com/downloads/pp/pp-1.5.zip
这里要展示的最后一个特性是,在IPythonShell中运行单元测试。在对模块进行更改时,需要频繁地运行单元测试,而这也是非常容易的。您需要添加一个标记以运行run-e,这样一来,您就可以在IPythonShell中避免回溯到单元测试模块。您可以在本文所附带的源文件中下载这个单元测试。
请注意,IPython0.8.2还有一个新的文档测试特性,它允许您在IPython中生成文档测试。文档测试是Python的一个很好的特性,因为与其他特性一起,它提供了一种为API创建可测试文档的方法。下面给出了一个示例,以说明如何在IPython中为我们的模块运行doctest:
清单6.以doctest模式运行IPython
In[5]:%doctest_mode ***Pastingofcodewith">>>"or"..."hasbeenenabled. Exceptionreportingmode:Plain Doctestmodeis:ON >>>fromsnmpinputimportsnmpSessionBaseClass >>>s=snmpSessionBaseClass() >>>s.query() ('Linuxdevmws2.racemi.com2.6.9-55.0.2.EL#1TueJun2614:08:18EDT2007i686',)
因为doctest模式将不加分析地执行Python语句,所以您必须小心,不要在doctest中使用可能更改的值,就像上面所给出的值。如果您在模块的docstring中粘贴了数行代码,那么您可以通过使用下面的方法来测试您的API文档:
def_test(): importdoctest doctest.testmod() if__name__=="__main__": _test()
总结
在本文中,您已经了解了协同使用Net-SNMP和IPython将成为一种功能强大的组合。本文介绍了下面几个主要概念:
- Python绑定:Net-SNMP现在提供了Python绑定,这使得我们能够充分地利用Python的功能来处理SNMP协议。
- 处理库:目前,Python绑定是同步的,但是使用处理库可以为每个请求派生新的进程,从而解决这个问题。
- 灵活的技术:对于系统管理员和软件工程师来说,IPython是一种非常成熟、并且功能非常强大的工具。尽管本文只是简要地介绍了几种灵活的技术,如文档测试和单元测试,但是您可以应用这些技术,以进行任何以测试为中心的开发、或者以交互的方式编写和分析代码。
- SNMP和IPython:对于SNMP和IPython在单独或者共同使用时能够实现的功能,本文只是进行了简要介绍。
SNMP非常复杂,它几乎使人们不敢想象编写任何有意义的代码,但是,我们希望本文所介绍的技术能够激发某些新的观点。如果您很好奇,想知道SNMP的Python实现究竟到了什么程度,那么可以研究一下Zenoss,下载一个虚拟机,并对它进行测试。还有一个API,您可以利用它来编写脚本,因此您可以将这里所学到的内容和全面的PythonNMS相结合。当然,也适用于任何其他NMS。