qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject svn commit: r1664739 - in /qpid/dispatch/trunk: doc/man/ python/qpid_dispatch/management/ python/qpid_dispatch_internal/ python/qpid_dispatch_internal/management/ python/qpid_dispatch_internal/tools/ src/ tests/ tools/
Date Fri, 06 Mar 2015 22:39:46 GMT
Author: aconway
Date: Fri Mar  6 22:39:45 2015
New Revision: 1664739

URL: http://svn.apache.org/r1664739
Log:
DISPATCH-110: Provide access to recent log messages via management agent.

Added GET-LOGS operation to management entity. Returns a list of log entries each a list of:

[module name(string), level name(string), message text(string), file name(string or None),
line number(integer or None), timestamp(integer)]

Added --log option to qdstat, prints log in same format as qdrouterd, without source file/line.

qdmanage can call GET-LOG also.

Conflicts:
	python/qpid_dispatch_internal/management/agent.py
DISPATCH-110: Provide access to recent log messages via management agent.

Added GET-LOGS operation to management entity. Returns a list of log entries each a list of:

[module name(string), level name(string), message text(string), file name(string or None),
line number(integer or None), timestamp(integer)]

Added --log option to qdstat, prints log in same format as qdrouterd, without source file/line.

qdmanage can call GET-LOG also, prints log list in JSON format.

Modified:
    qpid/dispatch/trunk/doc/man/qdmanage.8.noopt.md.in
    qpid/dispatch/trunk/python/qpid_dispatch/management/client.py
    qpid/dispatch/trunk/python/qpid_dispatch/management/qdrouter.json
    qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch.py
    qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
    qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py
    qpid/dispatch/trunk/python/qpid_dispatch_internal/tools/command.py
    qpid/dispatch/trunk/src/log.c
    qpid/dispatch/trunk/tests/system_tests_qdmanage.py
    qpid/dispatch/trunk/tests/system_tests_qdstat.py
    qpid/dispatch/trunk/tools/qdmanage
    qpid/dispatch/trunk/tools/qdstat

Modified: qpid/dispatch/trunk/doc/man/qdmanage.8.noopt.md.in
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/doc/man/qdmanage.8.noopt.md.in?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/doc/man/qdmanage.8.noopt.md.in (original)
+++ qpid/dispatch/trunk/doc/man/qdmanage.8.noopt.md.in Fri Mar  6 22:39:45 2015
@@ -56,6 +56,9 @@ with qdrouter.
 `get-json-schema` [*INDENT*]
 :    Get the router schema in JSON format. Optional integer indent for formatted  output.
 
+`get-log` [*INDENT*]
+:    Get recent log entries from the router.
+
 # Options
 
 Run `qdmanage --help` to see options.

Modified: qpid/dispatch/trunk/python/qpid_dispatch/management/client.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch/management/client.py?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch/management/client.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch/management/client.py Fri Mar  6 22:39:45 2015
@@ -300,3 +300,5 @@ class Node(object):
     def get_mgmt_nodes(self, type=None):
         return self.call(self.node_request(operation="GET-MGMT-NODES", entityType=type)).body
 
+    def get_log(self, limit=None, type=None):
+        return self.call(self.node_request(operation="GET-LOG", entityType=type, limit=limit)).body

Modified: qpid/dispatch/trunk/python/qpid_dispatch/management/qdrouter.json
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch/management/qdrouter.json?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch/management/qdrouter.json (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch/management/qdrouter.json Fri Mar  6 22:39:45
2015
@@ -377,7 +377,7 @@
             "description": "Qpid dispatch router extensions to the standard org.amqp.management
interface.",
             "extends": "org.amqp.management",
             "singleton": true,
-            "operations": ["GET-SCHEMA", "GET-JSON-SCHEMA"],
+            "operations": ["GET-SCHEMA", "GET-JSON-SCHEMA", "GET-LOG"],
             "operationDefs": {
                 "GET-SCHEMA": {
                     "description": "Get the qdrouterd schema for this router in AMQP map
format",
@@ -416,6 +416,27 @@
                             "type": "string"
                         }
                     }
+                },
+                "GET-LOG": {
+                    "description": "Get recent log entries from the router.",
+                    "request": {
+                        "properties": {
+                            "identity": {
+                                "description": "Set to the value `self`",
+                                "type": "string"
+                            },
+                            "limit": {
+                                "description": "Maximum number of log entries to get.",
+                                "type": "integer"
+                            }
+                        }
+                    },
+                    "response": {
+                        "body": {
+                            "description": "A list of log entries where each entry is a list
of: module name(string), level name(string), message text(string), file name(string or None),
line number(integer or None) , timestamp(integer)",
+                            "type": "string"
+                        }
+                    }
                 }
             }
         },

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch.py?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch.py Fri Mar  6 22:39:45 2015
@@ -76,9 +76,12 @@ class QdDll(ctypes.PyDLL):
         self._prototype(self.qd_entity_refresh_begin, c_long, [py_object])
         self._prototype(self.qd_entity_refresh_end, None, [])
 
