Repository: qpid-dispatch
Updated Branches:
  refs/heads/crolke-DISPATCH-188-1 3a766aebf -> 3e9a37ea5


Made HostStruct a class for external use.


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/3e9a37ea
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/3e9a37ea
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/3e9a37ea

Branch: refs/heads/crolke-DISPATCH-188-1
Commit: 3e9a37ea5b838c2dca53611c70447aebc720552f
Parents: 3a766ae
Author: Chuck Rolke <[email protected]>
Authored: Wed Dec 9 11:28:14 2015 -0500
Committer: Chuck Rolke <[email protected]>
Committed: Wed Dec 9 11:28:14 2015 -0500

----------------------------------------------------------------------
 .../qpid_dispatch_internal/management/policy.py | 125 ++++++++++++-------
 tests/system_tests_policy.py                    |  53 ++++----
 2 files changed, 110 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3e9a37ea/python/qpid_dispatch_internal/management/policy.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/policy.py 
b/python/qpid_dispatch_internal/management/policy.py
index 2601ec5..8ba72dd 100644
--- a/python/qpid_dispatch_internal/management/policy.py
+++ b/python/qpid_dispatch_internal/management/policy.py
@@ -105,20 +105,13 @@ class PolicyError(Exception):
 
 #
 #
-class HostAddr():
+class HostStruct():
     """
-    Provide HostIP address ranges and comparison functions.
-    A HostIP may be:
-    - single address:      10.10.1.1
-    - a pair of addresses: 10.10.0.0,10.10.255.255
-    Only IPv4 and IPv6 are supported.
-    - No unix sockets.
-    HostIP names must resolve to a single IP address.
-    Address pairs define a range.
-    - The second address must be numerically larger than the first address.
-    - The addresses must be of the same address 'family', IPv4 or IPv6.
-    IPv6 support is conditional based on underlying OS network options.
-    Raises a PolicyError on validation error in constructor.
+    HostStruct represents a single, binary socket address from getaddrinfo
+        - name     : name given to constructor, numeric IP or host name
+        - saddr    : net name resolved by getaddrinfo, numeric IP
+        - family   : saddr.family, int
+        - binary   : saddr packed binary address, binary string
     """
     families = [socket.AF_INET]
     famnames = ["IPv4"]
@@ -126,20 +119,15 @@ class HostAddr():
         families.append(socket.AF_INET6)
         famnames.append("IPv6")
 
-    HostStruct = namedtuple("HostStruct", "text family binary")
-
-    def has_ipv6(self):
-        return socket.has_ipv6
-
-    def parsehost(self, hostname):
+    def __init__(self, hostname):
         """
+        Given a host name text string, return the socket info for it.
         @param[in] hostname host IP address to parse
-        @return HostStruct representing this host
         """
         try:
             res = socket.getaddrinfo(hostname, 0)
             if len(res) == 0:
