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]