+        self._prototype(self.qd_log_recent_py, py_object, [c_long])
+
     def _errcheck(self, result, func, args):
         if self.qd_error_code():
             raise CError(self.qd_error_message())
+        return result
 
     def _prototype(self, f, restype, argtypes, check=True):
         """Set up the return and argument types and the error checker for a ctypes function"""

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=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py Fri Mar  6 22:39:45
2015
@@ -65,7 +65,7 @@ Temporary solution is to lock the entire
 Better solution coming soon...
 """
 
-yimport traceback, json
+import traceback, json
 from itertools import ifilter, chain
 from traceback import format_exc
 from threading import Lock
@@ -500,15 +500,20 @@ class ManagementEntity(EntityAdapter):
             return str(Address.topological(node.attributes['routerId'], "$management", area))
         return (OK, self._agent.entities.map_type(node_address, 'router.node'))
 
-
     def get_schema(self, request):
         return (OK, self._schema.dump())
 
+    def _intprop(self, request, prop):
+        value = request.properties.get(prop)
+        if value is not None: value = int(value)
+        return value
+
     def get_json_schema(self, request):
-        indent = request.properties.get("indent")
-        if indent is not None: indent = int(indent)
-        return (OK, json.dumps(self._schema.dump(), indent=indent))
+        return (OK, json.dumps(self._schema.dump(), indent=self._intprop(request, "indent")))
 
+    def get_log(self, request):
+        logs = self._qd.qd_log_recent_py(self._intprop(request, "limit") or -1)
+        return (OK, logs)
 
 class Agent(object):
     """AMQP managment agent. Manages entities, directs requests to the correct entity."""
@@ -667,14 +672,17 @@ class Agent(object):
         requested_type = request.properties.get('type')
         if requested_type:
             requested_type = self.schema.entity_type(requested_type)
-            # Special case for management object, allow just type with no name/id
-            if self.management.entity_type.is_a(requested_type):
-                return self.management
-
         # ids is a map of identifying attribute values
         ids = dict((k, request.properties.get(k))
                    for k in ['name', 'identity'] if k in request.properties)
-        if not len(ids): raise BadRequestStatus("No name or identity provided")
+
+        # Special case for management object: if no name/id and no conflicting type
+        # then assume this is for "self"
+        if not ids:
+            if not requested_type or self.management.entity_type.is_a(requested_type):
+                return self.management
+            else:
+                raise BadRequestStatus("No name or identity provided")
 
         def attrvals():
             """String form of the id attribute values for error messages"""

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py Fri Mar  6 22:39:45
2015
@@ -24,7 +24,7 @@ Configuration file parsing
 import json, re, sys
 from copy import copy
 from qpid_dispatch.management.entity import camelcase
-from .. import dispatch_c
+from ..dispatch import QdDll
 from .qdrouter import QdSchema
 
 class Config(object):
@@ -120,7 +120,7 @@ class Config(object):
 
 def configure_dispatch(dispatch, lib_handle, filename):
     """Called by C router code to load configuration file and do configuration"""
-    qd = dispatch_c.QdDll(lib_handle)
+    qd = QdDll(lib_handle)
     dispatch = qd.qd_dispatch_p(dispatch)
     config = Config(filename)
 

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/tools/command.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/tools/command.py?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/tools/command.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/tools/command.py Fri Mar  6 22:39:45
2015
@@ -62,11 +62,13 @@ def check_args(args, maxargs=0, minargs=
     Check number of arguments, raise UsageError if in correct.
     @param maxargs: max number of allowed args after command or None to skip check.
     @param minargs: min number of allowed args after command or None to skip check.
+    @return args padded with None to maxargs.
     """
     if minargs is not None and len(args) < minargs:
         raise UsageError("Not enough arguments, got %s need %s" % (len(args), minargs))
     if maxargs is not None and len(args) > maxargs:
         raise UsageError("Unexpected arguments: %s" % (" ".join(args[maxargs:])))
