2011-11-20 50 views
2

在下面的代码中,我试图找到一种方法来从L3Address()类中删除self.owner ...这个想法是我想知道谁在给定的Vlan上拥有IP地址或接口,而不必明确地将其调出。有效反思Python对象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) 

执行结果

[[email protected] ~]$ 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)' 
[[email protected] ~]$ 

回答

4

您目前的方法使用所有者可能是最干净的解决方案。

这就是说,如果你需要找出谁拥有一个IP地址,那么gc.get_referrers()可能会有所帮助。

2

没有办法只有从L3Protocol删除owner场和神奇地确定它在运行时。你基本上要问的是“什么对象有这个参考?”。在一般情况下,甚至没有意义,因为可能有任何数量的对象包含对实例的引用(并且每个对象甚至可以包含对L3Protocol实例的任意数量的引用)。

因此,要么以某种方式记录每个L3Protocol的所有者,要么只能在可获取更多信息的环境中请求L3Protocol的拥有者; owner在理论上可以是一个函数,它需要一个L3Protocol以及一个潜在所有者的全局并返回拥有L3Protocol(或None)的那个。如果您有一个记录所有Interface s和Vlan s的对象,那么使它成为该对象上的一个方法将起作用。

但是它看起来像你这样做的方式几乎是我能想到的最直接的方式,只要你确保你保持双向链接(所有者 - >拥有和拥有 - >所有者)一致,如果他们改变了。