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 2016/01/09 00:08:14 UTC

qpid-dispatch git commit: Add management object structs for policy. Convert policy config files to json format. Rename policy roles to groups.

Repository: qpid-dispatch
Updated Branches:
  refs/heads/crolke-DISPATCH-188-1 d59f02bb0 -> 0d6ce1375


Add management object structs for policy.
Convert policy config files to json format.
Rename policy roles to groups.


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

Branch: refs/heads/crolke-DISPATCH-188-1
Commit: 0d6ce1375c593f88119414490bc56fc9b88fdd7a
Parents: d59f02b
Author: Chuck Rolke <cr...@redhat.com>
Authored: Fri Jan 8 18:06:10 2016 -0500
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Jan 8 18:06:10 2016 -0500

----------------------------------------------------------------------
 python/qpid_dispatch/management/qdrouter.json   | 148 ++++++++++++-
 .../qpid_dispatch_internal/management/policy.py | 208 +++++++------------
 tests/policy-1/policy-photoserver.conf          | 149 -------------
 tests/policy-1/policy-photoserver.json          | 106 ++++++++++
 tests/system_tests_policy.py                    |   4 +-
 5 files changed, 333 insertions(+), 282 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0d6ce137/python/qpid_dispatch/management/qdrouter.json
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index eb8e599..87c45ef 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -1008,13 +1008,13 @@
                 "maximumConnections": {
                     "type": "integer",
                     "default": 0,
-                    "description": "The maximum number of concurrent client connections allowed. Zero implies no limit.",
+                    "description": "The maximum number of concurrent client connections allowed to this router. Zero implies no limit.",
                     "required": false,
                     "create": true
                 },
                 "policyDb": {
                     "type": "path",
-                    "description": "The path to the folder that holds policy definition files.",
+                    "description": "The path to the folder that holds local policy definition files.",
 		    "required": false,
                     "create": true
                 },
@@ -1024,6 +1024,150 @@
             }
         },
 
