[编辑:我在运行python2.7.3]
我是一名网络工程师,我一直在ncclient(网站上的版本很旧,this是我一直在使用的版本)来让它与Brocade的NETCONF实现一起工作。为了让它能与我们的Brocade设备一起工作,我不得不做一些调整,但是我不得不从包中掏出钱来对源代码本身进行调整。这对我来说并不“干净”,所以我决定尝试用“正确的方式”来做,并覆盖包中存在的一些东西*;具体来说有三件事:
到目前为止,我在一个文件brcd_ncclient.py
中保存了以下代码:
#!/usr/bin/env python
# hack on XML element creation and create a subclass to override HelloHandler's
# build() method to format the XML in a way that the brocades actually like
from ncclient.xml_ import *
from ncclient.transport.session import HelloHandler
from ncclient.operations.rpc import RPC, RaiseMode
from ncclient.operations import util
# register brocade namespace and create functions to create proper xml for
# hello/capabilities exchange
BROCADE_1_0 = "http://brocade.com/ns/netconf/config/netiron-config/"
register_namespace('brcd', BROCADE_1_0)
brocade_new_ele = lambda tag, ns, attrs={}, **extra: ET.Element(qualify(tag, ns), attrs, **extra)
brocade_sub_ele = lambda parent, tag, ns, attrs={}, **extra: ET.SubElement(parent, qualify(tag, ns), attrs, **extra)
# subclass RPC to override self._id to change uuid-generated message-id's;
# Brocades seem to not be able to handle the really long id's
class BrcdRPC(RPC):
def __init__(self, session, async=False, timeout=30, raise_mode=RaiseMode.NONE):
self._id = "1"
return super(BrcdRPC, self).self._id
class BrcdHelloHandler(HelloHandler):
def __init__(self):
return super(BrcdHelloHandler, self).__init__()
@staticmethod
def build(capabilities):
hello = brocade_new_ele("hello", None, {'xmlns':"urn:ietf:params:xml:ns:netconf:base:1.0"})
caps = brocade_sub_ele(hello, "capabilities", None)
def fun(uri): brocade_sub_ele(caps, "capability", None).text = uri
map(fun, capabilities)
return to_xml(hello)
#return super(BrcdHelloHandler, self).build() ???
# since there's no classes I'm assuming I can just override the function itself
# in ncclient.operations.util?
def build_filter(spec, capcheck=None):
type = None
if isinstance(spec, tuple):
type, criteria = spec
# brocades want the netconf prefix on subtree filter attribute
rep = new_ele("filter", {'nc:type':type})
if type == "xpath":
rep.attrib["select"] = criteria
elif type == "subtree":
rep.append(to_ele(criteria))
else:
raise OperationError("Invalid filter type")
else:
rep = validated_element(spec, ("filter", qualify("filter")),
attrs=("type",))
# TODO set type var here, check if select attr present in case of xpath..
if type == "xpath" and capcheck is not None:
capcheck(":xpath")
return rep
然后在我的文件netconftest.py
中我有:
每当我运行netconftest.py
文件时,我得到了超时错误,因为在日志文件ncclient.log
中,我可以看到我的子类定义(即更改hello exchange的XML的子类定义——staticmethodbuild
)正在被忽略,而Brocade框不知道如何解释原始ncclientHelloHandler.build()
方法生成的XML**。我还可以在生成的日志文件中看到,我试图覆盖的其他内容也被忽略了,比如消息id(静态值为1)以及XML过滤器。在
所以,我有点不知所措。我确实从我的研究中发现了this blog post/module,它似乎正是我想要的,但我真的希望能够通过手工操作来理解我做错了什么,而不是用别人已经编写的模块作为借口,不用我自己来解决这个问题。在
*有人能给我解释一下这是否是“猴子修补”实际上很糟糕吗?在我的研究中,我发现猴子补丁是不可取的,但是this answer和{a5}让我有点困惑。对我来说,我想要覆盖这些位的愿望将阻止我维护自己的ncclient的整个分支。在
**为了提供更多的上下文,ncclient.transport.session.HelloHandler.build()
默认生成的XML,Brocade box似乎不喜欢:
<?xml version='1.0' encoding='UTF-8'?>
<nc:hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
<nc:capabilities>
<nc:capability>urn:ietf:params:netconf:base:1.0</nc:capability>
<nc:capability>urn:ietf:params:netconf:capability:writeable-running:1.0</nc:capability>
</nc:capabilities>
</nc:hello>
我重写的build()
方法的目的是将上面的XML转换成以下内容(Brocade喜欢:
<?xml version="1.0" encoding="UTF-8"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<capabilities>
<capability>urn:ietf:params:netconf:base:1.0</capability>
<capability>urn:ietf:params:netconf:capability:writeable-running:1.0</capability>
</capabilities>
</hello>
我不想再去问什么,因为我很难再去寻找答案了。我真正想做的是在运行时重写包中的东西。在
我将
brcd_ncclient.py
改为(为简洁起见删除了注释):然后在
^{pr2}$netconftest.py
中:这让我几乎到了我想去的地方。我仍然需要编辑原始源代码来更改使用
uuid1().urn
生成的消息id,因为我还没有弄清楚或者不明白如何在运行时__init__
发生之前更改对象的属性(鸡/蛋问题?);以下是ncclient/operations/rpc.py
中的错误代码:归功于this recipe on ActiveState终于让我明白了我真正想做的事。我最初发布的代码在技术上是不正确的-如果我想做的是从我自己的ncclient中分离出来,对它进行更改和/或维护,这根本不是我想做的,至少现在不是这样。在
我会编辑我的问题标题,以更好地反映我最初想要的-如果其他人有更好或更干净的想法,我完全开放。在
相关问题 更多 >
编程相关推荐