+    return args + [None] * (maxargs - len(args))
 
 def connection_options(options, title="Connection Options"):
     """Return an OptionGroup for connection options."""

Modified: qpid/dispatch/trunk/src/log.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/log.c?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/log.c (original)
+++ qpid/dispatch/trunk/src/log.c Fri Mar  6 22:39:45 2015
@@ -17,6 +17,8 @@
  * under the License.
  */
 
+#include <Python.h>
+
 #include "log_private.h"
 #include "entity.h"
 #include "aprintf.h"
@@ -196,6 +198,11 @@ static const level_t* level_for_name(con
     return &levels[i];
 }
 
+/// Return the name of log level or 0 if not found.
+static const char* level_name(int level) {
+    return (0 <= level && level < N_LEVELS) ? levels[level].name : NULL;
+}
+
 static const char *SEPARATORS=", ;:";
 
 /// Calculate the bit mask for a log enable string. Return -1 and set qd_error on error.
@@ -347,13 +354,50 @@ void qd_log_impl(qd_log_source_t *source
 
     write_log(source, entry);
 
+    // Bounded buffer of log entries, keep most recent.
     sys_mutex_lock(log_lock);
     DEQ_INSERT_TAIL(entries, entry);
     if (DEQ_SIZE(entries) > LIST_MAX)
-        qd_log_entry_free_lh(entry);
+        qd_log_entry_free_lh(DEQ_HEAD(entries));
     sys_mutex_unlock(log_lock);
 }
 