+        "policy.appConnections": {
+            "description": "Defines per application connection limits, counts, and state.",
+            "extends": "operationalEntity",
+            "attributes": {
+                "appName": {
+                    "type": "string",
+                    "description": "Application to which these statistics apply",
+                    "create": true
+                },
+
+                "maxConnections": {
+                    "type": "integer",
+                    "description": "The maximum number of concurrent client connections allowed to this application. Zero implies no limit."
+                    },
+                "maxConnPerUser": {
+                    "type": "integer",
+                    "description": "The maximum number of concurrent connections allowed to this application for a single authenticated user. Zero implies no limit."
+                    },
+                "maxConnPerHost": {
+                    "type": "integer",
+                    "description": "The maximum number of concurrent connections allowed to this application from a remote host. Zero implies no limit."
+                },
+
+                "connectionsApproved": {"type": "integer", "graph": true},
+                "connectionsDenied": {"type": "integer", "graph": true},
+                "connectionsActive": {"type": "integer", "graph": true},
+                "perUserState": {
+                    "type": "map",
+                    "description": "Index is authenticated username; data is comma separated string naming the user's connections."
+                },
+                "perHostState": {
+                    "type": "map",
+                    "description": "Index is remote host; data is comma separated string naming the host's connections."
+                }
+            }
+        },
+
+        "policy.appStatistics": {
+            "description": "Aggregated statistics for one application.",
+            "extends": "operationalEntity",
+            "attributes": {
+                "appName": {
+                    "type": "string",
+                    "description": "Application to which these statistics apply",
+                    "create": true
+                },
+
+                "maxSendersDenials": {"type": "integer", "graph": true},
+                "maxReceiversDenials": {"type": "integer", "graph": true},
+                "dynamicSrcDenials": {"type": "integer", "graph": true},
+                "anonmousSenderDenials": {"type": "integer", "graph": true},
+                "sourceDenials": {"type": "integer", "graph": true},
+                "targetsDenials": {"type": "integer", "graph": true}
+            }
+        },
+
+        "policy.appGroupSettings": {
+            "description": "Defines control values for a group of users in one application",
+            "extends": "configurationEntity",
+            "attributes": {
+                "appName": {
+                    "type": "string",
+                    "description": "Application to which these settings apply",
+                    "create": true
+                },
+                "appGroupName": {
+                    "type": "string",
+                    "description": "Rule set name",
+                    "create": true
+                },
+
+                "maxFrameSize": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "Largest frame that may be used on this connection. Value placed into forwarded AMQP Open.max-frame-size field. Zero implies inserting system default.",
+                    "required": false,
+                    "create": true
+                },
+                "maxMessageSize": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "Largest message that may be used on this connection. Value placed into forwarded AMQP Attach.max-message-size field. Zero implies inserting system default.",
+                    "required": false,
+                    "create": true
+                },
+                "maxSessionWindow": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "Largest incoming and outgoing window that may be used on this connection. Value placed into forwarded AMQP Begin.incoming-window and .outgoing-window fields. Zero implies inserting system default.",
+                    "required": false,
+                    "create": true
+                },
+                "maxSessions": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "Maximum number of simultaneous sessions that may be used on this connection. Value placed into forwarded AMQP Open.channel-max field. Zero implies inserting system default.",
+                    "required": false,
+                    "create": true
+                },
+                "maxSenders": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "Maximum number of simultaneous senders that may be used on this connection. Zero implies system default.",
+                    "required": false,
+                    "create": true
+                },
+                "maxReceivers": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "Maximum number of simultaneous receivers that may be used on this connection. Zero implies system default.",
+                    "required": false,
+                    "create": true
+                },
+                "allowDynamicSrc": {
+                    "type": "boolean",
+                    "default": false,
+                    "description": "A receiver link created on this connection is allowed to set the dynamic flag to true.",
+                    "required": false,
+                    "create": true
+                },
+                "allowAnonymousSender": {
+                    "type": "boolean",
+                    "default": false,
+                    "description": "A sender link created on this connection is allowed to have a blank target address.",
+                    "required": false,
+                    "create": true
+                },
+                "sources": {
+                    "type": "string",
+                    "default": 0,
+                    "description": "Comma separated list of allowed source addresses to be specified by receive links. A blank list denies all access. A list with a single wildcard address '*' allows all access. Simple beginsWith and endsWith may be specified by prefixing and postfixing a string with '*'. Username substitution is supported by using the $USER token in a string.",
+                    "required": false,
+                    "create": true
+                },
+                "targets": {
+                    "type": "string",
+                    "default": 0,
+                    "description": "Comma separated list of allowed target addresses to be specified by sending links. A blank list denies all access. A list with a single wildcard address '*' allows all access. Simple beginsWith and endsWith may be specified by prefixing and postfixing a string with '*'. Username substitution is supported by using the $USER token in a string.",
+                    "required": false,
+                    "create": true
+                }
+            }
+        },
+
         "dummy": {
             "description": "Dummy entity for test purposes.",
             "extends": "entity",

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0d6ce137/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 501dd16..f29cc3f 100644
--- a/python/qpid_dispatch_internal/management/policy.py
+++ b/python/qpid_dispatch_internal/management/policy.py
@@ -22,11 +22,10 @@
 """
 
 import sys, os
-import ConfigParser
+import json
 import optparse
 from policy_util import PolicyError, HostStruct, HostAddr, PolicyAppConnectionMgr
 import pdb #; pdb.set_trace()
-import ast
 
 
 
@@ -35,60 +34,15 @@ Entity implementing the business logic of user connection/access policy.
 
 Policy is represented several ways:
 
-1. External       : ConfigParser-format file
-2. CRUD Interface : ConfigParser file section: name, [(name, value), ...]
-3. Internal       : dictionary
-
-For example:
-
-1. External
-
-The External Policy is a plain ascii text file formatted for processing
-by ConfigParser.
-
-External Policy:
-----------------
-
-    [photoserver]
-    schemaVersion            : 1
-    policyVersion            : 1
-    roles: {
-      'users'           : ['u1', 'u2'],
-      'paidsubscribers' : ['p1', 'p2']
-      }
-
-2. CRUD Interface
-
-At the CRUD Create function the policy is represented by two strings:
-- name : name of the ConfigParser section which is the application name
-- data : ConfigParser section as a string
-
-The CRUD Interface policy is created by ConfigParser.read(externalFile)
-and then iterating through the config parser sections.
-
-CRUD Interface Policy:
-----------------------
-
-    name: 'photoserver'
-    data: '[('schemaVersion', '1'), 
-            ('policyVersion', '1'), 
-            ('roles', "{\n
-              'users'           : ['u1', 'u2'],\n
-              'paidsubscribers' : ['p1', 'p2']\n}")]'
-
-3. Internal
-
-Internally the policy is stored in a python dictionary. 
-Policies are converted from CRUD Interface format to Internal format
-by a compilation phase. The compiler sanitizes the input and
-creates the nested structures needed for run-time processing.
+1. External       : json format file
+2. Internal       : dictionary
 
 Internal Policy:
 ----------------
 
     data['photoserver'] = 
     {'schemaVersion': 1, 
-     'roles': {'paidsubscribers': ['p1', 'p2'], 
+     'groups': {'paidsubscribers': ['p1', 'p2'],
                'users': ['u1', 'u2']}, 
      'policyVersion': 1}
 
@@ -97,17 +51,17 @@ Internal Policy:
 #
 #
 class PolicyKeys():
-    # Internal policy key words
+    # Policy key words
     KW_POLICY_VERSION           = "policyVersion"
     KW_VERSION                  = "schemaVersion"
     KW_CONNECTION_ALLOW_DEFAULT = "connectionAllowDefault"
     KW_CONNECTION_ORIGINS       = "connectionOrigins"
     KW_CONNECTION_POLICY        = "connectionPolicy"
-    KW_MAXCONN                  = "maximumConnections"
-    KW_MAXCONNPERHOST           = "maximumConnectionsPerHost"
-    KW_MAXCONNPERUSER           = "maximumConnectionsPerUser"
+    KW_MAXCONN                  = "maxConnections"
+    KW_MAXCONNPERHOST           = "maxConnPerHost"
+    KW_MAXCONNPERUSER           = "maxConnPerUser"
     KW_POLICIES                 = "policies"
-    KW_ROLES                    = "roles"
+    KW_GROUPS                   = "groups"
 
     SETTING_MAX_FRAME_SIZE         = "maxFrameSize"
     SETTING_MAX_MESSAGE_SIZE       = "maxMessageSize"
@@ -141,7 +95,7 @@ class PolicyCompiler():
         PolicyKeys.KW_MAXCONNPERHOST,
         PolicyKeys.KW_MAXCONNPERUSER,
         PolicyKeys.KW_POLICIES,
-        PolicyKeys.KW_ROLES
+        PolicyKeys.KW_GROUPS
         )
         ]
 
@@ -276,9 +230,9 @@ class PolicyCompiler():
 
     def crud_compiler_v1(self, name, policy_in, policy_out, warnings, errors):
         """
-        Compile a schema from CRUD format to Internal format.
+        Compile a schema from processed json format to Internal format.
         @param[in] name application name
-        @param[in] policy_in CRUD Interface policy
+        @param[in] policy_in raw policy to be validated
         @param[out] policy_out validated Internal format
         @param[out] warnings nonfatal irregularities observed
         @param[out] errors descriptions of failure
@@ -289,7 +243,7 @@ class PolicyCompiler():
         """
         cerror = []
         # validate the options
-        for (key, val) in policy_in:
+        for key, val in policy_in.iteritems():
             if key not in self.allowed_opts:
                 warnings.append("Application '%s' option '%s' is ignored." %
                                 (name, key))
@@ -318,26 +272,25 @@ class PolicyCompiler():
             elif key in [PolicyKeys.KW_CONNECTION_ORIGINS,
                          PolicyKeys.KW_CONNECTION_POLICY,
                          PolicyKeys.KW_POLICIES,
-                         PolicyKeys.KW_ROLES
+                         PolicyKeys.KW_GROUPS
                          ]:
                 try:
-                    submap = ast.literal_eval(val)
-                    if not type(submap) is dict:
+                    if not type(val) is dict:
                         errors.append("Application '%s' option '%s' must be of type 'dict' but is '%s'" %
-                                      (name, key, type(submap)))
+                                      (name, key, type(val)))
                         return False
                     if key == PolicyKeys.KW_CONNECTION_ORIGINS:
-                        if not self.crud_compiler_v1_origins(name, submap, warnings, errors):
+                        if not self.crud_compiler_v1_origins(name, val, warnings, errors):
                             return False
                     elif key == PolicyKeys.KW_POLICIES:
-                        if not self.crud_compiler_v1_policies(name, submap, warnings, errors):
+                        if not self.crud_compiler_v1_policies(name, val, warnings, errors):
                             return False
                     else:
-                        # deduplicate connectionPolicy and roles lists
-                        for k,v in submap.iteritems():
+                        # deduplicate connectionPolicy and groups lists
+                        for k,v in val.iteritems():
                             v = list(set(v))
-                            submap[k] = v
-                    policy_out[key] = submap
+                            val[k] = v
+                    policy_out[key] = val
                 except Exception, e:
                     errors.append("Application '%s' option '%s' error processing map: %s" %
                                   (name, key, e))
@@ -354,7 +307,7 @@ class PolicyLocal():
         Create instance
         @params folder: relative path from __file__ to conf file folder
         """
-        self.data = {}
+        self.policydb = {}
         self.lookup_cache = {}
         self.stats = {}
         self.folder = folder
@@ -373,37 +326,34 @@ class PolicyLocal():
         apath = os.path.abspath(os.path.dirname(__file__))
         apath = os.path.join(apath, self.folder)
         for i in os.listdir(apath):
-            if i.endswith(".conf"):
+            if i.endswith(".json"):
                 self.policy_io_read_file(os.path.join(apath, i))
 
     def policy_io_read_file(self, fn):
         """
-        Read a single policy config file.
-        A file may hold multiple policies in separate ConfigParser sections.
-        All policies validated before any are committed.
-        Create each policy in db.
+        Read a policy config file.
+        Validate each policy and commit to policy database.
         @param fn: absolute path to file
         """
         try:
-            cp = ConfigParser.ConfigParser()
-            cp.optionxform = str
-            cp.read(fn)
+            with open(fn) as json_file:
+                cp = json.load(json_file)
 
         except Exception, e:
             raise PolicyError( 
                 "Error processing policy configuration file '%s' : %s" % (fn, e))
         newpolicies = {}
-        for policy in cp.sections():
+        for key, val in cp.iteritems():
             warnings = []
             diag = []
             candidate = {}
-            if not self.policy_compiler.crud_compiler_fn(policy, cp.items(policy), candidate, warnings, diag):
+            if not self.policy_compiler.crud_compiler_fn(key, val, candidate, warnings, diag):
                 msg = "Policy file '%s' is invalid: %s" % (fn, diag[0])
                 raise PolicyError( msg )
             if len(warnings) > 0:
                 print ("LogMe: Policy file '%s' application '%s' has warnings: %s" %
-                       (fn, policy, warnings))
-            newpolicies[policy] = candidate
+                       (fn, key, warnings))
+            newpolicies[key] = candidate
         # Log a warning if policy from one config file replaces another.
         # TODO: Should this throw? Do we increment the policy version per load?
         for c in newpolicies:
