| #!/usr/bin/env python3 |
| |
| # |
| # 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 sys |
| from datetime import datetime |
| from time import ctime, strftime, gmtime |
| |
| import qpid_dispatch_site |
| qpid_dispatch_site.populate_pythonpath() |
| |
| from qpid_dispatch.management.client import Node |
| from qpid_dispatch_internal.management.qdrouter import QdSchema |
| from qpid_dispatch_internal.tools import Display, Header, Sorter, TimeLong, TimeShort, BodyFormat, PlainNum |
| from qpid_dispatch_internal.tools import NumKMG |
| from qpid_dispatch_internal.tools.command import (parse_args_qdstat, main, |
| opts_ssl_domain, opts_sasl, |
| opts_url) |
| from qpid_dispatch_internal.compat import UNICODE |
| |
| |
| def get(obj, attr): |
| return getattr(obj, attr, None) |
| |
| |
| class BusManager: |
| |
| schema = QdSchema() |
| |
| def __init__(self, opts): |
| self.opts = opts |
| self.node = Node.connect(opts_url(opts), opts.router, |
| timeout=opts.timeout, |
| ssl_domain=opts_ssl_domain(opts), |
| sasl=opts_sasl(opts), |
| edge_router=opts.edge_router) |
| self.show = getattr(self, opts.show) |
| self.bodyFormat = BodyFormat.CSV if opts.csv else BodyFormat.CLASSIC |
| |
| def query(self, entity_type, attribute_names=None, limit=None): |
| if attribute_names: |
| unames = [] |
| for a in attribute_names: |
| unames.append(UNICODE(a)) |
| attribute_names = unames |
| return self.node.query(entity_type, attribute_names, count=limit).get_entities() |
| |
| def close(self): |
| self.node.close() |
| |
| def connAuth(self, conn): |
| ## |
| # Summarize the authentication for a connection: |
| # no-auth |
| # anonymous-user |
| # <user>(PLAIN) |
| # <user>(kerberos) |
| # <user>(x.509) |
| ## |
| if not conn.isAuthenticated: |
| return "no-auth" |
| sasl = conn.sasl |
| if sasl == "GSSAPI": |
| sasl = "Kerberos" |
| elif sasl == "EXTERNAL": |
| sasl = "x.509" |
| elif sasl == "ANONYMOUS": |
| return "anonymous-user" |
| if not conn.user: |
| return sasl |
| 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 noTrailingSlash(self, text): |
| if text is None: |
| return "" |
| if text[-1:] == '/': |
| return text[:-1] |
| return text |
| |
| def displayRouterId(self): |
| objects = self.query('org.apache.qpid.dispatch.router') |
| router = objects[0] |
| if router: |
| print(router.id) |
| |
| def display_datetime_router_id(self): |
| print(str(datetime.utcnow()) + " UTC") |
| self.displayRouterId() |
| print("") |
| |
| def displayEdges(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("id")) |
| heads.append(Header("host")) |
| heads.append(Header("container")) |
| heads.append(Header("role")) |
| heads.append(Header("dir")) |
| heads.append(Header("security")) |
| heads.append(Header("authentication")) |
| heads.append(Header("tenant")) |
| |
| rows = [] |
| objects = self.query('org.apache.qpid.dispatch.connection', limit=self.opts.limit) |
| |
| if not objects: |
| if show_date_id: |
| self.display_datetime_router_id() |
| print("No Edge Router Connections") |
| return |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| has_active = False |
| |
| first = objects[0] |
| try: |
| if first: |
| active = first.active |
| has_active = True |
| except: |
| pass |
| |
| if has_active: |
| heads.append(Header("active")) |
| |
| for conn in objects: |
| if conn.role == "edge": |
| row = [] |
| row.append(conn.identity) |
| 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)) |
| row.append(self.noTrailingSlash(get(conn, 'tenant'))) |
| if has_active: |
| if conn.active: |
| row.append("yes") |
| else: |
| row.append("no") |
| rows.append(row) |
| |
| if rows: |
| title = "Connections" |
| else: |
| return |
| |
| dispRows = rows |
| disp.formattedTable(title, heads, dispRows) |
| |
| def displayConnections(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("id")) |
| heads.append(Header("host")) |
| heads.append(Header("container")) |
| heads.append(Header("role")) |
| heads.append(Header("proto")) |
| heads.append(Header("dir")) |
| heads.append(Header("security")) |
| heads.append(Header("authentication")) |
| heads.append(Header("tenant")) |
| |
| rows = [] |
| objects = self.query('org.apache.qpid.dispatch.connection', limit=self.opts.limit) |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| has_uptime = False |
| has_last_dlv = False |
| |
| if objects: |
| first_conn = objects[0] |
| try: |
| lastDlvSeconds = first_conn.lastDlvSeconds |
| has_last_dlv = True |
| except: |
| pass |
| try: |
| uptime = first_conn.uptimeSeconds |
| has_uptime = True |
| except: |
| pass |
| |
| # This is so that, this qdstat can be used against older routers without Python keyerrors |
| if has_last_dlv: |
| heads.append(Header("last dlv")) |
| if has_uptime: |
| heads.append(Header("uptime")) |
| |
| for conn in objects: |
| row = [] |
| row.append(conn.identity) |
| row.append(conn.host) |
| row.append(conn.container) |
| row.append(get(conn, 'role')) |
| row.append(conn.protocol) |
| row.append(conn.dir) |
| row.append(self.connSecurity(conn)) |
| row.append(self.connAuth(conn)) |
| row.append(self.noTrailingSlash(get(conn, 'tenant'))) |
| if has_last_dlv: |
| if conn.lastDlvSeconds is None: |
| row.append('-') |
| else: |
| row.append(TimeLong(conn.lastDlvSeconds)) |
| if has_uptime: |
| row.append(TimeLong(conn.uptimeSeconds)) |
| rows.append(row) |
| title = "Connections" |
| dispRows = rows |
| disp.formattedTable(title, heads, dispRows) |
| |
| def _addr_summary(self, addr): |
| cls = self._addr_class(addr) |
| phase = self._addr_phase(addr) |
| text = self._addr_text(addr) |
| if cls == '-': |
| return "-" |
| if cls == 'M': |
| if phase == '0': |
| return text |
| else: |
| return "%s:%s" % (phase, text) |
| return "%s:%s" % (cls, text) |
| |
| 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] == 'T' : |
| return "topo" |
| if addr[0] in 'CE' : |
| return "link-in" |
| if addr[0] in 'DF' : |
| return "link-out" |
| if addr[0] == 'H' : |
| return "edge" |
| 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, router_id=None): |
| if router_id: |
| return router_id |
| if not identity: |
| return "-" |
| pos = identity.find('/') |
| if pos >= 0: |
| return identity[pos + 1:] |
| return identity |
| |
| def _list_clean(self, inlist): |
| outlist = [] |
| if not inlist: |
| return outlist |
| for i in inlist: |
| outlist.append(str(i)) |
| return outlist |
| |
| def displayGeneral(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("attr")) |
| heads.append(Header("value")) |
| rows = [] |
| |
| objects = self.query('org.apache.qpid.dispatch.router') |
| |
| router = objects[0] |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| rows.append(('Version', router.version)) |
| rows.append(('Mode', router.mode)) |
| rows.append(('Router Id', router.id)) |
| try: |
| rows.append(('Worker Threads', PlainNum(router.workerThreads))) |
| except: |
| pass |
| |
| try: |
| rows.append(('Uptime', TimeLong(router.uptimeSeconds))) |
| except: |
| pass |
| |
| try: |
| if router.memoryUsage > 0: |
| rows.append(('VmSize', NumKMG(router.memoryUsage, |
| base=1024))) |
| except Exception: |
| pass |
| rows.append(('Area', router.area)) |
| rows.append(('Link Routes', PlainNum(router.linkRouteCount))) |
| rows.append(('Auto Links', PlainNum(router.autoLinkCount))) |
| rows.append(('Links', PlainNum(router.linkCount))) |
| rows.append(('Nodes', PlainNum(router.nodeCount))) |
| rows.append(('Addresses', PlainNum(router.addrCount))) |
| rows.append(('Connections', PlainNum(router.connectionCount))) |
| |
| # Overall delivery related counts. |
| # These overall statistics were introduced in 1.1 version. |
| # Wrap these in a try except so that newer versions of qdstat works with older version of router |
| try: |
| rows.append(('Presettled Count', PlainNum(router.presettledDeliveries))) |
| rows.append(('Dropped Presettled Count', PlainNum(router.droppedPresettledDeliveries))) |
| rows.append(('Accepted Count', PlainNum(router.acceptedDeliveries))) |
| rows.append(('Rejected Count', PlainNum(router.rejectedDeliveries))) |
| rows.append(('Released Count', PlainNum(router.releasedDeliveries))) |
| rows.append(('Modified Count', PlainNum(router.modifiedDeliveries))) |
| try: |
| rows.append(('Deliveries Delayed > 1sec', PlainNum(router.deliveriesDelayed1Sec))) |
| rows.append(('Deliveries Delayed > 10sec', PlainNum(router.deliveriesDelayed10Sec))) |
| rows.append(('Deliveries Stuck > 10sec', PlainNum(router.deliveriesStuck))) |
| rows.append(('Deliveries to Fallback', PlainNum(router.deliveriesRedirectedToFallback))) |
| try: |
| rows.append(('Links Blocked', PlainNum(router.linksBlocked))) |
| except: |
| pass |
| except: |
| pass |
| rows.append(('Ingress Count', PlainNum(router.deliveriesIngress))) |
| rows.append(('Egress Count', PlainNum(router.deliveriesEgress))) |
| rows.append(('Transit Count', PlainNum(router.deliveriesTransit))) |
| rows.append(('Deliveries from Route Container', PlainNum(router.deliveriesIngressRouteContainer))) |
| rows.append(('Deliveries to Route Container', PlainNum(router.deliveriesEgressRouteContainer))) |
| except: |
| pass |
| |
| title = "Router Statistics" |
| dispRows = rows |
| disp.formattedTable(title, heads, dispRows) |
| |
| def displayRouterLinks(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("type")) |
| heads.append(Header("dir")) |
| heads.append(Header("conn id")) |
| heads.append(Header("id")) |
| heads.append(Header("peer")) |
| heads.append(Header("class")) |
| heads.append(Header("addr")) |
| heads.append(Header("phs")) |
| heads.append(Header("cap", Header.PLAIN_NUM)) |
| |
| rows = [] |
| cols = ('linkType', 'linkDir', 'connectionId', 'identity', 'peer', 'owningAddr', |
| 'capacity', 'undeliveredCount', 'unsettledCount', 'deliveryCount', |
| 'presettledCount', 'droppedPresettledCount', 'acceptedCount', 'rejectedCount', 'releasedCount', |
| 'modifiedCount', 'deliveriesDelayed1Sec', 'deliveriesDelayed10Sec', 'deliveriesStuck', |
| 'creditAvailable', 'zeroCreditSeconds', |
| 'adminStatus', 'operStatus', 'linkName', 'priority', 'settleRate') |
| |
| objects = self.query('org.apache.qpid.dispatch.router.link', cols, limit=self.opts.limit) |
| |
| has_dropped_presettled_count = False |
| has_priority = False |
| has_delayed = False |
| has_stuck = False |
| has_credit = False |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| if objects: |
| first_row = objects[0] |
| if first_row: |
| if hasattr(first_row, 'droppedPresettledCount'): |
| has_dropped_presettled_count = True |
| if hasattr(first_row, 'priority'): |
| has_priority = True |
| if hasattr(first_row, 'deliveriesDelayed1Sec'): |
| has_delayed = True |
| if hasattr(first_row, 'deliveriesStuck'): |
| has_stuck = True |
| if hasattr(first_row, 'creditAvailable'): |
| has_credit = True |
| |
| if has_priority: |
| heads.append(Header("pri", Header.PLAIN_NUM)) |
| heads.append(Header("undel", Header.PLAIN_NUM)) |
| heads.append(Header("unsett", Header.PLAIN_NUM)) |
| heads.append(Header("deliv", Header.PLAIN_NUM)) |
| heads.append(Header("presett", Header.PLAIN_NUM)) |
| |
| if has_dropped_presettled_count: |
| heads.append(Header("psdrop", Header.PLAIN_NUM)) |
| |
| heads.append(Header("acc", Header.PLAIN_NUM)) |
| heads.append(Header("rej", Header.PLAIN_NUM)) |
| heads.append(Header("rel", Header.PLAIN_NUM)) |
| heads.append(Header("mod", Header.PLAIN_NUM)) |
| if has_delayed: |
| heads.append(Header("delay", Header.PLAIN_NUM)) |
| heads.append(Header("rate", Header.PLAIN_NUM)) |
| if has_stuck: |
| heads.append(Header("stuck", Header.PLAIN_NUM)) |
| if has_credit: |
| heads.append(Header("cred", Header.PLAIN_NUM)) |
| heads.append(Header("blkd")) |
| if self.opts.verbose: |
| heads.append(Header("admin")) |
| heads.append(Header("oper")) |
| heads.append(Header("name")) |
| |
| for link in objects: |
| row = [] |
| row.append(link.linkType) |
| row.append(link.linkDir) |
| row.append(link.connectionId) |
| row.append(link.identity) |
| row.append(link.peer) |
| row.append(self._addr_class(link.owningAddr)) |
| row.append(self._addr_text(link.owningAddr)) |
| row.append(self._addr_phase(link.owningAddr)) |
| row.append(link.capacity) |
| if has_priority: |
| row.append(link.priority) |
| row.append(link.undeliveredCount) |
| row.append(link.unsettledCount) |
| row.append(link.deliveryCount) |
| row.append(link.presettledCount) |
| if has_dropped_presettled_count: |
| row.append(link.droppedPresettledCount) |
| row.append(link.acceptedCount) |
| row.append(link.rejectedCount) |
| row.append(link.releasedCount) |
| row.append(link.modifiedCount) |
| if has_delayed: |
| row.append(link.deliveriesDelayed1Sec + link.deliveriesDelayed10Sec) |
| row.append(link.settleRate) |
| if has_stuck: |
| row.append(link.deliveriesStuck) |
| if has_credit: |
| row.append(link.creditAvailable) |
| if link.zeroCreditSeconds > 0: |
| row.append(TimeShort(link.zeroCreditSeconds * 1000000000)) |
| else: |
| row.append('-') |
| if self.opts.verbose: |
| row.append(link.adminStatus) |
| row.append(link.operStatus) |
| row.append(link.linkName) |
| rows.append(row) |
| title = "Router Links" |
| dispRows = rows |
| disp.formattedTable(title, heads, dispRows) |
| |
| def displayRouterNodes(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("router-id")) |
| heads.append(Header("next-hop")) |
| heads.append(Header("link")) |
| if self.opts.verbose: |
| heads.append(Header("ver")) |
| heads.append(Header("cost")) |
| heads.append(Header("neighbors")) |
| heads.append(Header("valid-origins")) |
| rows = [] |
| objects = self.query('org.apache.qpid.dispatch.router.node', limit=self.opts.limit) |
| |
| # Find the most recent topo change in this neighborhood. |
| lastTopoChange = 0.0 |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| for node in objects: |
| row = [] |
| if node.lastTopoChange: |
| if float(node.lastTopoChange) > lastTopoChange: |
| lastTopoChange = float(node.lastTopoChange) |
| row.append(node.id) |
| if node.nextHop is not None: |
| row.append(node.nextHop) |
| row.append('-') |
| else: |
| row.append('-') |
| row.append(PlainNum(node.routerLink)) |
| |
| if self.opts.verbose: |
| row.append(PlainNum(get(node, 'protocolVersion'))) |
| cost = get(node, 'cost') |
| if cost: |
| row.append(PlainNum(cost)) |
| else: |
| row.append("") |
| 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" |
| # Use gmtime to make times comparable across large networks. |
| if lastTopoChange > 1.0: |
| topoLine = "\nLast Topology Change: " + strftime('%A %b %d %H:%M:%S %Y', gmtime(lastTopoChange)) + " GMT" |
| title += topoLine |
| 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, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("class")) |
| heads.append(Header("addr")) |
| heads.append(Header("phs")) |
| heads.append(Header("distrib")) |
| |
| rows = [] |
| cols = ('distribution', 'inProcess', 'subscriberCount', 'remoteCount', |
| 'containerCount', 'deliveriesIngress', 'deliveriesEgress', 'deliveriesRedirectedToFallback', |
| 'deliveriesTransit', 'deliveriesToContainer', 'deliveriesFromContainer', 'name', 'priority') |
| |
| objects = self.query('org.apache.qpid.dispatch.router.address', cols, limit=self.opts.limit) |
| |
| has_priority = False |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| if objects: |
| first_row = objects[0] |
| if first_row: |
| if hasattr(first_row, 'priority'): |
| has_priority = True |
| |
| if has_priority: |
| heads.append(Header("pri")) |
| if self.opts.verbose: |
| heads.append(Header("in-proc", Header.COMMAS)) |
| 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("fallback", Header.COMMAS)) |
| if self.opts.verbose: |
| heads.append(Header("to-proc", Header.COMMAS)) |
| heads.append(Header("from-proc", Header.COMMAS)) |
| |
| for addr in objects: |
| row = [] |
| row.append(self._addr_class(addr.name)) |
| row.append(self._addr_text(addr.name)) |
| row.append(self._addr_phase(addr.name)) |
| row.append(addr.distribution) |
| if has_priority: |
| row.append(PlainNum(addr.priority) if addr.priority >= 0 else "-") |
| if self.opts.verbose: |
| row.append(PlainNum(addr.inProcess)) |
| row.append(PlainNum(addr.containerCount) if addr.name[0] in 'CDEF' else PlainNum(addr.subscriberCount)) |
| row.append(PlainNum(addr.remoteCount)) |
| row.append(PlainNum(addr.deliveriesIngress)) |
| row.append(PlainNum(addr.deliveriesEgress)) |
| row.append(PlainNum(addr.deliveriesTransit)) |
| try: |
| row.append(PlainNum(addr.deliveriesRedirectedToFallback)) |
| except: |
| row.append("-") |
| if self.opts.verbose: |
| row.append(PlainNum(addr.deliveriesToContainer)) |
| row.append(PlainNum(addr.deliveriesFromContainer)) |
| rows.append(row) |
| title = "Router Addresses" |
| sorter = Sorter(heads, rows, 'addr', 0, True) |
| dispRows = sorter.getSorted() |
| disp.formattedTable(title, heads, dispRows) |
| |
| def displayAutolinks(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("addr")) |
| heads.append(Header("dir")) |
| heads.append(Header("phs")) |
| heads.append(Header("extAddr")) |
| heads.append(Header("link")) |
| heads.append(Header("status")) |
| heads.append(Header("lastErr")) |
| rows = [] |
| cols = ('address', 'direction', 'phase', 'externalAddress', 'linkRef', 'operStatus', 'lastError') |
| |
| objects = self.query('org.apache.qpid.dispatch.router.config.autoLink', cols, limit=self.opts.limit) |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| if not objects: |
| print("AutoLinks") |
| print("No AutoLinks found") |
| return |
| |
| for al in objects: |
| row = [] |
| row.append(al.address) |
| row.append(al.direction) |
| row.append(PlainNum(al.phase)) |
| row.append(al.externalAddress) |
| row.append(al.linkRef) |
| row.append(al.operStatus) |
| row.append(al.lastError) |
| rows.append(row) |
| |
| title = "AutoLinks" |
| sorter = Sorter(heads, rows, 'addr', 0, True) |
| dispRows = sorter.getSorted() |
| disp.formattedTable(title, heads, dispRows) |
| |
| def displayLinkRoutes(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("address")) |
| heads.append(Header("dir")) |
| heads.append(Header("distrib")) |
| heads.append(Header("status")) |
| rows = [] |
| cols = ('prefix', 'direction', 'distribution', 'operStatus', 'pattern', 'addExternalPrefix', 'delExternalPrefix') |
| |
| link_routes = self.query('org.apache.qpid.dispatch.router.config.linkRoute', cols, limit=self.opts.limit) |
| |
| have_add_del_prefix = False |
| |
| if not link_routes: |
| if show_date_id: |
| self.display_datetime_router_id() |
| print("Link Routes") |
| print("No Link Routes found") |
| return |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| for link_route in link_routes: |
| row = [] |
| row.append(link_route.prefix if link_route.prefix else link_route.pattern) |
| row.append(link_route.direction) |
| row.append(link_route.distribution) |
| row.append(link_route.operStatus) |
| try: |
| if link_route.addExternalPrefix or link_route.delExternalPrefix: |
| row.append(link_route.addExternalPrefix) |
| row.append(link_route.delExternalPrefix) |
| have_add_del_prefix = True |
| except KeyError: |
| pass # added post 1.1.0 |
| rows.append(row) |
| title = "Link Routes" |
| if have_add_del_prefix: |
| heads.append(Header("add-ext-prefix")) |
| heads.append(Header("del-ext-prefix")) |
| sorter = Sorter(heads, rows, 'address', 0, True) |
| dispRows = sorter.getSorted() |
| disp.formattedTable(title, heads, dispRows) |
| |
| def displayMemory(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| 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 = [] |
| cols = ('identity', 'typeSize', 'transferBatchSize', 'localFreeListMax', |
| 'totalAllocFromHeap', 'heldByThreads', 'batchesRebalancedToThreads', |
| 'batchesRebalancedToGlobal') |
| |
| objects = self.query('org.apache.qpid.dispatch.allocator', cols) |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| pooled_total = 0 |
| memory_stats_enabled = True |
| for t in objects: |
| # t.totalAllocFromHeap is None *only* if memory stats is disabled. |
| if t.totalAllocFromHeap is None: |
| memory_stats_enabled = False |
| break |
| row = [] |
| row.append(self._identity_clean(t.identity)) |
| row.append(PlainNum(t.typeSize)) |
| row.append(PlainNum(t.transferBatchSize)) |
| row.append(PlainNum(t.localFreeListMax)) |
| row.append(PlainNum(t.totalAllocFromHeap)) |
| row.append(PlainNum(t.heldByThreads)) |
| row.append(PlainNum(t.batchesRebalancedToThreads)) |
| row.append(PlainNum(t.batchesRebalancedToGlobal)) |
| rows.append(row) |
| pooled_total += (t.typeSize * t.totalAllocFromHeap) |
| |
| if not rows or not memory_stats_enabled: |
| # router built w/o memory pools: |
| print("No memory statistics available") |
| return |
| |
| title = "Memory Pools" |
| sorter = Sorter(heads, rows, 'type', 0, True) |
| dispRows = sorter.getSorted() |
| disp.formattedTable(title, heads, dispRows) |
| |
| # attempt to get the qdrouterd process memory usage |
| # this may not be present on all platforms |
| rows = [] |
| try: |
| objects = self.query('org.apache.qpid.dispatch.router', ['memoryUsage']) |
| mem = objects[0].memoryUsage |
| except Exception: |
| mem = None |
| |
| if mem is not None: |
| hdr_format = Header.KiMiGi |
| rows.append(mem) |
| else: |
| hdr_format = Header.NONE |
| rows.append("-") |
| |
| rows.append(pooled_total) |
| |
| disp.formattedTable("\nMemory Summary", |
| [Header("VmSize", hdr_format), |
| Header("Pooled", Header.KiMiGi)], |
| [rows]) |
| |
| def displayPolicy(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| heads = [] |
| heads.append(Header("attr")) |
| heads.append(Header("value")) |
| rows = [] |
| |
| objects = self.query('org.apache.qpid.dispatch.policy') |
| |
| policy = objects[0] |
| |
| if show_date_id: |
| self.display_datetime_router_id() |
| |
| rows.append(('Maximum Concurrent Connections', PlainNum(policy.maxConnections))) |
| if 'maxMessageSize' in policy: |
| rows.append(('Maximum Message Size', PlainNum(policy.maxMessageSize))) |
| rows.append(('Enable Vhost Policy', policy.enableVhostPolicy)) |
| rows.append(('Enable Vhost Name Patterns', policy.enableVhostNamePatterns)) |
| rows.append(('Policy Directory', policy.policyDir if len(policy.policyDir) > 0 else '(nil)')) |
| rows.append(('Default Vhost', policy.defaultVhost if len(policy.defaultVhost) > 0 else '(nil)')) |
| disp.formattedTable("Policy Configuration", heads, rows) |
| |
| heads = [] |
| heads.append(Header("attr")) |
| heads.append(Header("value")) |
| rows = [] |
| |
| rows.append(('Connections Processed', PlainNum(policy.connectionsProcessed))) |
| rows.append(('Connections Denied', PlainNum(policy.connectionsDenied))) |
| rows.append(('Connections Current', PlainNum(policy.connectionsCurrent))) |
| rows.append(('Links Denied', PlainNum(policy.linksDenied))) |
| if 'maxMessageSizeDenied' in policy: |
| rows.append(('Maximum Message Size Denied', PlainNum(policy.maxMessageSizeDenied))) |
| rows.append(('Total Denials', PlainNum(policy.totalDenials))) |
| |
| disp.formattedTable("\nPolicy Status", heads, rows) |
| |
| def showNodefaultString(self, dict, key, schema): |
| return dict[key] if key in dict else schema[key]['default'] if 'default' in schema[key] else '(nil)' |
| |
| def showNodefaultBool(self, dict, key, schema): |
| return dict[key] if key in dict else schema[key]['default'] if 'default' in schema[key] else 'False' |
| |
| def showNodefaultInt(self, dict, key, schema): |
| return PlainNum(dict[key]) if key in dict else PlainNum(schema[key]['default']) if 'default' in schema[key] else '(nil)' |
| |
| def displayVhosts(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| |
| vhosts = self.query('org.apache.qpid.dispatch.vhost') |
| |
| if len(vhosts) == 0: |
| print("No Vhosts") |
| return |
| heads = [] |
| heads.append(Header("hostname")) |
| heads.append(Header("maxConnections")) |
| |
| have_max_message_size = False |
| if 'maxMessageSize' in vhosts[0]: |
| have_max_message_size = True |
| heads.append(Header('maxMessageSize')) |
| |
| heads.append(Header("maxConnectionsPerUser")) |
| heads.append(Header("maxConnectionsPerHost")) |
| heads.append(Header("allowUnknownUser")) |
| heads.append(Header("groups")) |
| |
| rows = [] |
| for vhost in vhosts: |
| row = [] |
| row.append(vhost.hostname) |
| row.append(PlainNum(vhost.maxConnections)) |
| if have_max_message_size: |
| row.append(PlainNum(vhost.maxMessageSize)) |
| row.append(PlainNum(vhost.maxConnectionsPerUser)) |
| row.append(PlainNum(vhost.maxConnectionsPerHost)) |
| row.append(vhost.allowUnknownUser) |
| row.append(PlainNum(len(vhost.groups))) |
| rows.append(tuple(row)) |
| |
| disp.formattedTable("Vhosts", heads, rows) |
| |
| def displayVhostgroups(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| |
| vhosts = self.query('org.apache.qpid.dispatch.vhost') |
| schema = self.node.get_schema() |
| vg_schema = schema['entityTypes']['vhostUserGroupSettings']['attributes'] |
| |
| if len(vhosts) == 0: |
| print("No Vhosts") |
| return |
| # Create table for all vhosts and groups omitting |
| # strings that are potentially 'very long'. |
| heads = [] |
| heads.append(Header("vhost")) |
| heads.append(Header("group")) |
| heads.append(Header("maxConnectionsPerUser")) |
| heads.append(Header("maxConnectionsPerHost")) |
| |
| have_max_message_size = False |
| if 'maxMessageSize' in vhosts[0]: |
| have_max_message_size = True |
| heads.append(Header('maxMessageSize')) |
| |
| heads.append(Header("maxFrameSize")) |
| heads.append(Header("maxSessionWindow")) |
| heads.append(Header("maxSessions")) |
| heads.append(Header("maxSenders")) |
| heads.append(Header("maxReceivers")) |
| heads.append(Header("allowDynamicSource")) |
| heads.append(Header("allowAnonymousSender")) |
| heads.append(Header("allowUserIdProxy")) |
| heads.append(Header("allowWaypointLinks")) |
| heads.append(Header("allowDynamicLinkRoutes")) |
| heads.append(Header("allowAdminStatusUpdate")) |
| heads.append(Header("allowFallbackLinks")) |
| rows = [] |
| for vhost in vhosts: |
| groups = vhost["groups"] |
| if len(groups) > 0: |
| for groupname in groups: |
| group = groups[groupname] |
| row = [] |
| row.append(vhost.hostname) |
| row.append(groupname) |
| row.append(self.showNodefaultInt(group, "maxConnectionsPerUser", vg_schema)) |
| row.append(self.showNodefaultInt(group, "maxConnectionsPerHost", vg_schema)) |
| if have_max_message_size: |
| row.append(self.showNodefaultInt(group, "maxMessageSize", vg_schema)) |
| row.append(self.showNodefaultInt(group, "maxFrameSize", vg_schema)) |
| row.append(self.showNodefaultInt(group, "maxSessionWindow", vg_schema)) |
| row.append(self.showNodefaultInt(group, "maxSessions", vg_schema)) |
| row.append(self.showNodefaultInt(group, "maxSenders", vg_schema)) |
| row.append(self.showNodefaultInt(group, "maxReceivers", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowDynamicSource", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowAnonymousSender", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowUserIdProxy", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowWaypointLinks", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowDynamicLinkRoutes", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowAdminStatusUpdate", vg_schema)) |
| row.append(self.showNodefaultBool(group, "allowFallbackLinks", vg_schema)) |
| rows.append(tuple(row)) |
| disp.formattedTable("Vhost Groups", heads, rows) |
| |
| # Create tables per vhost and per usergroup |
| # showing only potentially lengthy strings. |
| heads = [] |
| heads.append(Header("attr")) |
| heads.append(Header("value")) |
| |
| for vhost in vhosts: |
| groups = vhost["groups"] |
| if len(groups) > 0: |
| for groupname in groups: |
| group = groups[groupname] |
| rows = [] |
| rows.append(("vhost", vhost.hostname)) |
| rows.append(("group", groupname)) |
| rows.append(("users", self.showNodefaultString(group, "users", vg_schema))) |
| rows.append(("remoteHosts", self.showNodefaultString(group, "remoteHosts", vg_schema))) |
| rows.append(("sources", self.showNodefaultString(group, "sources", vg_schema))) |
| rows.append(("targets", self.showNodefaultString(group, "targets", vg_schema))) |
| rows.append(("sourcePattern", self.showNodefaultString(group, "sourcePattern", vg_schema))) |
| rows.append(("targetPattern", self.showNodefaultString(group, "targetPattern", vg_schema))) |
| disp.formattedTable(("\nVhost '%s' UserGroup '%s'" % (vhost.hostname, groupname)), heads, rows) |
| |
| def displayVhoststats(self, show_date_id=True): |
| disp = Display(prefix=" ", bodyFormat=self.bodyFormat) |
| |
| vstats = self.query('org.apache.qpid.dispatch.vhostStats') |
| |
| if len(vstats) == 0: |
| print("No Vhost Stats") |
| return |
| heads = [] |
| heads.append(Header("hostname")) |
| heads.append(Header("connectionsApproved")) |
| heads.append(Header("connectionsDenied")) |
| heads.append(Header("connectionsCurrent")) |
| heads.append(Header("sessionDenied")) |
| heads.append(Header("senderDenied")) |
| heads.append(Header("receiverDenied")) |
| have_max_message_size = False |
| if 'maxMessageSizeDenied' in vstats[0]: |
| have_max_message_size = True |
| heads.append(Header("maxMessageSizeDenied")) |
| rows = [] |
| |
| for vstat in vstats: |
| row = [] |
| row.append(vstat.hostname) |
| row.append(PlainNum(vstat.connectionsApproved)) |
| row.append(PlainNum(vstat.connectionsDenied)) |
| row.append(PlainNum(vstat.connectionsCurrent)) |
| row.append(PlainNum(vstat.sessionDenied)) |
| row.append(PlainNum(vstat.senderDenied)) |
| row.append(PlainNum(vstat.receiverDenied)) |
| if have_max_message_size: |
| row.append(PlainNum(vstat.maxMessageSizeDenied)) |
| rows.append(tuple(row)) |
| disp.formattedTable("Vhost Stats", heads, rows) |
| |
| heads = [] |
| heads.append(Header("vhost")) |
| heads.append(Header("user")) |
| heads.append(Header("remote hosts")) |
| rows = [] |
| |
| for vstat in vstats: |
| ustates = vstat["perUserState"] |
| if len(ustates) > 0: |
| for ustate in ustates: |
| rows.append(( |
| vstat.hostname, |
| ustate, |
| ustates[ustate] |
| )) |
| disp.formattedTable("\nVhost User Stats", heads, rows) |
| |
| def displayLog(self): |
| log = self.node.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 show_all(self, show_summary=True): |
| if show_summary: |
| # print the datetime and router id |
| print(str(datetime.utcnow()) + " UTC") |
| self.displayRouterId() |
| print("") |
| |
| self.displayRouterLinks(show_date_id=False) |
| print("") |
| self.displayAddresses(show_date_id=False) |
| print("") |
| self.displayConnections(show_date_id=False) |
| print("") |
| self.displayAutolinks(show_date_id=False) |
| print("") |
| self.displayLinkRoutes(show_date_id=False) |
| print("") |
| self.displayGeneral(show_date_id=False) |
| print("") |
| self.displayMemory(show_date_id=False) |
| print("") |
| self.displayPolicy(show_date_id=False) |
| print("") |
| self.displayVhosts(show_date_id=False) |
| print("") |
| # Groups is an ugly display. Show it only on demand. |
| # self.displayVhostgroups(show_date_id=False) |
| # print("") |
| self.displayVhoststats(show_date_id=False) |
| print("") |
| |
| def has_nodes(self): |
| all_nodes = self.node.get_mgmt_nodes() |
| has_nodes = True |
| if all_nodes: |
| if len(all_nodes) < 2: |
| has_nodes = False |
| else: |
| has_nodes = False |
| |
| return has_nodes, all_nodes |
| |
| def has_nodes(self): |
| all_nodes = self.node.get_mgmt_nodes() |
| has_nodes = True |
| if all_nodes: |
| if len(all_nodes) < 2: |
| has_nodes = False |
| else: |
| has_nodes = False |
| |
| return has_nodes, all_nodes |
| |
| def display(self): |
| has_nodes, nodes = self.has_nodes() |
| if self.opts.all_routers and has_nodes: |
| print(str(datetime.utcnow()) + " UTC") |
| for node in nodes: |
| self.node.set_client(node[6:]) |
| parts = node.split("/") |
| print("Router ", parts[3]) |
| print("") |
| if self.show.__name__ == 'show_all': |
| self.show(show_summary=False) |
| else: |
| self.show(show_date_id=False) |
| print("") |
| else: |
| self.show() |
| |
| |
| def run(argv): |
| args = parse_args_qdstat(BusManager) |
| bm = BusManager(args) |
| try: |
| bm.display() |
| finally: |
| bm.close() |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main(run)) |