Exemple #1
0
    def execute(self, action, actionargs=None, vs=None, rs=None):
        """
        Execute an action.
        """
        if action not in [
                "enable", "disable", "operenable", "operdisable", "enableall",
                "disableall"
        ]:
            yield None
            return
        v, httpclass, rip, port = self.parse(vs, rs)
        if rip is None:
            yield {}
            return
        orip = ip2oid(rip)

        if action == "enableall" or action == "disableall":
            d = defer.waitForDeferred(
                self.proxy.set(
                    (self.oids['ltmNodeAddrNewSessionEnable'], orip),
                    (action == "enableall") and 2 or 1))
            yield d
            d.getResult()
            yield True
            return

        # Get pool
        ov = str2oid(v)
        if httpclass is None:
            p = defer.waitForDeferred(
                self.cache_or_get(('ltmVirtualServDefaultPool', ov)))
        else:
            oc = str2oid(httpclass)
            p = defer.waitForDeferred(
                self.cache_or_get(('ltmHttpClassPoolName', oc)))
        yield p
        p = p.getResult()
        op = str2oid(p)

        d = defer.waitForDeferred(
            self.proxy.set(
                (self.oids['ltmPoolMemberNewSessionEnable'], op, orip, port),
                action.endswith("enable") and 2 or 1))
        yield d
        d.getResult()
        yield True
        return
Exemple #2
0
    def execute(self, action, actionargs=None, vs=None, rs=None):
        """
        Execute an action.
        """
        if action not in ["enable", "disable", "operenable", "operdisable",
                          "enableall", "disableall"]:
            yield None
            return
        v, httpclass, rip, port = self.parse(vs, rs)
        if rip is None:
            yield {}
            return
        orip = ip2oid(rip)

        if action == "enableall" or action == "disableall":
            d = defer.waitForDeferred(
                self.proxy.set((self.oids['ltmNodeAddrNewSessionEnable'], orip),
                               (action == "enableall") and 2 or 1))
            yield d
            d.getResult()
            yield True
            return

        # Get pool
        ov = str2oid(v)
        if httpclass is None:
            p = defer.waitForDeferred(self.cache_or_get(('ltmVirtualServDefaultPool', ov)))
        else:
            oc = str2oid(httpclass)
            p = defer.waitForDeferred(self.cache_or_get(('ltmHttpClassPoolName', oc)))
        yield p
        p = p.getResult()
        op = str2oid(p)

        d = defer.waitForDeferred(
            self.proxy.set((self.oids['ltmPoolMemberNewSessionEnable'],
                            op, orip, port),
                           action.endswith("enable") and 2 or 1))
        yield d
        d.getResult()
        yield True
        return
Exemple #3
0
    def process_rs(self, owner, content, service, backup=False):
        """
        Process data for a given virtual server and real server.

        @param service: service name
        @param backup: C{False} or a string representing backup position
           C{None} is we don't know if it is a backup or not

        @return: a deferred C{IRealServer} or None
        """
        oservice = str2oid(service)
        # Retrieve some data if needed:
        oids = []
        for o in self.oids:
            if o.startswith("apSvc"):
                oids.append((o, oservice))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        # Is it a backup?
        if backup is None:
            oowner = str2oid(owner)
            ocontent = str2oid(content)
            for b in ["primary", "second"]:
                s = defer.waitForDeferred(
                    self.cache_or_get(('apCnt%sSorryServer' % b.capitalize(),
                                       oowner, ocontent)))
                yield s
                s = s.getResult()
                if s and s == service:
                    backup = b
                    break
            if backup is None:
                backup = False

        # Build the real server
        rip = self.cache(('apSvcIPAddress', oservice))
        rport = self.cache(('apSvcPort', oservice))
        protocol = self.protocols[
            self.cache(('apSvcIPProtocol', oservice))]
        state = self.states[
            self.cache(('apSvcState', oservice))]
        if not backup:
            weight = self.cache(('apSvcWeight', oservice))
            rs = RealServer(service, rip, rport, protocol, weight, state)
        else:
            rs = SorryServer(service, rip, rport, protocol, state)
            rs.extra["backup type"] = backup

        rs.extra["KAL type"] = self.kals[
            self.cache(('apSvcKALType', oservice))]


        for key, oid in [
            ('KAL frequency', 'apSvcKALFrequency'),
            ('KAL max failure', 'apSvcKALMaxFailure'),
            ('KAL retry period', 'apSvcKALRetryPeriod'),
            ('KAL URI', 'apSvcKALUri'),
            ('KAL port', 'apSvcKALPort')
            ]:
            try:
                rs.extra[key] = self.cache((oid, oservice))
            except KeyError:
                pass
        yield rs
        return