@@ -412,8 +362,8 @@ class PolicyLocal():
             c_pol = newpolicies[c]
             if PolicyKeys.KW_POLICY_VERSION in c_pol:
                 c_ver = int(c_pol[PolicyKeys.KW_POLICY_VERSION])
-            if c in self.data:
-                e_pol = self.data[c]
+            if c in self.policydb:
+                e_pol = self.policydb[c]
                 if PolicyKeys.KW_POLICY_VERSION in e_pol:
                     e_ver = int(e_pol[PolicyKeys.KW_POLICY_VERSION])
                 if c_ver < e_ver:
@@ -440,7 +390,7 @@ class PolicyLocal():
                 self.stats[c].update(c_max, c_max_u, c_max_h)
             else:
                 self.stats[c] = PolicyAppConnectionMgr(c_max, c_max_u, c_max_h)
-        self.data.update(newpolicies)
+        self.policydb.update(newpolicies)
 
 
     #
@@ -461,7 +411,7 @@ class PolicyLocal():
         if len(warnings) > 0:
             print ("LogMe: Application '%s' has warnings: %s" %
                    (name, warnings))
-        self.data[name] = candidate
+        self.policydb[name] = candidate
         # TODO: Create stats
 
     def policy_read(self, name):
@@ -470,7 +420,7 @@ class PolicyLocal():
         @param[in] name application name
         @return policy data in Crud Interface format
         """
-        return self.data[name]
+        return self.policydb[name]
 
     def policy_update(self, name, policy):
         """
