You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ch...@apache.org on 2015/12/16 23:28:40 UTC
qpid-dispatch git commit: Break utility code into separate source
module.
Repository: qpid-dispatch
Updated Branches:
refs/heads/crolke-DISPATCH-188-1 6faf3da50 -> 3256a51c8
Break utility code into separate source module.
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/3256a51c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/3256a51c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/3256a51c
Branch: refs/heads/crolke-DISPATCH-188-1
Commit: 3256a51c8cd00bfbe1fc4a17ea8f72eb841cb49f
Parents: 6faf3da
Author: Chuck Rolke <cr...@redhat.com>
Authored: Wed Dec 16 17:27:57 2015 -0500
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Wed Dec 16 17:27:57 2015 -0500
----------------------------------------------------------------------
.../qpid_dispatch_internal/management/policy.py | 298 +----------------
.../management/policy_util.py | 335 +++++++++++++++++++
tests/system_tests_policy.py | 46 ++-
3 files changed, 370 insertions(+), 309 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3256a51c/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 c07b891..185b60c 100644
--- a/python/qpid_dispatch_internal/management/policy.py
+++ b/python/qpid_dispatch_internal/management/policy.py
@@ -18,17 +18,15 @@
#
"""
-Utilities for command-line programs.
+
"""
-import sys, optparse, os
+import sys, os
import ConfigParser
-from collections import Sequence, Mapping, namedtuple
-from qpid_dispatch_site import VERSION
+import optparse
+from policy_util import PolicyError, HostStruct, HostAddr, PolicyAppConnectionMgr
import pdb #; pdb.set_trace()
import ast
-import socket
-import binascii
@@ -98,195 +96,6 @@ Internal Policy:
#
#
-class PolicyError(Exception):
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-#
-#
-class HostStruct():
- """
- 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"]
- if socket.has_ipv6:
- families.append(socket.AF_INET6)
- famnames.append("IPv6")
-
- def __init__(self, hostname):
- """
- Given a host name text string, return the socket info for it.
- @param[in] hostname host IP address to parse
- """
- try:
- res = socket.getaddrinfo(hostname, 0)
- if len(res) == 0:
- raise PolicyError("HostStruct: '%s' did not resolve to an IP address" % hostname)
- foundFirst = False
- saddr = ""
- sfamily = socket.AF_UNSPEC
- for i0 in range(0, len(res)):
- family, dum0, dum1, dum2, sockaddr = res[i0]
- if not foundFirst:
- if family in self.families:
- saddr = sockaddr[0]
- sfamily = family
- foundFirst = True
- else:
- if family in self.families:
- if not saddr == sockaddr[0] or not sfamily == family:
- raise PolicyError("HostStruct: '%s' resolves to multiple IP addresses" %
- hostname)
-
- if not foundFirst:
- raise PolicyError("HostStruct: '%s' did not resolve to one of the supported address family" %
- hostname)
- self.name = hostname
- self.saddr = saddr
- self.family = sfamily
- self.binary = socket.inet_pton(family, saddr)
- return
- except Exception, e:
- 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.
- Validate the hostspec to enforce usage rules.
- """
- self.hoststructs = []
-
- if hostspec == "*":
- self.wildcard = True
- else:
- self.wildcard = False
-
- hosts = [x.strip() for x in hostspec.split(",")]
-
- # 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(HostStruct(hosts[0]))
- if len(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)
- if c0 > 0:
- raise PolicyError("host specs in range must have lower numeric address first")
-
- def __str__(self):
- if self.wildcard:
- return "*"
- res = self.hoststructs[0].name
- if len(self.hoststructs) > 1:
- res += "," + self.hoststructs[1].name
- return res
-
- def __repr__(self):
- return self.__str__()
-
- def dump(self):
- if self.wildcard:
- return "(*)"
- res = "(" + self.hoststructs[0].dump()
- if len(self.hoststructs) > 1:
- res += "," + self.hoststructs[1].dump()
- res += ")"
- return res
-
- def memcmp(self, a, b):
- res = 0
- for i in range(0,len(a)):
- if a[i] > b[i]:
- res = 1
- break;
- elif a[i] < b[i]:
- res = -1
- break
- return res
-
- def match_bin(self, cstruct):
- """
- 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
- """
- if self.wildcard:
- return True
- try:
- if not cstruct.family == self.hoststructs[0].family:
- # sorry, wrong AF_INET family
- return False
- c0 = self.memcmp(cstruct.binary, self.hoststructs[0].binary)
- if len(self.hoststructs) == 1:
- return c0 == 0
- 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 PolicyKeys():
# Internal policy key words
KW_POLICY_VERSION = "policyVersion"
@@ -544,103 +353,6 @@ class PolicyCompiler():
return False
return True
-class PolicyConnStatsPerApp():
- """
- Track policy user/host connection statistics for one app
- connections : 5
- max_t : 20
- max_u : 5
- max_h : 10
- host_aggr : { 'host1' : [conn1, conn2, conn3],
- 'host2' : [conn4, conn5] }
- user_aggr : { 'user1' : [conn1, conn2, conn3],
- 'user2' : [conn4, conn5] }
- """
- def __init__(self, maxconn, maxconnperuser, maxconnperhost):
- """
- The object is constructed with the policy limits
- for total, total per user, and total per host counts.
- As connections are allowed they are tracked in
- aggregation maps.
- """
- self.connections = 0
- if maxconn < 0 or maxconnperuser < 0 or maxconnperhost < 0:
- raise PolicyError("PolicyConnStatsPerApp settings must be >= 0")
- self.max_t = maxconn
- self.max_u = maxconnperuser
- self.max_h = maxconnperhost
- self.user_aggr = {}
- self.host_aggr = {}
-
- def __str__(self):
- pdb.set_trace()
- res = ("Connection Limits: Total: %s, Per User: %s, Per Host: %s\n" %
- (self.max_t, self.max_u, self.max_h))
- res += ("User counts: %s\n" % self.user_aggr)
- res += ("Host counts: %s" % self.host_aggr)
- return res
-
- def __repr__(self):
- return self.__str__()
-
- def update(self, maxconn, maxconnperuser, maxconnperhost):
- if maxconn < 0 or maxconnperuser < 0 or maxconnperhost < 0:
- raise PolicyError("PolicyConnStatsPerApp settings must be >= 0")
- self.max_t = maxconn
- self.max_u = maxconnperuser
- self.max_h = maxconnperhost
-
- def can_connect(self, conn_id, user, host, diags):
- """
- Register a connection attempt.
- If all the connection rules pass then add the
- user/host to the connection tables
- """
- n_user = 0
- if user in self.user_aggr:
- n_user = len(self.user_aggr[user])
- n_host = 0
- if host in self.host_aggr:
- n_host = len(self.host_aggr[host])
-
- allowbytotal = self.max_t == 0 or self.connections < self.max_t
- allowbyuser = self.max_u == 0 or n_user < self.max_u
- allowbyhost = self.max_h == 0 or n_host < self.max_h
-
- if allowbytotal and allowbyuser and allowbyhost:
- self.connections += 1
- if not user in self.user_aggr:
- self.user_aggr[user] = []
- self.user_aggr[user].append(conn_id)
- if not host in self.host_aggr:
- self.host_aggr[host] = []
- self.host_aggr[host].append(conn_id)
- return True
- else:
- if not allowbytotal:
- diags.append("LogMe: INFO user '%s' from host '%s' denied connection by total connection limit" %
- (user, host))
- if not allowbyuser:
- diags.append("LogMe: INFO user '%s' from host '%s' denied connection by per user limit" %
- (user, host))
- if not allowbyhost:
- diags.append("LogMe: INFO user '%s' from host '%s' denied connection by per host limit" %
- (user, host))
- return False
-
- def disconnect(self, conn_id, user, host):
- """
- Unregister a connection
- """
- assert(self.connections > 0)
- assert(user in self.user_aggr)
- assert(conn_id in self.user_aggr[user])
- assert(host in self.host_aggr)
- assert(conn_id in self.host_aggr[host])
- self.connections -= 1
- self.user_aggr[user].remove(conn_id)
- self.host_aggr[host].remove(conn_id)
-
class Policy():
"""
The policy database.
@@ -736,7 +448,7 @@ class Policy():
if c in self.stats:
self.stats[c].update(c_max, c_max_u, c_max_h)
else:
- self.stats[c] = PolicyConnStatsPerApp(c_max, c_max_u, c_max_h)
+ self.stats[c] = PolicyAppConnectionMgr(c_max, c_max_u, c_max_h)
self.data.update(newpolicies)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3256a51c/python/qpid_dispatch_internal/management/policy_util.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/policy_util.py b/python/qpid_dispatch_internal/management/policy_util.py
new file mode 100644
index 0000000..681743d
--- /dev/null
+++ b/python/qpid_dispatch_internal/management/policy_util.py
@@ -0,0 +1,335 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License
+#
+
+import sys, os
+import socket
+import binascii
+
+
+#
+#
+class PolicyError(Exception):
+ def __init__(self, value):
+ self.value = value
+ def __str__(self):
+ return repr(self.value)
+
+#
+#
+class HostStruct():
+ """
+ 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"]
+ if socket.has_ipv6:
+ families.append(socket.AF_INET6)
+ famnames.append("IPv6")
+
+ def __init__(self, hostname):
+ """
+ Given a host name text string, return the socket info for it.
+ @param[in] hostname host IP address to parse
+ """
+ try:
+ res = socket.getaddrinfo(hostname, 0)
+ if len(res) == 0:
+ raise PolicyError("HostStruct: '%s' did not resolve to an IP address" % hostname)
+ foundFirst = False
+ saddr = ""
+ sfamily = socket.AF_UNSPEC
+ for i0 in range(0, len(res)):
+ family, dum0, dum1, dum2, sockaddr = res[i0]
+ if not foundFirst:
+ if family in self.families:
+ saddr = sockaddr[0]
+ sfamily = family
+ foundFirst = True
+ else:
+ if family in self.families:
+ if not saddr == sockaddr[0] or not sfamily == family:
+ raise PolicyError("HostStruct: '%s' resolves to multiple IP addresses" %
+ hostname)
+
+ if not foundFirst:
+ raise PolicyError("HostStruct: '%s' did not resolve to one of the supported address family" %
+ hostname)
+ self.name = hostname
+ self.saddr = saddr
+ self.family = sfamily
+ self.binary = socket.inet_pton(family, saddr)
+ return
+ except Exception, e:
+ 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
+ - a wildcard: *
+ 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.
+ The wildcard '*' matches all address 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.
+ Validate the hostspec to enforce usage rules.
+ """
+ self.hoststructs = []
+
+ if hostspec == "*":
+ self.wildcard = True
+ else:
+ self.wildcard = False
+
+ hosts = [x.strip() for x in hostspec.split(",")]
+
+ # 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(HostStruct(hosts[0]))
+ if len(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)
+ if c0 > 0:
+ raise PolicyError("host specs in range must have lower numeric address first")
+
+ def __str__(self):
+ if self.wildcard:
+ return "*"
+ res = self.hoststructs[0].name
+ if len(self.hoststructs) > 1:
+ res += "," + self.hoststructs[1].name
+ return res
+
+ def __repr__(self):
+ return self.__str__()
+
+ def dump(self):
+ if self.wildcard:
+ return "(*)"
+ res = "(" + self.hoststructs[0].dump()
+ if len(self.hoststructs) > 1:
+ res += "," + self.hoststructs[1].dump()
+ res += ")"
+ return res
+
+ def memcmp(self, a, b):
+ res = 0
+ for i in range(0,len(a)):
+ if a[i] > b[i]:
+ res = 1
+ break;
+ elif a[i] < b[i]:
+ res = -1
+ break
+ return res
+
+ def match_bin(self, candidate):
+ """
+ Does the candidate hoststruct match the IP or range of IP addresses represented by this?
+ @param[in] candidate the IP address to be tested
+ @return candidate matches this or not
+ """
+ if self.wildcard:
+ return True
+ try:
+ if not candidate.family == self.hoststructs[0].family:
+ # sorry, wrong AF_INET family
+ return False
+ c0 = self.memcmp(candidate.binary, self.hoststructs[0].binary)
+ if len(self.hoststructs) == 1:
+ return c0 == 0
+ c1 = self.memcmp(candidate.binary, self.hoststructs[1].binary)
+ return c0 >= 0 and c1 <= 0
+ except PolicyError:
+ return False
+ except Exception, e:
+ assert isinstance(candidate, HostStruct), \
+ ("Wrong type. Expected HostStruct but received %s" % candidate.__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 PolicyAppConnectionMgr():
+ """
+ Track policy user/host connection limits and statistics for one app.
+ # limits - set at creation and by update()
+ max_total : 20
+ max_per_user : 5
+ max_per_host : 10
+ # statistics - maintained for the lifetime of corresponding application
+ connections_approved : N
+ connections_denied : N
+ # live state - maintained for the lifetime of corresponding application
+ connections_active : 5
+ per_host_state : { 'host1' : [conn1, conn2, conn3],
+ 'host2' : [conn4, conn5] }
+ per_user_state : { 'user1' : [conn1, conn2, conn3],
+ 'user2' : [conn4, conn5] }
+ """
+ def __init__(self, maxconn, maxconnperuser, maxconnperhost):
+ """
+ The object is constructed with the policy limits and zeroed counts.
+ @param[in] maxconn maximum total concurrent connections
+ @param[in] maxconnperuser maximum total conncurrent connections for each user
+ @param[in] maxconnperuser maximum total conncurrent connections for each host
+ """
+ if maxconn < 0 or maxconnperuser < 0 or maxconnperhost < 0:
+ raise PolicyError("PolicyAppConnectionMgr settings must be >= 0")
+ self.max_total = maxconn
+ self.max_per_user = maxconnperuser
+ self.max_per_host = maxconnperhost
+ self.connections_approved = 0
+ self.connections_denied = 0
+ self.connections_active = 0
+ self.per_host_state = {}
+ self.per_user_state = {}
+
+ def __str__(self):
+ res = ("Connection Limits: total: %s, per user: %s, per host: %s\n" %
+ (self.max_total, self.max_per_user, self.max_per_host))
+ res += ("Connections Statistics: total approved: %s, total denied: %s" %
+ (self.connections_approved, self.connections_denied))
+ res += ("Connection State: total current: %s" % self.connections_active)
+ res += ("User state: %s\n" % self.per_user_state)
+ res += ("Host state: %s" % self.per_host_state)
+ return res
+
+ def __repr__(self):
+ return self.__str__()
+
+ def update(self, maxconn, maxconnperuser, maxconnperhost):
+ """
+ Reset connection limits
+ @param[in] maxconn maximum total concurrent connections
+ @param[in] maxconnperuser maximum total conncurrent connections for each user
+ @param[in] maxconnperuser maximum total conncurrent connections for each host
+ """
+ if maxconn < 0 or maxconnperuser < 0 or maxconnperhost < 0:
+ raise PolicyError("PolicyAppConnectionMgr settings must be >= 0")
+ self.max_total = maxconn
+ self.max_per_user = maxconnperuser
+ self.max_per_host = maxconnperhost
+
+ def can_connect(self, conn_id, user, host, diags):
+ """
+ Register a connection attempt.
+ If all the connection limit rules pass then add the
+ user/host to the connection tables.
+ @param[in] conn_id unique ID for connection, usually IP:port
+ @param[in] user authenticated user ID
+ @param[in] host IP address of host
+ @param[out] diags on failure holds 1, 2, or 3 error strings
+ @return connection is allowed and tracked in state tables
+ """
+ n_user = 0
+ if user in self.per_user_state:
+ n_user = len(self.per_user_state[user])
+ n_host = 0
+ if host in self.per_host_state:
+ n_host = len(self.per_host_state[host])
+
+ allowbytotal = self.max_total == 0 or self.connections_active < self.max_total
+ allowbyuser = self.max_per_user == 0 or n_user < self.max_per_user
+ allowbyhost = self.max_per_host == 0 or n_host < self.max_per_host
+
+ if allowbytotal and allowbyuser and allowbyhost:
+ if not user in self.per_user_state:
+ self.per_user_state[user] = []
+ self.per_user_state[user].append(conn_id)
+ if not host in self.per_host_state:
+ self.per_host_state[host] = []
+ self.per_host_state[host].append(conn_id)
+ self.connections_active += 1
+ self.connections_approved += 1
+ return True
+ else:
+ if not allowbytotal:
+ diags.append("LogMe: INFO user '%s' from host '%s' denied connection by total connection limit" %
+ (user, host))
+ if not allowbyuser:
+ diags.append("LogMe: INFO user '%s' from host '%s' denied connection by per user limit" %
+ (user, host))
+ if not allowbyhost:
+ diags.append("LogMe: INFO user '%s' from host '%s' denied connection by per host limit" %
+ (user, host))
+ self.connections_denied += 1
+ return False
+
+ def disconnect(self, conn_id, user, host):
+ """
+ Unregister a connection
+ """
+ assert(self.connections_active > 0)
+ assert(user in self.per_user_state)
+ assert(conn_id in self.per_user_state[user])
+ assert(host in self.max_per_host)
+ assert(conn_id in self.max_per_host[host])
+ self.connections_active -= 1
+ self.per_user_state[user].remove(conn_id)
+ self.per_host_state[host].remove(conn_id)
+
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3256a51c/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index 6f195b3..0ef7356 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -30,8 +30,10 @@ from proton.utils import BlockingConnection, LinkDetached
from qpid_dispatch.management.client import Node
from system_test import TIMEOUT
+from qpid_dispatch_internal.management.policy_util import \
+ HostAddr, PolicyError, HostStruct, PolicyAppConnectionMgr
from qpid_dispatch_internal.management.policy import \
- Policy, HostAddr, PolicyError, HostStruct, PolicyConnStatsPerApp
+ Policy
class AbsoluteConnectionCountLimit(TestCase):
"""
@@ -233,34 +235,34 @@ class PolicyFile(TestCase):
for s in addrs: self.assertTrue(s in upolicy['targets'])
for s in addrs: self.assertTrue(s in upolicy['sources'])
-class PolicyConnStatsPerAppTests(TestCase):
+class PolicyAppConnectionMgrTests(TestCase):
- def test_policy_app_conn_stats_fail_by_total(self):
- stats = PolicyConnStatsPerApp(1, 2, 2)
+ def test_policy_app_conn_mgr_fail_by_total(self):
+ stats = PolicyAppConnectionMgr(1, 2, 2)
diags = []
self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', '10.10.10.10', diags))
self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', '10.10.10.10', diags))
self.assertTrue(len(diags) == 1)
self.assertTrue('by total' in diags[0])
- def test_policy_app_conn_stats_fail_by_user(self):
- stats = PolicyConnStatsPerApp(3, 1, 2)
+ def test_policy_app_conn_mgr_fail_by_user(self):
+ stats = PolicyAppConnectionMgr(3, 1, 2)
diags = []
self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', '10.10.10.10', diags))
self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', '10.10.10.10', diags))
self.assertTrue(len(diags) == 1)
self.assertTrue('per user' in diags[0])
- def test_policy_app_conn_stats_fail_by_hosts(self):
- stats = PolicyConnStatsPerApp(3, 2, 1)
+ def test_policy_app_conn_mgr_fail_by_hosts(self):
+ stats = PolicyAppConnectionMgr(3, 2, 1)
diags = []
self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', '10.10.10.10', diags))
self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', '10.10.10.10', diags))
self.assertTrue(len(diags) == 1)
self.assertTrue('per host' in diags[0])
- def test_policy_app_conn_stats_fail_by_user_hosts(self):
- stats = PolicyConnStatsPerApp(3, 1, 1)
+ def test_policy_app_conn_mgr_fail_by_user_hosts(self):
+ stats = PolicyAppConnectionMgr(3, 1, 1)
diags = []
self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', '10.10.10.10', diags))
self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', '10.10.10.10', diags))
@@ -268,8 +270,8 @@ class PolicyConnStatsPerAppTests(TestCase):
self.assertTrue('per user' in diags[0] or 'per user' in diags[1])
self.assertTrue('per host' in diags[0] or 'per host' in diags[1])
- def test_policy_app_conn_stats_update(self):
- stats = PolicyConnStatsPerApp(3, 1, 2)
+ def test_policy_app_conn_mgr_update(self):
+ stats = PolicyAppConnectionMgr(3, 1, 2)
diags = []
self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', '10.10.10.10', diags))
self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', '10.10.10.10', diags))
@@ -279,18 +281,18 @@ class PolicyConnStatsPerAppTests(TestCase):
stats.update(3, 2, 2)
self.assertTrue(stats.can_connect('10.10.10.10:10001', 'chuck', '10.10.10.10', diags))
- def test_policy_app_conn_stats_create_bad_settings(self):
+ def test_policy_app_conn_mgr_create_bad_settings(self):
denied = False
try:
- stats = PolicyConnStatsPerApp(-3, 1, 2)
+ stats = PolicyAppConnectionMgr(-3, 1, 2)
except PolicyError:
denied = True
self.assertTrue(denied, "Failed to detect negative setting value.")
- def test_policy_app_conn_stats_update_bad_settings(self):
+ def test_policy_app_conn_mgr_update_bad_settings(self):
denied = False
try:
- stats = PolicyConnStatsPerApp(0, 0, 0)
+ stats = PolicyAppConnectionMgr(0, 0, 0)
except PolicyError:
denied = True
self.assertFalse(denied, "Should allow all zeros.")
@@ -300,5 +302,17 @@ class PolicyConnStatsPerAppTests(TestCase):
denied = True
self.assertTrue(denied, "Failed to detect negative setting value.")
+ def test_policy_app_conn_mgr_larger_counts(self):
+ stats = PolicyAppConnectionMgr(10000, 10000, 10000)
+ diags = []
+ for i in range(0, 10000):
+ self.assertTrue(stats.can_connect('1.1.1.1:' + str(i), 'chuck', '1.1.1.1', diags))
+ self.assertTrue(len(diags) == 0)
+ self.assertFalse(stats.can_connect('1.1.1.1:10000', 'chuck', '1.1.1.1', diags))
+ self.assertTrue(len(diags) == 3)
+ self.assertTrue(stats.connections_active == 10000)
+ self.assertTrue(stats.connections_approved == 10000)
+ self.assertTrue(stats.connections_denied == 1)
+
if __name__ == '__main__':
unittest.main(main_module())
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org