Exemple #4
0
    def process_vs(self, owner, content):
        """
        Process data for a given virtual server when no real server is provided

        @param owner: owner of the content
        @param content: content name
        @return: a deferred C{IVirtualServer} or None
        """
        oowner = str2oid(owner)
        ocontent = str2oid(content)
        # Retrieve some data if needed
        oids = []
        for o in self.oids:
            if o.startswith("apCnt") and not o.startswith("apCntsvc"):
                oids.append((o, oowner, ocontent))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        # Let's build our virtual server
        vip = "%s:%d" % tuple(self.cache(('apCntIPAddress', oowner, ocontent),
                                         ('apCntPort', oowner, ocontent)))
        protocol = self.protocols[self.cache(('apCntIPProtocol', oowner, ocontent))]
        mode = self.modes[self.cache(('apCntBalance', oowner, ocontent))]
        vs = VirtualServer(content, vip, protocol, mode)

        # Add some extra information
        vs.extra["URL"] = self.cache(('apCntUrl', oowner, ocontent))
        vs.extra["sticky"] = self.sticky[
            self.cache(('apCntSticky', oowner, ocontent))]
        vs.extra["virtual server status"] = self.status[
            self.cache(('apCntEnable', oowner, ocontent))] and "up" or "down"
        vs.extra["persistence"] = self.status[
            self.cache(('apCntPersistence', oowner, ocontent))] and "enabled" or "disabled"
        vs.extra["content type"] = self.contents[
            self.cache(('apCntContentType', oowner, ocontent))]

        # Find and attach real servers
        if not self.is_cached(('apCntsvcSvcName', oowner, ocontent)):
            services = defer.waitForDeferred(
                self.proxy.walk("%s.%s.%s" % (self.oids['apCntsvcSvcName'],
                                              oowner, ocontent)))
            yield services
            services.getResult()
        for r in self.cache(('apCntsvcSvcName', oowner, ocontent)):
            service = oid2str(r)
            rs = defer.waitForDeferred(self.process_rs(owner, content, service))
            yield rs
            rs = rs.getResult()
            if rs is not None:
                vs.realservers[service] = rs

        # Add backups
        for backup in ["primary", "second"]:
            service = self.cache(('apCnt%sSorryServer' % backup.capitalize(),
                                  oowner, ocontent))
            if not service: continue
            rs = defer.waitForDeferred(self.process_rs(owner, content, service, backup))
            yield rs
            rs = rs.getResult()
            if rs is not None:
                vs.realservers[service] = rs

        yield vs
        return
Exemple #5
0
    def process_rs(self, v, httpclass, rip, port):
        """
        Process data for a given virtual server and real server.

        @param v: virtual server
        @param httpclass: HTTP class (or C{None} for default pool)
        @param rip: real IP
        @param port: port
        """
        # Retrieve some data if needed:
        ov = str2oid(v)
        orip = ip2oid(rip)
        if httpclass is None:
            p = defer.waitForDeferred(self.cache_or_get(('ltmVirtualServDefaultPool', ov)))
        else:
            oc = str2oid(httpclass)
            p = defer.waitForDeferred(self.cache_or_get(('ltmHttpClassPoolName', oc)))
        yield p
        p = p.getResult()
        op = str2oid(p)
        oids = []
        for o in self.oids:
            if o.startswith("ltmPoolMbr") or o.startswith("ltmPoolMember"):
                oids.append((o, op, orip, port))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        oids = []
        for o in self.oids:
            if o.startswith("ltmNodeAddr"):
                oids.append((o, orip))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        name = self.cache(('ltmNodeAddrScreenName', orip))
        protocol = defer.waitForDeferred(self.get_protocol(ov))
        yield protocol
        protocol = protocol.getResult()
        weight = self.cache(('ltmPoolMemberWeight', op, orip, port))
        avail, enabled, session = self.cache(
            ('ltmPoolMbrStatusAvailState', op, orip, port),
            ('ltmPoolMbrStatusEnabledState', op, orip, port),
            ('ltmPoolMemberSessionStatus', op, orip, port))
        if session != 1 or self.enabledstates[enabled] != "enabled":
            state = "disabled"
        else:
            state = self.availstates[avail]
        rs = RealServer(name, rip, port, protocol, weight, state)
        rs.extra["detailed reason"] = self.cache(('ltmPoolMbrStatusDetailReason',
                                                  op, orip, port))
        rs.extra["monitor rule"] = self.cache(('ltmPoolMemberMonitorRule',
                                               op, orip, port))
        # Actions
        if self.proxy.writable:
            # ltmPoolMemberNewSessionEnable == 1 means user disabled
            if self.cache(('ltmPoolMemberNewSessionEnable', op, orip, port)) != 1:
                rs.actions['disable'] = 'Disable (permanent)'
            else:
                rs.actions['enable'] = 'Enable (permanent)'
            if self.cache(('ltmNodeAddrNewSessionEnable', orip)) != 1:
                rs.actions['disableall'] = 'Disable globally (permanent)'
            else:
                rs.actions['enableall'] = 'Enable globally (permanent)'
        yield rs
        return