@@ -478,7 +428,7 @@ class PolicyLocal():
         @param[in] name application name
         @param[in] policy data in Crud interface format
         """
-        if not name in self.data:
+        if not name in self.policydb:
             raise PolicyError("Policy '%s' does not exist" % name)
         self.policy_create(name, policy)
 
@@ -487,9 +437,9 @@ class PolicyLocal():
         Delete named policy
         @param[in] name application name
         """
-        if not name in self.data:
+        if not name in self.policydb:
             raise PolicyError("Policy '%s' does not exist" % name)
-        del self.data[name]
+        del self.policydb[name]
 
     #
     # db enumerator
@@ -498,7 +448,7 @@ class PolicyLocal():
         """
         Return a list of application names in this policy
         """
-        return self.data.keys()
+        return self.policydb.keys()
 
 
     #
@@ -514,9 +464,9 @@ class PolicyLocal():
         if settingname in policy:
             upolicy[settingname] = policy[settingname]
 
-    def policy_aggregate_policy_int(self, upolicy, policy, roles, settingname):
+    def policy_aggregate_policy_int(self, upolicy, policy, groups, settingname):
         """
-        Pull int out of policy.policies[role] and install into upolicy.
+        Pull int out of policy.policies[group] and install into upolicy.
         Integers are set to max(new, existing)
         param[in,out] upolicy user policy receiving aggregations
         param[in] policy Internal policy holding settings to be aggregated
@@ -525,9 +475,9 @@ class PolicyLocal():
         if not PolicyKeys.KW_POLICIES in policy:
             return
         policies = policy[PolicyKeys.KW_POLICIES]
-        for role in roles:
-            if role in policies:
-                rpol = policies[role]
+        for group in groups:
+            if group in policies:
+                rpol = policies[group]
                 if settingname in rpol:
                     sp = rpol[settingname]
                     if settingname in upolicy:
@@ -542,13 +492,13 @@ class PolicyLocal():
                         # user policy doesn't have setting so force it
                         upolicy[settingname] = sp
                 else:
-                    # no setting of this name in the role's policy
+                    # no setting of this name in the group's policy
                     pass
             else:
-                # no policy for this role
+                # no policy for this group
                 pass
 
-    def policy_aggregate_policy_bool(self, upolicy, policy, roles, settingname):
+    def policy_aggregate_policy_bool(self, upolicy, policy, groups, settingname):
         """
         Pull bool out of policy and install into upolicy if true
         param[in,out] upolicy user policy receiving aggregations
