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/09/02 14:21:34 UTC

qpid-dispatch git commit: DISPATCH-494: Policy vhost support for mgmt Update and Delete

Repository: qpid-dispatch
Updated Branches:
  refs/heads/master 19e85bce1 -> d356593fe


DISPATCH-494: Policy vhost support for mgmt Update and Delete

Sets proper field attributes in qdrouter.json to allow ops.
Add hooks in agent and policy manager to relay mgmt ops to policy code.
Add self tests to exercise vhost add, update, and delete.


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

Branch: refs/heads/master
Commit: d356593fef5935edda538734f5ccb48c2bb37764
Parents: 19e85bc
Author: Chuck Rolke <cr...@redhat.com>
Authored: Fri Sep 2 10:12:08 2016 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Sep 2 10:12:08 2016 -0400

----------------------------------------------------------------------
 python/qpid_dispatch/management/qdrouter.json   |  20 +--
 .../qpid_dispatch_internal/management/agent.py  |   7 +-
 .../policy/policy_local.py                      |  23 +---
 .../policy/policy_manager.py                    |  20 +++
 tests/system_tests_policy.py                    | 126 +++++++++++++++++++
 5 files changed, 170 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/d356593f/python/qpid_dispatch/management/qdrouter.json
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index ae1b901..b46f341 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -1271,46 +1271,52 @@
         "vhost": {
             "description": "AMQP virtual host policy definition of users, user groups, allowed remote hosts, and AMQP restrictions.",
             "extends": "configurationEntity",
-            "operations": ["CREATE"],
+            "operations": ["CREATE", "UPDATE", "DELETE"],
             "attributes": {
                 "id": {
                     "type": "string",
                     "description": "The vhost name.",
-                    "required": true
+                    "required": true,
+                    "create": true
                 },
                 "maxConnections": {
                     "type": "integer",
                     "default": 65535,
                     "description": "Maximum number of concurrent client connections allowed.",
                     "required": false,
-                    "create": true
+                    "create": true,
+                    "update": true
                 },
                 "maxConnectionsPerUser": {
                     "type": "integer",
                     "default": 65535,
                     "description": "Maximum number of concurrent client connections allowed for any single user.",
                     "required": false,
-                    "create": true
+                    "create": true,
+                    "update": true
                 },
                 "maxConnectionsPerHost": {
                     "type": "integer",
                     "default": 65535,
                     "description": "Maximum number of concurrent client connections allowed for any remote host.",
                     "required": false,
-                    "create": true
+                    "create": true,
+                    "update": true
                 },
                 "allowUnknownUser": {
                     "type": "boolean",
                     "description": "Unrestricted users, those who are not members of a defined user group, are allowed to connect to this application. Unrestricted users are assigned to the 'default' user group and receive 'default' settings.",
                     "default": false,
                     "required": false,
-                    "create": true
+                    "create": true,
+                    "update": true
                 },
                 "groups": {
                     "type": "map",
                     "description": "A map where each key is a user group name and the value is a map of the corresponding settings for that group.",
                     "required": false,
-                    "create": true
+                    "create": true,
+                    "update": true
                 }
             }
         },

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/d356593f/python/qpid_dispatch_internal/management/agent.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/agent.py b/python/qpid_dispatch_internal/management/agent.py
index 42191da..370dc36 100644
--- a/python/qpid_dispatch_internal/management/agent.py
+++ b/python/qpid_dispatch_internal/management/agent.py
@@ -315,7 +315,6 @@ class PolicyEntity(EntityAdapter):
     def __str__(self):
         return super(PolicyEntity, self).__str__().replace("Entity(", "PolicyEntity(")
 
-
 class VhostEntity(EntityAdapter):
     def create(self):
         self._policy.create_ruleset(self.attributes)
@@ -326,6 +325,12 @@ class VhostEntity(EntityAdapter):
     def __str__(self):
         return super(VhostEntity, self).__str__().replace("Entity(", "VhostEntity(")
 
+    def _delete(self):
+        self._policy.delete_ruleset(self.id)
+
+    def _update(self):
+        self._policy.update_ruleset(self.attributes)
+
 
 class VhostStatsEntity(EntityAdapter):
     def _identifier(self):

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/d356593f/python/qpid_dispatch_internal/policy/policy_local.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_local.py b/python/qpid_dispatch_internal/policy/policy_local.py
index 5b61152..87fe11a 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -477,7 +477,7 @@ class PolicyLocal(object):
     #
     def create_ruleset(self, attributes):
         """
-        Create named policy ruleset
+        Create or update named policy ruleset.
         @param[in] attributes: from config
         """
         warnings = []
@@ -491,30 +491,16 @@ class PolicyLocal(object):
             for warning in warnings:
                 self._manager.log_warning(warning)
         if name not in self.rulesetdb:
-            self.statsdb[name] = AppStats(name, self._manager, candidate)
+            if name not in self.statsdb:
+                self.statsdb[name] = AppStats(name, self._manager, candidate)
             self._manager.log_info("Created policy rules for vhost %s" % name)
         else:
             self.statsdb[name].update_ruleset(candidate)
             self._manager.log_info("Updated policy rules for vhost %s" % name)
+        # TODO: ruleset lock
         self.rulesetdb[name] = {}
         self.rulesetdb[name].update(candidate)
 
-    def policy_read(self, name):
-        """
-        Read policy for named vhost
-        @param[in] name vhost name
-        @return policy data in raw user format
-        """
-        return self.rulesetdb[name]
-
-    def policy_update(self, name, policy):
-        """
-        Update named policy
-        @param[in] name vhost name
-        @param[in] policy data in raw user input
-        """
-        raise PolicyError("Policy updatd function not implemented")
-
     def policy_delete(self, name):
         """
         Delete named policy
@@ -522,6 +508,7 @@ class PolicyLocal(object):
         """
         if name not in self.rulesetdb:
             raise PolicyError("Policy '%s' does not exist" % name)