Exemple #6
0
    def process_vs(self, v, httpclass):
        """
        Process data for a given virtual server when no real server is provided

        @param v: virtual server
        @param httpclass: HTTP class to use (or C{None} for default pool) to select pool
        @return: a maybe deferred C{IVirtualServer}
        """
        ov = str2oid(v)
        # Retrieve some data if needed
        oids = []
        for o in self.oids:
            if o.startswith("ltmVirtualServ") or o.startswith("ltmVs"):
                if not o.startswith("ltmVirtualServProfile"):
                    oids.append((o, ov))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        # IPv6 or IPv4 virtual server
        if self.cache(('ltmVirtualServAddrType', ov)) not in [1, 2]:
            log.msg("In %r, unknown address type for virtual server %s, skip it" % (self.lb.name, v))
            yield None
            return

        # Get pool
        if httpclass is None:
            p = self.cache(('ltmVirtualServDefaultPool', ov))
            if not p:
                log.msg("In %r, no pool for %s, skip it" % (self.lb.name, v))
                yield None
                return
        else:
            oc = str2oid(httpclass)
            p = defer.waitForDeferred(self.cache_or_get(('ltmHttpClassPoolName', oc)))
            yield p
            p = p.getResult()
            if not p:
                log.msg("In %r, no pool for %s (class %s), skip it" % (self.lb.name, v, httpclass))
                yield None
                return
        op = str2oid(p)
        oids = []
        for o in self.oids:
            if o.startswith("ltmPool") and not o.startswith("ltmPoolMbr") and \
                    not o.startswith("ltmPoolMember"):
                oids.append((o, op))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        if self.cache(('ltmVirtualServAddrType', ov)) == 1:
            vip = "%s:%d" % (socket.inet_ntop(socket.AF_INET,
                                              self.cache(('ltmVirtualServAddr', ov))),
                             self.cache(('ltmVirtualServPort', ov)))
        else:
            vip = "[%s]:%d" % (socket.inet_ntop(socket.AF_INET6,
                                              self.cache(('ltmVirtualServAddr', ov))),
                             self.cache(('ltmVirtualServPort', ov)))
        protocol = defer.waitForDeferred(self.get_protocol(ov))
        yield protocol
        protocol = protocol.getResult()
        mode = self.modes[self.cache(('ltmPoolLbMode', op))]
        vs = VirtualServer(httpclass is None and v or ("%s;%s" % (v, httpclass)),
                           vip, protocol, mode)
        if httpclass:
            vs.extra["http class"] = httpclass
        vs.extra["vs availability state"] = \
            self.availstates[self.cache(('ltmVsStatusAvailState', ov))]
        vs.extra["vs enabled state"] = \
            self.enabledstates[self.cache(('ltmVsStatusEnabledState', ov))]
        vs.extra["virtual server detailed reason"] = \
            self.cache(('ltmVsStatusDetailReason', ov))
        vs.extra["address translation"] = \
            self.cache(('ltmVirtualServTranslateAddr', ov)) == 1 and "enabled" or "disabled"
        vs.extra["pool name"] = p
        vs.extra["pool availability state"] = \
            self.availstates[self.cache(('ltmPoolStatusAvailState', op))]
        vs.extra["pool enabled state"] = \
            self.enabledstates[self.cache(('ltmPoolStatusEnabledState', op))]
        vs.extra["pool detailed reason"] = \
            self.cache(('ltmPoolStatusDetailReason', op))

        # Find and attach real servers
        if not self.is_cached(('ltmPoolMbrStatusAvailState', op)):
            for o in self.oids:
                if o.startswith('ltmPoolMbr') or o.startswith('ltmPoolMember'):
                    # F5 is buggy here, we need to walk all pool members
                    # pm = defer.waitForDeferred(
                    #    self.proxy.walk("%s.%s" % (self.oids[o], op)))
                    pm = defer.waitForDeferred(
                        self.proxy.walk(self.oids[o]))
                    yield pm
                    pm.getResult()
        if not self.is_cached(('ltmPoolMbrStatusAvailState', op)):
            print "pool %s is empty..." % p
            yield None
            return
        for r in self.cache(('ltmPoolMbrStatusAvailState', op)):
            rip = socket.inet_ntop(r[0] == 1 and socket.AF_INET or socket.AF_INET6,
                                   struct.pack("B"*r[1], *r[-(r[1]+1):-1]))
            port = r[-1]
            rs = defer.waitForDeferred(self.process_rs(v, httpclass, rip, port))
            yield rs
            rs = rs.getResult()
            if rs is not None:
                vs.realservers["%s,%d" % (rip, port)] = rs

        yield vs
        return