@@ -558,20 +508,20 @@ class PolicyLocal():
         if not PolicyKeys.KW_POLICIES in policy:
             return
         policies = policy[PolicyKeys.KW_POLICIES]
-        for role in roles:
-            if role in policies:
-                rpol = policies[role]
+        for group in groups:
+            if group in policies:
+                rpol = policies[group]
                 if settingname in rpol:
                     if rpol[settingname]:
                         upolicy[settingname] = True
                 else:
-                    # no setting of this name in the role's policy
+                    # no setting of this name in the group's policy
                     pass
             else:
-                # no policy for this role
+                # no policy for this group
                 pass
 
-    def policy_aggregate_policy_list(self, upolicy, policy, roles, settingname):
+    def policy_aggregate_policy_list(self, upolicy, policy, groups, settingname):
         """
         Pull list out of policy and append into upolicy
         param[in,out] upolicy user policy receiving aggregations
@@ -581,9 +531,9 @@ class PolicyLocal():
         if not PolicyKeys.KW_POLICIES in policy:
             return
         policies = policy[PolicyKeys.KW_POLICIES]
-        for role in roles:
-            if role in policies:
-                rpol = policies[role]
+        for group in groups:
+            if group in policies:
+                rpol = policies[group]
                 if settingname in rpol:
                     sp = rpol[settingname]
                     if settingname in upolicy:
@@ -593,10 +543,10 @@ class PolicyLocal():
                         # user policy doesn't have setting so force it
                         upolicy[settingname] = sp
                 else:
-                    # no setting of this name in the role's policy
+                    # no setting of this name in the group's policy
                     pass
             else:
-                # no policy for this role
+                # no policy for this group
                 pass
 
     def policy_lookup_settings(self, user, host, app, upolicy):
@@ -618,20 +568,20 @@ class PolicyLocal():
                 upolicy.update( self.lookup_cache[lookup_id] )
                 return True
 
-            settings = self.data[app]
+            settings = self.policydb[app]
             # User allowed to connect from host?
             allowed = False
             restricted = False
             uhs = HostStruct(host)
-            uroles = []
-            if PolicyKeys.KW_ROLES in settings:
-                for r in settings[PolicyKeys.KW_ROLES]:
-                    if user in settings[PolicyKeys.KW_ROLES][r]:
+            ugroups = []
+            if PolicyKeys.KW_GROUPS in settings:
+                for r in settings[PolicyKeys.KW_GROUPS]:
+                    if user in settings[PolicyKeys.KW_GROUPS][r]:
                         restricted = True
-                        uroles.append(r)
+                        ugroups.append(r)
             uorigins = []
             if PolicyKeys.KW_CONNECTION_POLICY in settings:
-                for ur in uroles:
+                for ur in ugroups:
                     if ur in settings[PolicyKeys.KW_CONNECTION_POLICY]:
                         uorigins.extend(settings[PolicyKeys.KW_CONNECTION_POLICY][ur])
             if PolicyKeys.KW_CONNECTION_ORIGINS in settings:
@@ -648,19 +598,19 @@ class PolicyLocal():
                     allowed = settings[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT]
             if not allowed:
                 return False
-            # Return connection limits and aggregation of role settings
-            uroles.append(user) # user roles also includes username directly
+            # Return connection limits and aggregation of group settings
+            ugroups.append(user) # user groups also includes username directly
             self.policy_aggregate_limits     (upolicy, settings, PolicyKeys.KW_POLICY_VERSION)
-            self.policy_aggregate_policy_int (upolicy, settings, uroles, PolicyKeys.SETTING_MAX_FRAME_SIZE)
-            self.policy_aggregate_policy_int (upolicy, settings, uroles, PolicyKeys.SETTING_MAX_MESSAGE_SIZE)
-            self.policy_aggregate_policy_int (upolicy, settings, uroles, PolicyKeys.SETTING_MAX_SESSION_WINDOW)
-            self.policy_aggregate_policy_int (upolicy, settings, uroles, PolicyKeys.SETTING_MAX_SESSIONS)
-            self.policy_aggregate_policy_int (upolicy, settings, uroles, PolicyKeys.SETTING_MAX_SENDERS)
-            self.policy_aggregate_policy_int (upolicy, settings, uroles, PolicyKeys.SETTING_MAX_RECEIVERS)
-            self.policy_aggregate_policy_bool(upolicy, settings, uroles, PolicyKeys.SETTING_ALLOW_DYNAMIC_SRC)
-            self.policy_aggregate_policy_bool(upolicy, settings, uroles, PolicyKeys.SETTING_ALLOW_ANONYMOUS_SENDER)
-            self.policy_aggregate_policy_list(upolicy, settings, uroles, PolicyKeys.SETTING_SOURCES)
-            self.policy_aggregate_policy_list(upolicy, settings, uroles, PolicyKeys.SETTING_TARGETS)
+            self.policy_aggregate_policy_int (upolicy, settings, ugroups, PolicyKeys.SETTING_MAX_FRAME_SIZE)
+            self.policy_aggregate_policy_int (upolicy, settings, ugroups, PolicyKeys.SETTING_MAX_MESSAGE_SIZE)
+            self.policy_aggregate_policy_int (upolicy, settings, ugroups, PolicyKeys.SETTING_MAX_SESSION_WINDOW)
+            self.policy_aggregate_policy_int (upolicy, settings, ugroups, PolicyKeys.SETTING_MAX_SESSIONS)
+            self.policy_aggregate_policy_int (upolicy, settings, ugroups, PolicyKeys.SETTING_MAX_SENDERS)
+            self.policy_aggregate_policy_int (upolicy, settings, ugroups, PolicyKeys.SETTING_MAX_RECEIVERS)
+            self.policy_aggregate_policy_bool(upolicy, settings, ugroups, PolicyKeys.SETTING_ALLOW_DYNAMIC_SRC)
+            self.policy_aggregate_policy_bool(upolicy, settings, ugroups, PolicyKeys.SETTING_ALLOW_ANONYMOUS_SENDER)
+            self.policy_aggregate_policy_list(upolicy, settings, ugroups, PolicyKeys.SETTING_SOURCES)
+            self.policy_aggregate_policy_list(upolicy, settings, ugroups, PolicyKeys.SETTING_TARGETS)
             c_upolicy = {}
             c_upolicy.update(upolicy)
             self.lookup_cache[lookup_id] = c_upolicy

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0d6ce137/tests/policy-1/policy-photoserver.conf
----------------------------------------------------------------------
diff --git a/tests/policy-1/policy-photoserver.conf b/tests/policy-1/policy-photoserver.conf
deleted file mode 100644
index d9d3758..0000000
--- a/tests/policy-1/policy-photoserver.conf
+++ /dev/null
@@ -1,149 +0,0 @@
-##
-## 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
-##
-
-# Definitions for photoserver application
-[photoserver]
-
-# policy schema used in this conf file
-schemaVersion            : 1
-
-# a version number to resolve multiple instances of this policy
-policyVersion            : 1
-
-# Aggregate connection limits
-maximumConnections        : 10
-maximumConnectionsPerUser : 5
-maximumConnectionsPerHost : 5
-
-# roles is a map.
-# key   = role name
-# value = list of authid names assigned to the role
-roles: {
-  'anonymous'       : ['anonymous'],
-  'users'           : ['u1', 'u2'],
-  'paidsubscribers' : ['p1', 'p2'],
-  'test'            : ['zeke', 'ynot'],
-  'admin'           : ['alice', 'bob', 'ellen'],
-  'superuser'       : ['ellen']
-  }
-
-# connectionOrigins is a map.
-# key   = origin name
-# value = list of host addresses or host address ranges
-connectionOrigins: {
-  'Ten18':      ['10.18.0.0,10.18.255.255'],
-  'EllensWS':   ['72.135.2.9'],
-  'TheLabs':    ['10.48.0.0,10.48.255.255','192.168.100.0,192.168.100.255'],
-  'Localhost':  ['127.0.0.1','::1'],
-  'TheWorld':   ['*']
-  }
-
-# connectionPolicy is a map.
-# key   = role name
-# value = list of connection origin names
-connectionPolicy: {
-  'admin'      : ['Ten18', 'TheLabs', 'Localhost'],
-  'test'       : ['TheLabs'],
-  'superuser'  : ['Localhost', 'EllensWS']
-  }
-
-# connectionAllowDefault - If a user is not restricted by a connectionPolicy
-#                          then is this user allowed to connect?
-connectionAllowDefault : True
-
-# policy is a map.
-# key   = role name or authid name
-# value = policy containing:
-#         - values passed in AMQP Open and Attach performatives
-#         - allowed source and target names in AMQP Attach
-#
-policies: {
-  'anonymous' : {
-    'maxFrameSize'         : 111111,
-    'maxMessageSize'       : 111111,
-    'maxSessionWindow'     : 111111,
-    'maxSessions'          : 1,
-    'maxSenders'           : 11,
-    'maxReceivers'         : 11,
-    'allowDynamicSrc'      : False,
-    'allowAnonymousSender' : False,
-    'sources'              : ['public'],
-    'targets'              : []
-    },
-  'users' : {
-    'maxFrameSize'         : 222222,
-    'maxMessageSize'       : 222222,
-    'maxSessionWindow'     : 222222,
-    'maxSessions'          : 2,
-    'maxSenders'           : 22,
-    'maxReceivers'         : 22,
-    'allowDynamicSrc'      : False,
-    'allowAnonymousSender' : False,
-    'sources'              : ['public', 'private'],
-    'targets'              : ['public']
-    },
-  'paidsubscribers' : {
-    'maxFrameSize'         : 333333,
-    'maxMessageSize'       : 333333,
-    'maxSessionWindow'     : 333333,
-    'maxSessions'          : 3,
-    'maxSenders'           : 33,
-    'maxReceivers'         : 33,
-    'allowDynamicSrc'      : True,
-    'allowAnonymousSender' : False,
-    'sources'              : ['public', 'private'],
-    'targets'              : ['public', 'private']
-    },
-  'test' : {
-    'maxFrameSize'         : 444444,
-    'maxMessageSize'       : 444444,
-    'maxSessionWindow'     : 444444,
-    'maxSessions'          : 4,
-    'maxSenders'           : 44,
-    'maxReceivers'         : 44,
-    'allowDynamicSrc'      : True,
-    'allowAnonymousSender' : True,
-    'sources'              : ['private'],
-    'targets'              : ['private']
-    },
-  'admin' : {
-    'maxFrameSize'         : 555555,
-    'maxMessageSize'       : 555555,
-    'maxSessionWindow'     : 555555,
-    'maxSessions'          : 5,
-    'maxSenders'           : 55,
-    'maxReceivers'         : 55,
-    'allowDynamicSrc'      : True,
-    'allowAnonymousSender' : True,
-    'sources'              : ['public', 'private', 'management'],
-    'targets'              : ['public', 'private', 'management']
-    },
-  'superuser' : {
-    'maxFrameSize'         : 666666,
-    'maxMessageSize'       : 666666,
-    'maxSessionWindow'     : 666666,
-    'maxSessions'          : 6,
-    'maxSenders'           : 66,
-    'maxReceivers'         : 66,
-    'allowDynamicSrc'      : False,
-    'allowAnonymousSender' : False,
-    'sources'              : ['public', 'private', 'management', 'root'],
-    'targets'              : ['public', 'private', 'management', 'root']
-    }
-  }

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0d6ce137/tests/policy-1/policy-photoserver.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/policy-photoserver.json b/tests/policy-1/policy-photoserver.json
new file mode 100644
index 0000000..b39b647
--- /dev/null
+++ b/tests/policy-1/policy-photoserver.json
@@ -0,0 +1,106 @@
+{
+    "photoserver": {
+        "schemaVersion": 1,
+        "policyVersion": 1,
+        "maxConnections": 10,
+        "maxConnPerUser": 5,
+        "maxConnPerHost": 5,
+        "groups": {
+            "anonymous":       ["anonymous"],
+            "users":           ["u1", "u2"],
+            "paidsubscribers": ["p1", "p2"],
+            "test":            ["zeke", "ynot"],
+            "admin":           ["alice", "bob", "ellen"],
+            "superuser":       ["ellen"]
+            },
+        "connectionOrigins": {
+            "Ten18":      ["10.18.0.0,10.18.255.255"],
+            "EllensWS":   ["72.135.2.9"],
+            "TheLabs":    ["10.48.0.0,10.48.255.255",
+                           "192.168.100.0,192.168.100.255"],
+            "Localhost":  ["127.0.0.1",
+                           "::1"],
+            "TheWorld":   ["*"]
+            },
+        "connectionPolicy": {
+            "admin":       ["Ten18", "TheLabs", "Localhost"],
+            "test":        ["TheLabs"],
+            "superuser":   ["Localhost", "EllensWS"]
+            },
+        "connectionAllowDefault": true,
+        "policies": {
+            "anonymous" : {
+                "maxFrameSize"         : 111111,
+                "maxMessageSize"       : 111111,
+                "maxSessionWindow"     : 111111,
+                "maxSessions"          : 1,
+                "maxSenders"           : 11,
+                "maxReceivers"         : 11,
+                "allowDynamicSrc"      : false,
+                "allowAnonymousSender" : false,
+                "sources"              : ["public"],
+                "targets"              : []
+                },
+            "users" : {
+                "maxFrameSize"         : 222222,
+                "maxMessageSize"       : 222222,
+                "maxSessionWindow"     : 222222,
+                "maxSessions"          : 2,
+                "maxSenders"           : 22,
+                "maxReceivers"         : 22,
+                "allowDynamicSrc"      : false,
+                "allowAnonymousSender" : false,
+                "sources"              : ["public", "private"],
+                "targets"              : ["public"]
+                },
+            "paidsubscribers" : {
+                "maxFrameSize"         : 333333,
+                "maxMessageSize"       : 333333,
+                "maxSessionWindow"     : 333333,
+                "maxSessions"          : 3,
+                "maxSenders"           : 33,
+                "maxReceivers"         : 33,
+                "allowDynamicSrc"      : true,
+                "allowAnonymousSender" : false,
+                "sources"              : ["public", "private"],
+                "targets"              : ["public", "private"]
+                },
+            "test" : {
+                "maxFrameSize"         : 444444,
+                "maxMessageSize"       : 444444,
+                "maxSessionWindow"     : 444444,
+                "maxSessions"          : 4,
+                "maxSenders"           : 44,
+                "maxReceivers"         : 44,
+                "allowDynamicSrc"      : true,
+                "allowAnonymousSender" : true,
+                "sources"              : ["private"],
+                "targets"              : ["private"]
+                },
+            "admin" : {
+                "maxFrameSize"         : 555555,
+                "maxMessageSize"       : 555555,
+                "maxSessionWindow"     : 555555,
+                "maxSessions"          : 5,
+                "maxSenders"           : 55,
+                "maxReceivers"         : 55,
+                "allowDynamicSrc"      : true,
+                "allowAnonymousSender" : true,
+                "sources"              : ["public", "private", "management"],
+                "targets"              : ["public", "private", "management"]
+                },
+            "superuser" : {
+                "maxFrameSize"         : 666666,
+                "maxMessageSize"       : 666666,
+                "maxSessionWindow"     : 666666,
+                "maxSessions"          : 6,
+                "maxSenders"           : 66,
+                "maxReceivers"         : 66,
+                "allowDynamicSrc"      : false,
+                "allowAnonymousSender" : false,
+                "sources"              : ["public", "private", "management", "root"],
+                "targets"              : ["public", "private", "management", "root"]
+                }
+            }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0d6ce137/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index 46a20d2..7c2ab70 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -178,7 +178,7 @@ class PolicyFile(TestCase):
         upolicy = {}
         self.assertTrue( 
             PolicyFile.policy.policy_lookup('192.168.100.5:33333', 'zeke', '192.168.100.5', 'photoserver', upolicy) )
-        self.assertTrue(upolicy['policyVersion']             == '1')
+        self.assertTrue(upolicy['policyVersion']             == 1)
         self.assertTrue(upolicy['maxFrameSize']            == 444444)
         self.assertTrue(upolicy['maxMessageSize']          == 444444)
         self.assertTrue(upolicy['maxSessionWindow']        == 444444)
@@ -219,7 +219,7 @@ class PolicyFile(TestCase):
         upolicy = {}
         self.assertTrue( 
             PolicyFile.policy.policy_lookup('192.168.100.5:33335', 'ellen', '72.135.2.9', 'photoserver', upolicy) )
-        self.assertTrue(upolicy['policyVersion']             == '1')
+        self.assertTrue(upolicy['policyVersion']             == 1)
         self.assertTrue(upolicy['maxFrameSize']            == 666666)
         self.assertTrue(upolicy['maxMessageSize']          == 666666)
         self.assertTrue(upolicy['maxSessionWindow']        == 666666)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org