Author: aconway
Date: Tue Dec 16 18:13:00 2014
New Revision: 1646034

URL: http://svn.apache.org/r1646034
Log:
DISPATCH-73: Disallow inter-router listeners and connectors if role = 
standalone.

Fixed validation logic that checks for this problem.
Improved agent debug logging.

Modified:
    qpid/dispatch/trunk/python/qpid_dispatch/management/entity.py
    qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
    qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py
    qpid/dispatch/trunk/tests/system_tests_management.py

Modified: qpid/dispatch/trunk/python/qpid_dispatch/management/entity.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch/management/entity.py?rev=1646034&r1=1646033&r2=1646034&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch/management/entity.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch/management/entity.py Tue Dec 16 
18:13:00 2014
@@ -77,7 +77,16 @@ class EntityBase(object):
     def __delattr__(self, name):
         self.__delitem__(name)
 
-    def __repr__(self): return "Entity(%r)" % self.attributes
+    def __repr__(self): return "EntityBase(%r)" % self.attributes
+
+    SPECIAL = ["name", "identity", "type"]
+    N_SPECIAL = len(SPECIAL)
+    PRIORITY = dict([(SPECIAL[i], i) for i in xrange(N_SPECIAL)])
+
+    def __str__(self):
+        # Print the name and identity first.
+        keys = sorted(self.attributes.keys(), key=lambda k: 
self.PRIORITY.get(k, self.N_SPECIAL))
+        return "Entity(%s)" % ", ".join("%s=%s" % (k, self.attributes[k]) for 
k in keys)
 
 
 def update(entity, values):

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py?rev=1646034&r1=1646033&r2=1646034&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py 
(original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py Tue 
Dec 16 18:13:00 2014
@@ -160,6 +160,7 @@ class ContainerEntity(AgentEntity):
     def create(self):
         self._qd.qd_dispatch_configure_container(self._dispatch, self)
 
+
 class RouterEntity(AgentEntity):
     def __init__(self, agent, entity_type, attributes=None):
         super(RouterEntity, self).__init__(agent, entity_type, attributes, 
validate=False, base_id=attributes.get('routerId'))
@@ -287,10 +288,9 @@ class EntityCache(object):
 
     def add(self, entity, pointer=None):
         """Add an entity. Provide pointer if it is associated with a C 
entity"""
-        self.log(LOG_DEBUG, "Add %s entity: %s" %
-                 (entity.entity_type.short_name, 
entity.attributes['identity']))
+        self.log(LOG_DEBUG, "Add entity: %s" % entity)
         # Validate in the context of the existing entities for uniqueness
-        self.schema.validate_all(chain(iter([entity]), iter(self.entities)))
+        self.schema.validate_full(chain(iter([entity]), iter(self.entities)))
         self.entities.append(entity)
         if pointer: self.pointers[pointer] = entity
 
@@ -364,18 +364,16 @@ class Agent(object):
         self.name = self.identity = 'self'
         self.type = 'org.amqp.management' # AMQP management node type
         self.request_lock = Lock()
-        self.log_adapter = None
+        self.log_adapter = LogAdapter("AGENT")
 
     def log(self, level, text):
-        if self.log_adapter:
-            info = traceback.extract_stack(limit=2)[0] # Caller frame info
-            self.log_adapter.log(level, text, info[0], info[1])
+        info = traceback.extract_stack(limit=2)[0] # Caller frame info
+        self.log_adapter.log(level, text, info[0], info[1])
 
     def activate(self, address):
         """Register the management address to receive management requests"""
         self.io = [IoAdapter(self.receive, address),
                    IoAdapter(self.receive, address, True)] # Global
-        self.log_adapter = LogAdapter("AGENT")
 
     def entity_class(self, entity_type):
         """Return the class that implements entity_type"""

Modified: 
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py?rev=1646034&r1=1646033&r2=1646034&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py 
(original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py 
Tue Dec 16 18:13:00 2014
@@ -41,24 +41,28 @@ class QdSchema(schema.Schema):
         self.configuration_entity = self.entity_type(self.CONFIGURATION_ENTITY)
         self.operational_entity = self.entity_type(self.OPERATIONAL_ENTITY)
 
-    def validate(self, entities, full=True, **kwargs):
+    def validate_full(self, entities, **kwargs):
         """
         In addition to L{schema.Schema.validate}, check the following:
 
-        If the operating mode of the router is not 'interior', then the only
-        permitted roles for listeners and connectors is 'normal'.
+        listeners and connectors can only have role=inter-router if the
+        router has mode=interior.
+
 
         @param entities: List of attribute name:value maps.
-        @param full: Perform validation for full configuration.
         @param kwargs: See L{schema.Schema.validate}
         """
+        entities = list(entities) # Need to traverse twice
         super(QdSchema, self).validate_all(entities, **kwargs)
-
-        if full:
-            if entities.router[0].mode != 'interior':
-                for connect in entities.get(entity_type='listeners') + 
entities.get(entity_type='connector'):
-                    if connect['role'] != 'normal':
-                        raise schema.ValidationError("Role '%s' for connection 
'%s' only permitted with 'interior' mode" % (connect['role'], connect.name))
+        inter_router = not_interior = None
+        for e in entities:
+            if self.short_name(e.type) == "router" and e.mode != "interior":
+                not_interior = e.mode
+            if self.short_name(e.type) in ["listener", "connector"] and e.role 
== "inter-router":
+                inter_router = e
+            if not_interior and inter_router:
+                raise schema.ValidationError(
+                    "role='inter-router' only allowed with router 
mode='interior' for %s." % inter_router)
 
     def is_configuration(self, entity_type):
         return entity_type and self.configuration_entity in 
entity_type.all_bases

Modified: qpid/dispatch/trunk/tests/system_tests_management.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_management.py?rev=1646034&r1=1646033&r2=1646034&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_management.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_management.py Tue Dec 16 18:13:00 
2014
@@ -21,7 +21,7 @@
 
 import unittest, system_test, re, os
 from qpid_dispatch.management import Node, ManagementError, Url, 
BadRequestStatus, NotImplementedStatus, NotFoundStatus, ForbiddenStatus
-from system_test import Qdrouterd, message, retry
+from system_test import Qdrouterd, message, retry, wait_ports, Process
 from proton import ConnectionException
 from itertools import chain
 
@@ -364,6 +364,35 @@ class ManagementTest(system_test.TestCas
         for type in LISTENER, WAYPOINT, LINK: self.assertIn(type, result)
         for a in ['linkType', 'linkDir', 'owningAddr']: self.assertIn(a, 
result[LINK])
 
+    def test_standalone_no_inter_router(self):
+        """Verify that we do not allow inter-router connectors or listeners in 
standalone mode"""
+
+        attrs = dict(role="inter-router", saslMechanisms="ANONYMOUS")
+        self.assertRaises(
+            BadRequestStatus,
+            self.node.create, dict(attrs, type=LISTENER, name="bad1", 
port=str(self.get_port())))
+
+        self.assertRaises(
+            BadRequestStatus,
+            self.node.create, dict(attrs, type=CONNECTOR, name="bad2", 
port=str(self.get_port())))
+
+        conf = Qdrouterd.Config([
+            ('router', { 'mode': 'standalone', 'routerId': 'all_by_myself1'}),
+            ('listener', {'port':self.get_port(), 'role':'inter-router'})
+        ])
+        r = self.qdrouterd('routerX', conf, wait=False)
+        r.expect = Process.EXIT_FAIL
+        self.assertTrue(r.wait() != 0)
+
+        conf = Qdrouterd.Config([
+            ('router', { 'mode': 'standalone', 'routerId': 'all_by_myself2'}),
+            ('listener', {'port':self.get_port(), 'role':'normal'}),
+            ('connector', {'port':self.get_port(), 'role':'inter-router'})
+        ])
+        r = self.qdrouterd('routerY', conf, wait=False)
+        r.expect = Process.EXIT_FAIL
+        self.assertTrue(r.wait() != 0)
+
 
 if __name__ == '__main__':
     unittest.main(system_test.main_module())



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

Reply via email to