Exemple #7
0
    def process_rs(self, owner, content, service, backup=False):
        """
        Process data for a given virtual server and real server.

        @param service: service name
        @param backup: C{False} or a string representing backup position
           C{None} is we don't know if it is a backup or not

        @return: a deferred C{IRealServer} or None
        """
        oservice = str2oid(service)
        # Retrieve some data if needed:
        oids = []
        for o in self.oids:
            if o.startswith("apSvc"):
                oids.append((o, oservice))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        # Is it a backup?
        if backup is None:
            oowner = str2oid(owner)
            ocontent = str2oid(content)
            for b in ["primary", "second"]:
                s = defer.waitForDeferred(
                    self.cache_or_get(('apCnt%sSorryServer' % b.capitalize(),
                                       oowner, ocontent)))
                yield s
                s = s.getResult()
                if s and s == service:
                    backup = b
                    break
            if backup is None:
                backup = False

        # Build the real server
        rip = self.cache(('apSvcIPAddress', oservice))
        rport = self.cache(('apSvcPort', oservice))
        protocol = self.protocols[self.cache(('apSvcIPProtocol', oservice))]
        state = self.states[self.cache(('apSvcState', oservice))]
        if not backup:
            weight = self.cache(('apSvcWeight', oservice))
            rs = RealServer(service, rip, rport, protocol, weight, state)
        else:
            rs = SorryServer(service, rip, rport, protocol, state)
            rs.extra["backup type"] = backup

        rs.extra["KAL type"] = self.kals[self.cache(
            ('apSvcKALType', oservice))]

        for key, oid in [('KAL frequency', 'apSvcKALFrequency'),
                         ('KAL max failure', 'apSvcKALMaxFailure'),
                         ('KAL retry period', 'apSvcKALRetryPeriod'),
                         ('KAL URI', 'apSvcKALUri'),
                         ('KAL port', 'apSvcKALPort')]:
            try:
                rs.extra[key] = self.cache((oid, oservice))
            except KeyError:
                pass
        yield rs
        return
