在下面的代码中,我试图找到一种方法来消除self.owner
类中的L3Address()
...我的想法是,我想知道谁在给定的Vlan上拥有IP地址或接口,而无需明确地将其调出。
是否有更好的方法来获取IPv4地址的所有者(可能通过内省)?
import ipaddr
class SomethingOwned(object):
def __init__(self, owner=None):
self._owner = owner
# Build self.owner (the object instance that owns the subclass object)
self._create_owner()
def _create_owner(self):
"""
create self.owner and ensure the subclass was called correctly
"""
if not (self._owner is None):
self.owner = self._owner
else:
raise ValueError, "%s() must be called with an 'owner' arg, which cannot be None" % self.__class__.__name__
class L3Address(SomethingOwned):
"""
A Layer3 IP PDU address that has an owning object
"""
def __init__(self, version=None, owner=None, addr=None, masklen=None):
# Call SomethingOwned.__init__(owner=owner) to add an owner attribute
super(L3Address, self).__init__(owner=owner)
self._addr = addr
self._masklen = masklen
self._version = version
# Build self._obj
self._create_ip_object()
self.addr = self._obj.ip
self.netmask = self._obj.netmask
self.masklen = self._obj.prefixlen
def __repr__(self):
return "<IPv%i %s/%s>" % (self._version, self.addr, self.masklen)
def _create_ip_object(self):
"""
create self._obj and ensure the subclass was called with the correct version
"""
if self._version==4:
if (self._masklen is None):
self._obj = ipaddr.IPv4Network(self._addr)
else:
self._obj = ipaddr.IPv4Network("%s/%s" % (self._addr, self._masklen))
elif version==6:
if (self._masklen is None):
self._obj = ipaddr.IPv6Network(self._addr)
else:
self._obj = ipaddr.IPv6Network("%s/%s" % (self._addr, self._masklen))
else:
raise ValueError, "Version must be 4 or 6"
class IPv4(L3Address):
def __init__(self, **kwargs):
## Initialize the IPv4 network object instance
# Call L3Protocol.__init__(version=4 **kwargs)
super(IPv4, self).__init__(version=4, **kwargs)
class IPv6(L3Address):
def __init__(self, **kwargs):
## Initialize the IPv6 network object instance
# Call L3Protocol.__init__(version=6 **kwargs)
super(IPv4, self).__init__(version=6, **kwargs)
class Vlan(object):
def __init__(self, name=None, id=None, ipv4=None):
self.id = id
self.name = name
if not (ipv4 is None):
### NOTE: I am trying to eliminate the need for the owner arg here
self.ipv4 = IPv4(owner=self, addr=ipv4)
def __repr__(self):
return "Vlan %s (name: %s)" % (self.id, self.name)
class Interface(object):
def __init__(self, id=None, ipv4=None):
self.id = id
self.ipv4 = None
if not (ipv4 is None):
### NOTE: I am trying to eliminate the need for the owner arg here
self.ipv4 = IPv4(owner=self, addr=ipv4)
def __repr__(self):
return "Interface %s" % self.id
if __name__=='__main__':
def find_owner(ip_instance):
print "Owner of '%s' is '%s'" % (ip_instance, ip_instance.owner)
find_owner(Interface(id='ge-0/0/0', ipv4='1.1.1.1').ipv4)
find_owner(Vlan(id='25', name='accounting', ipv4='1.1.1.2/25').ipv4)
执行结果:
[mpenning@hotcoffee ~]$ python cisco.py
Owner of <IPv4 1.1.1.1/32> is 'Interface ge-0/0/0'
Owner of <IPv4 1.1.1.2/25> is 'Vlan 25 (name: accounting)'
[mpenning@hotcoffee ~]$
答案 0 :(得分:4)
使用所有者的当前方法可能是最干净的解决方案。
话虽如此,如果您需要找出谁拥有IP地址,那么gc.get_referrers()可能会有所帮助。
答案 1 :(得分:2)
无法从owner
中删除L3Protocol
字段,只是在运行时神奇地确定它。你基本上要问的是“哪个对象引用了这个?”。在一般情况下,当然甚至没有意义,因为可能有任意数量的对象包含对L3Protocol
实例的引用(并且它们中的每一个甚至可以包含对{{1}的任意数量的引用实例)。
因此,要么您必须以某种方式记录每个L3Protocol
的所有者,要么您只需要在上下文中请求L3Protocol
的所有者哪些信息更多;从理论上讲,L3Protocol
可以是一个函数,它会占用owner
和一群潜在的所有者,并返回拥有L3Protocol
(或L3Protocol
)的所有者。如果您有一个记录所有None
和Interface
的对象,那么将其作为该对象的方法就可以了。
但看起来你正在这样做的方式几乎是我能想到的最直接的方式,只要你确保你保持双向链接(所有者 - &gt;拥有和拥有 - &gt ;所有者)如果他们改变了一致。