Эффективный анализ владения экземпляром IP-адреса объекта Python - PullRequest
2 голосов
/ 20 ноября 2011

В приведенном ниже коде я пытаюсь найти способ исключить self.owner из класса L3Address() ... Идея состоит в том, что я хочу знать, кому принадлежит IP-адрес данного Vlan или интерфейса, не имеяявно вызвать его.

Есть ли лучший способ получить владельца адресов 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 ~]$

Ответы [ 2 ]

4 голосов
/ 20 ноября 2011

Ваш нынешний подход с использованием владельца является, вероятно, самым чистым решением.

При этом, если вам необходимо выяснить, кому принадлежит IP-адрес, то gc.get_referrers() может быть полезным.

2 голосов
/ 20 ноября 2011

Невозможно просто удалить поле owner из L3Protocol и просто волшебным образом определить его во время выполнения.По сути, вы спрашиваете, «какой объект имеет ссылку на этот?».Конечно, в общем случае это даже не имеет смысла, поскольку может быть любое количество объектов, которые содержат ссылки на экземпляр L3Protocol (и каждый из них может даже содержать любое количество ссылок на экземпляр L3Protocol).

Так что либо вам придется каким-то образом записывать владельца каждого L3Protocol, либо вам нужно будет только попросить владельца L3Protocol в контекстекакая дополнительная информация доступна;owner теоретически может быть функцией, которая принимает L3Protocol и вселенную потенциальных владельцев и возвращает ту, которая владеет L3Protocol (или None).Если у вас есть объект, который записывает все Interface и Vlan с, то создание этого метода для этого объекта будет работать.

Но похоже, что вы делаете это в значительной степенисамый простой способ, который я могу придумать, если вы убедитесь, что двунаправленные ссылки (владелец - владелец и владелец -> владелец) непротиворечивы, если они когда-либо изменятся.

...