Exemple #8
0
    def process_vs(self, owner, content):
        """
        Process data for a given virtual server when no real server is provided

        @param owner: owner of the content
        @param content: content name
        @return: a deferred C{IVirtualServer} or None
        """
        oowner = str2oid(owner)
        ocontent = str2oid(content)
        # Retrieve some data if needed
        oids = []
        for o in self.oids:
            if o.startswith("apCnt") and not o.startswith("apCntsvc"):
                oids.append((o, oowner, ocontent))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        # Let's build our virtual server
        vip = "%s:%d" % tuple(
            self.cache(('apCntIPAddress', oowner, ocontent),
                       ('apCntPort', oowner, ocontent)))
        protocol = self.protocols[self.cache(
            ('apCntIPProtocol', oowner, ocontent))]
        mode = self.modes[self.cache(('apCntBalance', oowner, ocontent))]
        vs = VirtualServer(content, vip, protocol, mode)

        # Add some extra information
        vs.extra["URL"] = self.cache(('apCntUrl', oowner, ocontent))
        vs.extra["sticky"] = self.sticky[self.cache(
            ('apCntSticky', oowner, ocontent))]
        vs.extra["virtual server status"] = self.status[self.cache(
            ('apCntEnable', oowner, ocontent))] and "up" or "down"
        vs.extra["persistence"] = self.status[self.cache(
            ('apCntPersistence', oowner,
             ocontent))] and "enabled" or "disabled"
        vs.extra["content type"] = self.contents[self.cache(
            ('apCntContentType', oowner, ocontent))]

        # Find and attach real servers
        if not self.is_cached(('apCntsvcSvcName', oowner, ocontent)):
            services = defer.waitForDeferred(
                self.proxy.walk(
                    "%s.%s.%s" %
                    (self.oids['apCntsvcSvcName'], oowner, ocontent)))
            yield services
            services.getResult()
        for r in self.cache(('apCntsvcSvcName', oowner, ocontent)):
            service = oid2str(r)
            rs = defer.waitForDeferred(self.process_rs(owner, content,
                                                       service))
            yield rs
            rs = rs.getResult()
            if rs is not None:
                vs.realservers[service] = rs

        # Add backups
        for backup in ["primary", "second"]:
            service = self.cache(
                ('apCnt%sSorryServer' % backup.capitalize(), oowner, ocontent))
            if not service: continue
            rs = defer.waitForDeferred(
                self.process_rs(owner, content, service, backup))
            yield rs
            rs = rs.getResult()
            if rs is not None:
                vs.realservers[service] = rs

        yield vs
        return
Exemple #9
0
    def process_rs(self, v, httpclass, rip, port):
        """
        Process data for a given virtual server and real server.

        @param v: virtual server
        @param httpclass: HTTP class (or C{None} for default pool)
        @param rip: real IP
        @param port: port
        """
        # Retrieve some data if needed:
        ov = str2oid(v)
        orip = ip2oid(rip)
        if httpclass is None:
            p = defer.waitForDeferred(
                self.cache_or_get(('ltmVirtualServDefaultPool', ov)))
        else:
            oc = str2oid(httpclass)
            p = defer.waitForDeferred(
                self.cache_or_get(('ltmHttpClassPoolName', oc)))
        yield p
        p = p.getResult()
        op = str2oid(p)
        oids = []
        for o in self.oids:
            if o.startswith("ltmPoolMbr") or o.startswith("ltmPoolMember"):
                oids.append((o, op, orip, port))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        oids = []
        for o in self.oids:
            if o.startswith("ltmNodeAddr"):
                oids.append((o, orip))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        name = self.cache(('ltmNodeAddrScreenName', orip))
        protocol = defer.waitForDeferred(self.get_protocol(ov))
        yield protocol
        protocol = protocol.getResult()
        weight = self.cache(('ltmPoolMemberWeight', op, orip, port))
        avail, enabled, session = self.cache(
            ('ltmPoolMbrStatusAvailState', op, orip, port),
            ('ltmPoolMbrStatusEnabledState', op, orip, port),
            ('ltmPoolMemberSessionStatus', op, orip, port))
        if session != 1 or self.enabledstates[enabled] != "enabled":
            state = "disabled"
        else:
            state = self.availstates[avail]
        rs = RealServer(name, rip, port, protocol, weight, state)
        rs.extra["detailed reason"] = self.cache(
            ('ltmPoolMbrStatusDetailReason', op, orip, port))
        rs.extra["monitor rule"] = self.cache(
            ('ltmPoolMemberMonitorRule', op, orip, port))
        # Actions
        if self.proxy.writable:
            # ltmPoolMemberNewSessionEnable == 1 means user disabled
            if self.cache(
                ('ltmPoolMemberNewSessionEnable', op, orip, port)) != 1:
                rs.actions['disable'] = 'Disable (permanent)'
            else:
                rs.actions['enable'] = 'Enable (permanent)'
            if self.cache(('ltmNodeAddrNewSessionEnable', orip)) != 1:
                rs.actions['disableall'] = 'Disable globally (permanent)'
            else:
                rs.actions['enableall'] = 'Enable globally (permanent)'
        yield rs
        return