+static PyObject *inc_none() { Py_INCREF(Py_None); return Py_None; }
+
+/// Return the log buffer up to limit as a python list. Called by management agent.
+PyObject *qd_log_recent_py(long limit) {
+    if (PyErr_Occurred()) return NULL;
+    PyObject *list = PyList_New(0);
+    PyObject *py_entry = NULL;
+    if (!list) goto error;
+    qd_log_entry_t *entry = DEQ_TAIL(entries);
+    while (entry && limit) {
+        const int ENTRY_SIZE=6;
+        py_entry = PyList_New(ENTRY_SIZE);
+        if (!py_entry) goto error;
+        int i = 0;
+        // NOTE: PyList_SetItem steals a reference so no leak here.
+        PyList_SetItem(py_entry, i++, PyString_FromString(entry->module));
+        const char* level = level_name(entry->level);
+        PyList_SetItem(py_entry, i++, level ? PyString_FromString(level) : inc_none());
+        PyList_SetItem(py_entry, i++, PyString_FromString(entry->text));
+        PyList_SetItem(py_entry, i++, entry->file ? PyString_FromString(entry->file)
: inc_none());
+        PyList_SetItem(py_entry, i++, entry->file ? PyLong_FromLong(entry->line) :
inc_none());
+        PyList_SetItem(py_entry, i++, PyLong_FromLongLong((PY_LONG_LONG)entry->time));
+        assert(i == ENTRY_SIZE);
+        if (PyErr_Occurred()) goto error;
+        PyList_Insert(list, 0, py_entry);
+        Py_DECREF(py_entry);
+        if (limit > 0) --limit;
+        entry = DEQ_PREV(entry);
+    }
+    return list;
+ error:
+    Py_XDECREF(list);
+    Py_XDECREF(py_entry);
+    return NULL;
+}
+
 void qd_log_initialize(void)
 {
     DEQ_INIT(entries);

Modified: qpid/dispatch/trunk/tests/system_tests_qdmanage.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_qdmanage.py?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_qdmanage.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_qdmanage.py Fri Mar  6 22:39:45 2015
@@ -148,8 +148,15 @@ class QdmanageTest(TestCase):
 
     def test_get_schema(self):
         schema = dictify(QdSchema().dump())
-        actual = self.run_qdmanage("GET-JSON-SCHEMA")
+        actual = self.run_qdmanage("get-json-schema")
         self.assertEquals(schema, dictify(json.loads(actual)))
+        actual = self.run_qdmanage("get-schema")
+        self.assertEquals(schema, dictify(json.loads(actual)))
+
+    def test_get_log(self):
+        log = json.loads(self.run_qdmanage("get-log limit=1"))[0]
+        self.assertEquals(['AGENT', 'trace'], log[0:2])
+        self.assertRegexpMatches(log[2], 'get-log')
 
     def test_ssl(self):
         """Simple test for SSL connection. Note system_tests_qdstat has a more complete SSL
test"""

Modified: qpid/dispatch/trunk/tests/system_tests_qdstat.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_qdstat.py?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_qdstat.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_qdstat.py Fri Mar  6 22:39:45 2015
@@ -93,17 +93,20 @@ class QdstatTest(system_test.TestCase):
     def test_memory(self):
         self.run_qdstat(['--memory'], r'qd_address_t\s+[0-9]+')
 
-    def do_test(self, url, args):
-        # FIXME aconway 2015-02-18: shouldn't be timing out, should be rejected.
-        self.run_qdstat(['--general', '--timeout=0.5'] + args, 
-                        regexp=r'(?s)Router Statistics.*Mode\s*Standalone',
-                        address=str(url))
+    def test_log(self):
+        self.run_qdstat(['--log',  '--limit=5'], r'AGENT \(trace\).*GET-LOG')
 
     def test_ssl(self):
         """
         Test the matrix of dispatch and client SSL configuratoin and ensure we 
         can/can't connect as expected.
         """
+
+        def do_test(url, args):
+            self.run_qdstat(['--general'] + args,
+                            regexp=r'(?s)Router Statistics.*Mode\s*Standalone',
+                            address=str(url))
+
         trustfile = ['--ssl-trustfile', self.ssl_file('ca-certificate.pem')]
         bad_trustfile = ['--ssl-trustfile', self.ssl_file('bad-ca-certificate.pem')]
         client_cert = ['--ssl-certificate', self.ssl_file('client-certificate.pem')]
@@ -116,35 +119,35 @@ class QdstatTest(system_test.TestCase):
         none_s, strict_s, unsecured_s, auth_s = (Url(a, scheme="amqps") for a in addrs)
 
         # Non-SSL enabled listener should fail SSL connections.
-        self.do_test(none, [])
-        self.assertRaises(AssertionError, self.do_test, none_s, [])
-        self.assertRaises(AssertionError, self.do_test, none, client_cert)
+        do_test(none, [])
+        self.assertRaises(AssertionError, do_test, none_s, [])
+        self.assertRaises(AssertionError, do_test, none, client_cert)
 
         # Strict SSL listener, SSL only
-        self.assertRaises(AssertionError, self.do_test, strict, [])
-        self.do_test(strict_s, [])
-        self.do_test(strict_s, client_cert_all)
-        self.do_test(strict, client_cert_all)
-        self.do_test(strict, trustfile)
-        self.do_test(strict, trustfile + client_cert_all)
-        self.assertRaises(AssertionError, self.do_test, strict, bad_trustfile)
+        self.assertRaises(AssertionError, do_test, strict, [])
+        do_test(strict_s, [])
+        do_test(strict_s, client_cert_all)
+        do_test(strict, client_cert_all)
+        do_test(strict, trustfile)
+        do_test(strict, trustfile + client_cert_all)
+        self.assertRaises(AssertionError, do_test, strict, bad_trustfile)
 
         # Requre-auth SSL listener
-        self.assertRaises(AssertionError, self.do_test, auth, [])
-        self.assertRaises(AssertionError, self.do_test, auth_s, [])
-        self.assertRaises(AssertionError, self.do_test, auth, trustfile)
-        self.do_test(auth, client_cert_all)
-        self.do_test(auth, client_cert_all + trustfile)
-        self.assertRaises(AssertionError, self.do_test, auth, client_cert_all + bad_trustfile)
+        self.assertRaises(AssertionError, do_test, auth, [])
+        self.assertRaises(AssertionError, do_test, auth_s, [])
+        self.assertRaises(AssertionError, do_test, auth, trustfile)
+        do_test(auth, client_cert_all)
+        do_test(auth, client_cert_all + trustfile)
+        self.assertRaises(AssertionError, do_test, auth, client_cert_all + bad_trustfile)
 
         # Unsecured SSL listener, allows non-SSL
-        self.do_test(unsecured_s, [])
-        self.do_test(unsecured_s, client_cert_all)
-        self.do_test(unsecured_s, trustfile)
-        self.do_test(unsecured_s, client_cert_all + trustfile)
-        self.do_test(unsecured_s, [])
-        self.do_test(unsecured, []) # Allow unsecured
-        self.assertRaises(AssertionError, self.do_test, auth, client_cert_all + bad_trustfile)
+        do_test(unsecured_s, [])
+        do_test(unsecured_s, client_cert_all)
+        do_test(unsecured_s, trustfile)
+        do_test(unsecured_s, client_cert_all + trustfile)
+        do_test(unsecured_s, [])
+        do_test(unsecured, []) # Allow unsecured
+        self.assertRaises(AssertionError, do_test, auth, client_cert_all + bad_trustfile)
 
 if __name__ == '__main__':
     unittest.main(system_test.main_module())

Modified: qpid/dispatch/trunk/tools/qdmanage
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tools/qdmanage?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/tools/qdmanage (original)
+++ qpid/dispatch/trunk/tools/qdmanage Fri Mar  6 22:39:45 2015
@@ -38,7 +38,7 @@ class QdManage():
 
         self.operations = ['QUERY', 'CREATE', 'READ', 'UPDATE', 'DELETE',
                            'GET-TYPES', 'GET-OPERATIONS', 'GET-ATTRIBUTES', 'GET-ANNOTATIONS',
-                           'GET-MGMT-NODES', 'GET-JSON-SCHEMA']
+                           'GET-MGMT-NODES', 'GET-SCHEMA', 'GET-LOG']
 
         usage = "%prog <operation> [options...] [arguments...]"
         description = "Standard operations: %s. Use GET-OPERATIONS to find additional operations."
