2011-11-20 26 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的對象,那麼使它成爲該對象上的一個方法將起作用。

但是它看起來像你這樣做的方式幾乎是我能想到的最直接的方式,只要你確保你保持雙向鏈接(所有者 - >擁有和擁有 - >所有者)一致,如果他們改變了。