+        # TODO: ruleset lock
         del self.rulesetdb[name]
 
     #

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/d356593f/python/qpid_dispatch_internal/policy/policy_manager.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_manager.py b/python/qpid_dispatch_internal/policy/policy_manager.py
index 3438564..3d0c8d9 100644
--- a/python/qpid_dispatch_internal/policy/policy_manager.py
+++ b/python/qpid_dispatch_internal/policy/policy_manager.py
@@ -78,6 +78,26 @@ class PolicyManager(object):
         self._policy_local.create_ruleset(attributes)
 
     #
+    # Management interface to delete a ruleset
+    #
+    def delete_ruleset(self, id):
+        """
+        Delete named policy ruleset
+        @param[in] id: ruleset name
+        """
+        self._policy_local.policy_delete(id)
+
+    #
+    # Management interface to update a ruleset
+    #
+    def update_ruleset(self, attributes):
+        """
+        Update named policy ruleset
+        @param[in] id: ruleset name
+        """
+        self._policy_local.create_ruleset(attributes)
+
+    #
     # Management interface to set the default vhost
     #
     def set_default_vhost(self, name):

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/d356593f/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index e01e666..e67beff 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -107,6 +107,132 @@ class LoadPolicyFromFolder(TestCase):
         rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
         self.assertEqual(len(rulesets), 5)
 
+    def new_policy(self):
+        return """
+{
+    "id": "dispatch-494",
+    "maxConnections": 50,
+    "maxConnectionsPerHost": 20,
+    "maxConnectionsPerUser": 8,
+    "allowUnknownUser": true,
+    "groups": {
+        "$default": {
+            "allowAnonymousSender": true,
+            "maxReceivers": 99,
+            "users": "*",
+            "maxSessionWindow": 9999,
+            "maxFrameSize": 222222,
+            "sources": "public, private, $management",
+            "maxMessageSize": 222222,
+            "allowDynamicSource": true,
+            "remoteHosts": "*",
+            "maxSessions": 2,
+            "targets": "public, private, $management",
+            "maxSenders": 22
+        }
+    }
+}
+"""
+
+    def updated_policy(self):
+        return """
+{
+    "id": "dispatch-494",
+    "maxConnections": 500,
+    "maxConnectionsPerHost": 2,
+    "maxConnectionsPerUser": 30,
+    "allowUnknownUser": true,
+    "groups": {
+        "$default": {
+            "allowAnonymousSender": true,
+            "maxReceivers": 123,
+            "users": "*",
+            "maxSessionWindow": 9999,
+            "maxFrameSize": 222222,
+            "sources": "public, private, $management",
+            "maxMessageSize": 222222,
+            "allowDynamicSource": true,
+            "remoteHosts": "*",
+            "maxSessions": 2,
+            "targets": "public, private, $management",
+            "maxSenders": 222
+        }
+    }
+}
+"""
+
+    def test_verify_policy_add_update_delete(self):
+        # verify current vhost count
+        rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+        self.assertEqual(len(rulesets), 5)
+
+        # create
+        self.run_qdmanage('create --type=vhost --name=dispatch-494 --stdin', input=self.new_policy())
+        rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+        self.assertEqual(len(rulesets), 6)
+        found = False
+        for ruleset in rulesets:
+            if ruleset['id'] == 'dispatch-494':
+                found = True
+                self.assertEqual(ruleset['maxConnections'], 50)
+                self.assertEqual(ruleset['maxConnectionsPerHost'], 20)
+                self.assertEqual(ruleset['maxConnectionsPerUser'], 8)
+                break
+        self.assertTrue(found)
+
+        # update
+        self.run_qdmanage('update --type=vhost --name=dispatch-494 --stdin', input=self.updated_policy())
+        rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+        self.assertEqual(len(rulesets), 6)
+        found = False
+        for ruleset in rulesets:
+            if ruleset['id'] == 'dispatch-494':
+                found = True
+                self.assertEqual(ruleset['maxConnections'], 500)
+                self.assertEqual(ruleset['maxConnectionsPerHost'], 2)
+                self.assertEqual(ruleset['maxConnectionsPerUser'], 30)
+                break
+        self.assertTrue(found)
+
+        # delete
+        self.run_qdmanage('delete --type=vhost --name=dispatch-494')
+        rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+        self.assertEqual(len(rulesets), 5)
+        absent = True
+        for ruleset in rulesets:
+            if ruleset['id'] == 'dispatch-494':
+                absent = False
+                break
+        self.assertTrue(absent)
+
+    def test_repeated_create_delete(self):
+        for i in range(0, 10):
+            rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+            self.assertEqual(len(rulesets), 5)
+
+            # create
+            self.run_qdmanage('create --type=vhost --name=dispatch-494 --stdin', input=self.new_policy())
+            rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+            self.assertEqual(len(rulesets), 6)
+            found = False
+            for ruleset in rulesets:
+                if ruleset['id'] == 'dispatch-494':
+                    found = True
+                    break
+            self.assertTrue(found)
+
+            # delete
+            self.run_qdmanage('delete --type=vhost --name=dispatch-494')
+            rulesets = json.loads(self.run_qdmanage('query --type=vhost'))
+            self.assertEqual(len(rulesets), 5)
+            absent = True
+            for ruleset in rulesets:
+                if ruleset['id'] == 'dispatch-494':
+                    absent = False
+                    break
+            self.assertTrue(absent)
+
+
 class SenderReceiverLimits(TestCase):
     """
     Verify that specifying a policy folder from the router conf file


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