-                raise PolicyError("HostAddr.parsehost: '%s' did not resolve to 
an IP address" % hostname)
+                raise PolicyError("HostStruct: '%s' did not resolve to an IP 
address" % hostname)
             foundFirst = False
             saddr = ""
             sfamily = socket.AF_UNSPEC
@@ -153,21 +141,55 @@ class HostAddr():
                 else:
                     if family in self.families:
                         if not saddr == sockaddr[0] or not sfamily == family:
-                            raise PolicyError("HostAddr.parsehost: '%s' 
resolves to multiple IP addresses" %
+                            raise PolicyError("HostStruct: '%s' resolves to 
multiple IP addresses" %
                                               hostname)
 
             if not foundFirst:
-                raise PolicyError("HostAddr.parsehost: '%s' did not resolve to 
one of the supported address family" %
+                raise PolicyError("HostStruct: '%s' did not resolve to one of 
the supported address family" %
                         hostname)
-            packed = socket.inet_pton(family, saddr)
-            name = hostname
-            if not name == saddr:
-                name += "(" + saddr + ")"
-            return self.HostStruct(name, sfamily, packed)
+            self.name = hostname
+            self.saddr = saddr
+            self.family = sfamily
+            self.binary = socket.inet_pton(family, saddr)
+            return
         except Exception, e:
-            raise PolicyError("HostAddr.parsehost: '%s' failed to resolve: 
'%s'" %
+            raise PolicyError("HostStruct: '%s' failed to resolve: '%s'" %
                               (hostname, e))
 
+    def __str__(self):
+        return self.name
+
+    def __repr__(self):
+        return self.__str__()
+
+    def dump(self):
+        return ("(%s, %s, %s, %s)" %
+                (self.name,
+                 self.saddr,
+                 "AF_INET" if self.family == socket.AF_INET else "AF_INET6",
+                 binascii.hexlify(self.binary)))
+
+#
+#
+class HostAddr():
+    """
+    Provide HostIP address ranges and comparison functions.
+    A HostIP may be:
+    - single address:      10.10.1.1
+    - a pair of addresses: 10.10.0.0,10.10.255.255
+    Only IPv4 and IPv6 are supported.
+    - No unix sockets.
+    HostIP names must resolve to a single IP address.
+    Address pairs define a range.
+    - The second address must be numerically larger than the first address.
+    - The addresses must be of the same address 'family', IPv4 or IPv6.
+    IPv6 support is conditional based on underlying OS network options.
+    Raises a PolicyError on validation error in constructor.
+    """
+
+    def has_ipv6(self):
+        return socket.has_ipv6
+
     def __init__(self, hostspec):
         """
         Parse host spec into binary structures to use for comparisons.
@@ -180,10 +202,9 @@ class HostAddr():
         # hosts must contain one or two host specs
         if len(hosts) not in [1, 2]:
             raise PolicyError("hostspec must contain 1 or 2 host names")
-
-        self.hoststructs.append(self.parsehost(hosts[0]))
+        self.hoststructs.append(HostStruct(hosts[0]))
         if len(hosts) > 1:
-            self.hoststructs.append(self.parsehost(hosts[1]))
+            self.hoststructs.append(HostStruct(hosts[1]))
             if not self.hoststructs[0].family == self.hoststructs[1].family:
                 raise PolicyError("mixed IPv4 and IPv6 host specs in range not 
allowed")
             c0 = self.memcmp(self.hoststructs[0].binary, 
self.hoststructs[1].binary)
@@ -199,16 +220,10 @@ class HostAddr():
     def __repr__(self):
         return self.__str__()
 
-    def dumpstruct(self, hstruct):
-        return ("(%s, %s, %s)" %
-                (hstruct.text,
-                 "AF_INET" if hstruct.family == socket.AF_INET else "AF_INET6",
-                 binascii.hexlify(hstruct.binary)))
-
     def dump(self):
-        res = "(" + self.dumpstruct(self.hoststructs[0])
+        res = "(" + self.hoststructs[0].dump()
         if len(self.hoststructs) > 1:
-            res += "," + self.dumpstruct(self.hoststructs[1])
+            res += "," + self.hoststructs[1].dump()
         res += ")"
         return res
 
@@ -223,24 +238,40 @@ class HostAddr():
                 break
         return res
 
-    def match(self, candidate):
+    def match_bin(self, cstruct):
         """
-        Does the candidate match the IP or range of IP addresses represented 
by this?
-        @param[in] candidate the IP address to be tested
+        Does the candidate hoststruct match the IP or range of IP addresses 
represented by this?
+        @param[in] cstruct the IP address to be tested
         @return candidate matches this or not
         """
         try:
-            host = self.parsehost(candidate)
-            if not host.family == self.hoststructs[0].family:
+            if not cstruct.family == self.hoststructs[0].family:
                 # sorry, wrong AF_INET family
                 return False
-            c0 = self.memcmp(host.binary, self.hoststructs[0].binary)
+            c0 = self.memcmp(cstruct.binary, self.hoststructs[0].binary)
             if len(self.hoststructs) == 1:
                 return c0 == 0
-            c1 = self.memcmp(host.binary, self.hoststructs[1].binary)
+            c1 = self.memcmp(cstruct.binary, self.hoststructs[1].binary)
             return c0 >= 0 and c1 <= 0
         except PolicyError:
             return False
+        except Exception, e:
+            assert isinstance(cstruct, HostStruct), \
+                ("Wrong type. Expected HostStruct but received %s" % 
cstruct.__class__.__name__)
+            return False
+
+    def match_str(self, candidate):
+        """
+        Does the candidate string match the IP or range represented by this?
+        @param[in] candidate the IP address to be tested
+        @return candidate matches this or not
+        """
+        try:
+            hoststruct = HostStruct(candidate)
+        except PolicyError:
+            return False
+        return self.match_bin(hoststruct)
+
 #
 #
 class PolicyCompiler():

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3e9a37ea/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index dece8c9..6e2878c 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -30,7 +30,7 @@ from proton.utils import BlockingConnection, LinkDetached
 from qpid_dispatch.management.client import Node
 from system_test import TIMEOUT
 
-from qpid_dispatch_internal.management.policy import Policy, HostAddr, 
PolicyError
+from qpid_dispatch_internal.management.policy import Policy, HostAddr, 
PolicyError, HostStruct
 
 class AbsoluteConnectionCountLimit(TestCase):
     """
@@ -82,23 +82,34 @@ class PolicyHostAddrTest(TestCase):
     def expect_deny(self, badhostname, msg):
         denied = False
         try:
-            xxx = HostAddr(badhostname)
+            xxx = HostStruct(badhostname)
         except PolicyError:
             denied = True
-        self.assertTrue(denied) # msg
+        self.assertTrue(denied, ("%s" % msg))
+
+    def check_hostaddr_match(self, tHostAddr, tString, expectOk=True):
+        # check that the string is a match for the addr
+        # check that the internal struct version matches, too
+        ha = HostStruct(tString)
+        if expectOk:
+            self.assertTrue( tHostAddr.match_str(tString) )
+            self.assertTrue( tHostAddr.match_bin(ha) )
+        else:
+            self.assertFalse( tHostAddr.match_str(tString) )
+            self.assertFalse( tHostAddr.match_bin(ha) )
 
     def test_policy_hostaddr_ipv4(self):
         # Create simple host and range
         aaa = HostAddr("192.168.1.1")
         bbb = HostAddr("1.1.1.1,1.1.1.255")
         # Verify host and range
-        self.assertTrue ( aaa.match("192.168.1.1") )
-        self.assertFalse( aaa.match("1.1.1.1") )
-        self.assertFalse( aaa.match("192.168.1.2") )
-        self.assertTrue ( bbb.match("1.1.1.1") )
-        self.assertTrue ( bbb.match("1.1.1.254") )
-        self.assertFalse( bbb.match("1.1.1.0") )
-        self.assertFalse( bbb.match("1.1.2.0") )
+        self.check_hostaddr_match(aaa, "192.168.1.1")
+        self.check_hostaddr_match(aaa, "1.1.1.1", False)
+        self.check_hostaddr_match(aaa, "192.168.1.2", False)
+        self.check_hostaddr_match(bbb, "1.1.1.1")
+        self.check_hostaddr_match(bbb, "1.1.1.254")
+        self.check_hostaddr_match(bbb, "1.1.1.0", False)
+        self.check_hostaddr_match(bbb, "1.1.2.0", False)
 
     def test_policy_hostaddr_ipv6(self):
         if not HostAddr.has_ipv6:
@@ -108,17 +119,17 @@ class PolicyHostAddrTest(TestCase):
         bbb = HostAddr("::1,::ffff")
         ccc = HostAddr("ffff::0,ffff:ffff::0")
         # Verify host and range
-        self.assertTrue ( aaa.match("::1") )
-        self.assertFalse( aaa.match("::2") )
-        self.assertFalse( aaa.match("ffff:ffff::0") )
-        self.assertTrue ( bbb.match("::1") )
-        self.assertTrue ( bbb.match("::fffe") )
-        self.assertFalse( bbb.match("::1:0") )
-        self.assertFalse( bbb.match("ffff::0") )
-        self.assertTrue ( ccc.match("ffff::1") )
-        self.assertTrue ( ccc.match("ffff:fffe:ffff:ffff::ffff") )
-        self.assertFalse( ccc.match("ffff:ffff:1") )
-        self.assertFalse( ccc.match("ffff:ffff:ffff:ffff::ffff") )
+        self.check_hostaddr_match(aaa, "::1")
+        self.check_hostaddr_match(aaa, "::2", False)
+        self.check_hostaddr_match(aaa, "ffff:ffff::0", False)
+        self.check_hostaddr_match(bbb, "::1")
+        self.check_hostaddr_match(bbb, "::fffe")
+        self.check_hostaddr_match(bbb, "::1:0", False)
+        self.check_hostaddr_match(bbb, "ffff::0", False)
+        self.check_hostaddr_match(ccc, "ffff::1")
+        self.check_hostaddr_match(ccc, "ffff:fffe:ffff:ffff::ffff")
+        self.check_hostaddr_match(ccc, "ffff:ffff::1", False)
+        self.check_hostaddr_match(ccc, "ffff:ffff:ffff:ffff::ffff", False)
 
     def test_policy_malformed_hostaddr_ipv4(self):
         self.expect_deny( "0.0.0.0.0", "Name or service not known")


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to