#!/usr/bin/env python # # 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. # import os from optparse import OptionGroup import sys import locale import socket import re from time import ctime import qpid_dispatch_site from qpid_dispatch.management.client import Url, Node, Entity from qpid_dispatch_internal.management.qdrouter import QdSchema from qpid_dispatch_internal.tools import Display, Header, Sorter, YN, Commas, TimeLong from qpid_dispatch_internal.tools.command import connection_options, main, OptionParser, opts_ssl_domain, opts_url def parse_args(argv): """ Set global variables for options, return arguments """ usage = "%prog [options]" parser = OptionParser(usage=usage) parser.add_option_group(connection_options(parser)) parser.add_option("-g", "--general", help="Show General Router Stats", action="store_const", const="g", dest="show") parser.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show") parser.add_option("-l", "--links", help="Show Router Links", action="store_const", const="l", dest="show") 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("-v", "--verbose", help="Show maximum detail", action="store_true", dest="verbose") 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, -h or --log.") return opts, args class BusManager(Node): schema = QdSchema() def __init__(self, opts): self.opts = opts super(BusManager, self).__init__( Node.connection(opts_url(opts), opts.router, timeout=opts.timeout, ssl_domain=opts_ssl_domain(opts))) def query(self, entity_type): return super(BusManager, self).query(entity_type).get_entities() def connAuth(self, conn): ## ## Summarize the authentication for a connection: ## no-auth ## anonymous-user ## (PLAIN) ## (kerberos) ## (x.509) ## if not conn.isAuthenticated: return "no-auth" sasl = conn.sasl if sasl == "GSSAPI": sasl = "Kerberos" if sasl == "EXTERNAL": sasl = "x.509" if sasl == "ANONYMOUS": return "anonymous-user" return "%s(%s)" % (conn.user, sasl) def connSecurity(self, conn): ## ## Summarize the security of a connection: ## no-security ## SSLv3 (cipher) ## TLS (cipher) ## Kerberos ## if not conn.isEncrypted: return "no-security" if conn.sasl == "GSSAPI": return "Kerberos" return "%s(%s)" % (conn.sslProto, conn.sslCipher) def displayConnections(self): disp = Display(prefix=" ") heads = [] heads.append(Header("state")) heads.append(Header("host")) heads.append(Header("container")) heads.append(Header("role")) heads.append(Header("dir")) heads.append(Header("security")) heads.append(Header("authentication")) rows = [] objects = self.query('org.apache.qpid.dispatch.connection') for conn in objects: row = [] row.append(conn.state) row.append(conn.host) row.append(conn.container) row.append(conn.role) row.append(conn.dir) row.append(self.connSecurity(conn)) row.append(self.connAuth(conn)) rows.append(row) title = "Connections" dispRows = rows disp.formattedTable(title, heads, dispRows) def _addr_class(self, addr): if not addr: return "-" if addr[0] == 'M' : return "mobile" if addr[0] == 'R' : return "router" if addr[0] == 'A' : return "area" if addr[0] == 'L' : return "local" if addr[0] == 'C' : return "link-route" return "unknown: %s" % addr[0] def _addr_text(self, addr): if not addr: return "-" if addr[0] == 'M': return addr[2:] else: return addr[1:] def _addr_phase(self, addr): if not addr: return "-" if addr[0] == 'M': return addr[1] return '' def _identity_clean(self, identity): if not identity: return "-" pos = identity.find('/') if pos >= 0: return identity[pos + 1:] return identity def _list_clean(self, inlist): outlist = [] for i in inlist: outlist.append(str(i)) return outlist def displayGeneral(self): disp = Display(prefix=" ") heads = [] heads.append(Header("attr")) heads.append(Header("value")) rows = [] objects = self.query('org.apache.qpid.dispatch.router') router = objects[0] rows.append(('Mode', router.mode)) rows.append(('Area', router.area)) rows.append(('Router Id', self._identity_clean(router.identity))) rows.append(('Address Count', router.addrCount)) rows.append(('Link Count', router.linkCount)) rows.append(('Node Count', router.nodeCount)) title = "Router Statistics" dispRows = rows disp.formattedTable(title, heads, dispRows) def displayRouterLinks(self): disp = Display(prefix=" ") heads = [] heads.append(Header("type")) heads.append(Header("dir")) heads.append(Header("rindex")) heads.append(Header("class")) heads.append(Header("address")) heads.append(Header("phase")) heads.append(Header("event-fifo")) heads.append(Header("msg-fifo")) rows = [] objects = self.query('org.apache.qpid.dispatch.router.link') for link in objects: row = [] row.append(link.linkType) row.append(link.linkDir) if link.linkType == "inter-router": row.append(self._identity_clean(link.identity)) else: row.append('-') row.append(self._addr_class(link.owningAddr)) row.append(self._addr_text(link.owningAddr)) row.append(self._addr_phase(link.owningAddr)) row.append(link.eventFifoDepth) if link.linkDir == 'out': row.append(link.msgFifoDepth) else: row.append('-') rows.append(row) title = "Router Links" dispRows = rows disp.formattedTable(title, heads, dispRows) def displayRouterNodes(self): disp = Display(prefix=" ") heads = [] heads.append(Header("router-id")) heads.append(Header("next-hop")) heads.append(Header("link")) if self.opts.verbose: heads.append(Header("neighbors")) heads.append(Header("valid-origins")) rows = [] objects = self.query('org.apache.qpid.dispatch.router.node') for node in objects: row = [] row.append(node.routerId) if node.nextHop != None: row.append(node.nextHop) row.append('-') else: row.append('-') row.append(node.routerLink) if self.opts.verbose: row.append('%r' % self._list_clean(node.linkState)) row.append('%r' % self._list_clean(node.validOrigins)) rows.append(row) if len(rows) > 0: title = "Routers in the Network" sort = Sorter(heads, rows, 'router-id') dispRows = sort.getSorted() disp.formattedTable(title, heads, dispRows) else: print "Router is Standalone - No Router List" def displayAddresses(self): disp = Display(prefix=" ") heads = [] heads.append(Header("class")) heads.append(Header("address")) heads.append(Header("phase")) heads.append(Header("in-proc", Header.Y)) heads.append(Header("local", Header.COMMAS)) heads.append(Header("remote", Header.COMMAS)) heads.append(Header("in", Header.COMMAS)) heads.append(Header("out", Header.COMMAS)) heads.append(Header("thru", Header.COMMAS)) heads.append(Header("to-proc", Header.COMMAS)) heads.append(Header("from-proc", Header.COMMAS)) rows = [] objects = self.query('org.apache.qpid.dispatch.router.address') for addr in objects: row = [] row.append(self._addr_class(self._identity_clean(addr.identity))) row.append(self._addr_text(self._identity_clean(addr.identity))) row.append(self._addr_phase(self._identity_clean(addr.identity))) row.append(addr.inProcess) row.append(addr.subscriberCount) row.append(addr.remoteCount) row.append(addr.deliveriesIngress) row.append(addr.deliveriesEgress) row.append(addr.deliveriesTransit) row.append(addr.deliveriesToContainer) row.append(addr.deliveriesFromContainer) rows.append(row) title = "Router Addresses" sorter = Sorter(heads, rows, 'address', 0, True) dispRows = sorter.getSorted() disp.formattedTable(title, heads, dispRows) def displayMemory(self): disp = Display(prefix=" ") heads = [] heads.append(Header("type")) heads.append(Header("size", Header.COMMAS)) heads.append(Header("batch")) heads.append(Header("thread-max", Header.COMMAS)) heads.append(Header("total", Header.COMMAS)) heads.append(Header("in-threads", Header.COMMAS)) heads.append(Header("rebal-in", Header.COMMAS)) heads.append(Header("rebal-out", Header.COMMAS)) rows = [] objects = self.query('org.apache.qpid.dispatch.allocator') for t in objects: row = [] row.append(self._identity_clean(t.identity)) row.append(t.typeSize) row.append(t.transferBatchSize) row.append(t.localFreeListMax) row.append(t.totalAllocFromHeap) row.append(t.heldByThreads) row.append(t.batchesRebalancedToThreads) row.append(t.batchesRebalancedToGlobal) rows.append(row) if not rows: # router built w/o memory pools: print "No memory statistics available" return title = "Types" sorter = Sorter(heads, rows, 'type', 0, True) 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() elif main == 'a': self.displayAddresses() 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) finally: bm.close() if __name__ == "__main__": sys.exit(main(run, sys.argv))