\
@@ -59,15 +59,16 @@ class QdManage():
 
     def run(self, argv):
         self.opts, self.args = self.op.parse_args(argv[1:])
+        if self.opts.indent == -1: self.opts.indent = None
         if len(self.args) == 0: raise UsageError("No operation specified")
-        operation = self.args.pop(0)
         self.node = Node.connect(
             opts_url(self.opts), self.opts.router, self.opts.timeout, opts_ssl_domain(self.opts))
-        if operation.upper() in self.operations:
-            method = getattr(self, operation.lower().replace('-','_'))
-            method()
-        else:                   # Custom operation
-            self.operation(operation)
+        operation = self.args.pop(0)
+        method = operation.lower().replace('-','_')
+        if operation.upper() in self.operations and hasattr(self, method):
+            getattr(self, method)() # Built-in operation
+        else:
+            self.operation(operation) # Custom operation
 
     def main(self, argv):
         return main(self.run, argv, self.op)
@@ -76,6 +77,17 @@ class QdManage():
         """Print data as JSON"""
         print json.dumps(data, indent=self.opts.indent)
 
+    def print_result(self, result):
+        """Print a string result as-is, else try json dump, else print as-is"""
+        if not result: return
+        if isinstance(result, basestring):
+            print result
+        else:
+            try:
+                self.print_json(result)
+            except ValueError:
+                print result
+
     def call_node(self, method, *argnames, **kwargs):
         """Call method on node, use opts named in argnames"""
         names = set(argnames)
@@ -127,26 +139,22 @@ class QdManage():
 
     def get_types(self):
         """get-types [TYPE]         List entity types with their base types."""
-        check_args(self.args, 1)
-        if self.args: self.opts.type = self.args[0]
+        self.opts.type = check_args(self.args, 1)[0]
         self.print_json(self.call_node('get_types', 'type'))
 
     def get_annotations(self):
         """get-annotations [TYPE]   List entity types with the annotations they implement."""
-        check_args(self.args, 1)
-        if self.args: self.opts.type = self.args[0]
+        self.opts.type = check_args(self.args, 1)[0]
         self.print_json(self.call_node('get_annotations', 'type'))
 
     def get_attributes(self):
         """get-attributes [TYPE]    List entity types with their attributes."""