Exemple #10
0
    def process_vs(self, v, httpclass):
        """
        Process data for a given virtual server when no real server is provided

        @param v: virtual server
        @param httpclass: HTTP class to use (or C{None} for default pool) to select pool
        @return: a maybe deferred C{IVirtualServer}
        """
        ov = str2oid(v)
        # Retrieve some data if needed
        oids = []
        for o in self.oids:
            if o.startswith("ltmVirtualServ") or o.startswith("ltmVs"):
                if not o.startswith("ltmVirtualServProfile"):
                    oids.append((o, ov))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        # IPv6 or IPv4 virtual server
        if self.cache(('ltmVirtualServAddrType', ov)) not in [1, 2]:
            log.msg(
                "In %r, unknown address type for virtual server %s, skip it" %
                (self.lb.name, v))
            yield None
            return

        # Get pool
        if httpclass is None:
            p = self.cache(('ltmVirtualServDefaultPool', ov))
            if not p:
                log.msg("In %r, no pool for %s, skip it" % (self.lb.name, v))
                yield None
                return
        else:
            oc = str2oid(httpclass)
            p = defer.waitForDeferred(
                self.cache_or_get(('ltmHttpClassPoolName', oc)))
            yield p
            p = p.getResult()
            if not p:
                log.msg("In %r, no pool for %s (class %s), skip it" %
                        (self.lb.name, v, httpclass))
                yield None
                return
        op = str2oid(p)
        oids = []
        for o in self.oids:
            if o.startswith("ltmPool") and not o.startswith("ltmPoolMbr") and \
                    not o.startswith("ltmPoolMember"):
                oids.append((o, op))
        oids = tuple(oids)
        c = defer.waitForDeferred(self.cache_or_get(*oids))
        yield c
        c.getResult()

        if self.cache(('ltmVirtualServAddrType', ov)) == 1:
            vip = "%s:%d" % (socket.inet_ntop(
                socket.AF_INET, self.cache(('ltmVirtualServAddr', ov))),
                             self.cache(('ltmVirtualServPort', ov)))
        else:
            vip = "[%s]:%d" % (socket.inet_ntop(
                socket.AF_INET6, self.cache(('ltmVirtualServAddr', ov))),
                               self.cache(('ltmVirtualServPort', ov)))
        protocol = defer.waitForDeferred(self.get_protocol(ov))
        yield protocol
        protocol = protocol.getResult()
        mode = self.modes[self.cache(('ltmPoolLbMode', op))]
        vs = VirtualServer(
            httpclass is None and v or ("%s;%s" % (v, httpclass)), vip,
            protocol, mode)
        if httpclass:
            vs.extra["http class"] = httpclass
        vs.extra["vs availability state"] = \
            self.availstates[self.cache(('ltmVsStatusAvailState', ov))]
        vs.extra["vs enabled state"] = \
            self.enabledstates[self.cache(('ltmVsStatusEnabledState', ov))]
        vs.extra["virtual server detailed reason"] = \
            self.cache(('ltmVsStatusDetailReason', ov))
        vs.extra["address translation"] = \
            self.cache(('ltmVirtualServTranslateAddr', ov)) == 1 and "enabled" or "disabled"
        vs.extra["pool name"] = p
        vs.extra["pool availability state"] = \
            self.availstates[self.cache(('ltmPoolStatusAvailState', op))]
        vs.extra["pool enabled state"] = \
            self.enabledstates[self.cache(('ltmPoolStatusEnabledState', op))]
        vs.extra["pool detailed reason"] = \
            self.cache(('ltmPoolStatusDetailReason', op))

        # Find and attach real servers
        if not self.is_cached(('ltmPoolMbrStatusAvailState', op)):
            for o in self.oids:
                if o.startswith('ltmPoolMbr') or o.startswith('ltmPoolMember'):
                    # F5 is buggy here, we need to walk all pool members
                    # pm = defer.waitForDeferred(
                    #    self.proxy.walk("%s.%s" % (self.oids[o], op)))
                    pm = defer.waitForDeferred(self.proxy.walk(self.oids[o]))
                    yield pm
                    pm.getResult()
        if not self.is_cached(('ltmPoolMbrStatusAvailState', op)):
            print "pool %s is empty..." % p
            yield None
            return
        for r in self.cache(('ltmPoolMbrStatusAvailState', op)):
            rip = socket.inet_ntop(
                r[0] == 1 and socket.AF_INET or socket.AF_INET6,
                struct.pack("B" * r[1], *r[-(r[1] + 1):-1]))
            port = r[-1]
            rs = defer.waitForDeferred(self.process_rs(v, httpclass, rip,
                                                       port))
            yield rs
            rs = rs.getResult()
            if rs is not None:
                vs.realservers["%s,%d" % (rip, port)] = rs

        yield vs
        return