-        check_args(self.args, 1)
-        if self.args: self.opts.type = self.args[0]
+        self.opts.type = check_args(self.args, 1)[0]
         self.print_json(self.call_node('get_attributes', 'type'))
 
     def get_operations(self):
         """get-operations [TYPE]    List entity types with their operations."""
-        check_args(self.args, 1)
-        if self.args: self.opts.type = self.args[0]
+        self.opts.type = check_args(self.args, 1)[0]
         self.print_json(self.call_node('get_operations', 'type'))
 
     def get_mgmt_nodes(self):
@@ -154,14 +162,6 @@ class QdManage():
         check_args(self.args, 0)
         self.print_json(self.call_node('get_mgmt_nodes'))
 
-    def get_json_schema(self):
-        """get-schema-json [INDENT] Get the router schema in JSON format. Optional integer
indent for formatted output."""
-        check_args(self.args, 1, 0)
-        indent = None
-        if self.args: indent = self.args[0]
-        print self.node.call(self.node.request(
-            operation='GET-JSON-SCHEMA', identity='self', indent=indent)).body
-
     def json_arg(self, value):
         try:
             return json.loads(value)
@@ -179,7 +179,7 @@ class QdManage():
         if self.opts.body:
             body = self.json_arg(self.opts.body)
         request = self.call_node('request', 'type', 'name', 'identity', operation=operation,
body=body, **properties)
-        print self.node.call(request).body
+        self.print_result(self.node.call(request).body)
 
 if __name__ == "__main__":
     sys.exit(QdManage().main(sys.argv))

Modified: qpid/dispatch/trunk/tools/qdstat
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tools/qdstat?rev=1664739&r1=1664738&r2=1664739&view=diff
==============================================================================
--- qpid/dispatch/trunk/tools/qdstat (original)
+++ qpid/dispatch/trunk/tools/qdstat Fri Mar  6 22:39:45 2015
@@ -25,6 +25,7 @@ import sys
 import locale
 import socket
 import re
+from time import ctime
 from proton import Messenger, Message, Timeout
 import  qpid_dispatch_site
 from qpid_dispatch.management.client import Url, Node, Entity
@@ -47,11 +48,13 @@ def parse_args(argv):
     parser.add_option("-n", "--nodes", help="Show Router Nodes",            action="store_const",
const="n",   dest="show")
     parser.add_option("-a", "--address", help="Show Router Addresses",      action="store_const",
const="a",   dest="show")
     parser.add_option("-m", "--memory", help="Show Broker Memory Stats",    action="store_const",
const="m",   dest="show")
+    parser.add_option("--log", help="Show recent log entries", action="store_const", const="log",
dest="show")
+    parser.add_option("--limit", help="Limit number of log entries", type="int")
 
     opts, args = parser.parse_args(args=argv)
 
     if not opts.show:
-        parser.error("You must specify one of these options: -g, -c, -l, -n, -a, -m or -h.")
+        parser.error("You must specify one of these options: -g, -c, -l, -n, -a, -m, -h or
--log.")
 
     return opts, args
 
@@ -284,6 +287,11 @@ class BusManager(Node):
         dispRows = sorter.getSorted()
         disp.formattedTable(title, heads, dispRows)
 
+    def displayLog(self):
+        log = self.get_log(limit=self.opts.limit)
+        for line in log:
+            print "%s %s (%s) %s" % (ctime(line[5]), line[0], line[1], line[2])
+
     def displayMain(self, identitys, main):
         if   main == 'l': self.displayRouterLinks()
         elif main == 'n': self.displayRouterNodes()
@@ -291,12 +299,15 @@ class BusManager(Node):
         elif main == 'm': self.displayMemory()
         elif main == 'g': self.displayGeneral()
         elif main == 'c': self.displayConnections()
+        elif main == 'log': self.displayLog()
 
     def display(self, identitys):
         self.displayMain(identitys, self.opts.show)
 
 def run(argv):
     opts, args = parse_args(argv)
+    if args[1:]:
+        raise Exception("Unexpected arguments: %s" % " ".join(args[1:]))
     bm = BusManager(opts)
     try:
         bm.display(args)



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


Mime
View raw message