diff options
Diffstat (limited to 'qpid/cpp/management/python/bin/qmf-tool')
| -rwxr-xr-x | qpid/cpp/management/python/bin/qmf-tool | 775 |
1 files changed, 0 insertions, 775 deletions
diff --git a/qpid/cpp/management/python/bin/qmf-tool b/qpid/cpp/management/python/bin/qmf-tool deleted file mode 100755 index 407ae74b10..0000000000 --- a/qpid/cpp/management/python/bin/qmf-tool +++ /dev/null @@ -1,775 +0,0 @@ -#!/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 -import optparse -import sys -import socket -from cmd import Cmd -from shlex import split -from threading import Lock -from time import strftime, gmtime -from qpid.disp import Display -import qpid_messaging -import qmf2 - -class OptsAndArgs(object): - - def __init__(self, argv): - self.argv = argv - self.usage = """qmf-tool [OPTIONS] [<broker-host>[:<port>]]""" - self.option_parser = optparse.OptionParser(usage=self.usage) - self.conn_group = optparse.OptionGroup(self.option_parser, "Connection Options") - self.conn_group.add_option("-u", "--user", action="store", type="string", help="User name for authentication") - self.conn_group.add_option("-p", "--password", action="store", type="string", help="Password for authentication") - self.conn_group.add_option("-t", "--transport", action="store", type="string", help="Transport type (tcp, ssl, rdma)") - self.conn_group.add_option("-m", "--mechanism", action="store", type="string", help="SASL Mechanism for security") - self.conn_group.add_option("-s", "--service", action="store", type="string", default="qpidd", help="SASL Service name") - self.conn_group.add_option("--min-ssf", action="store", type="int", metavar="<n>", help="Minimum acceptable security strength factor") - self.conn_group.add_option("--max-ssf", action="store", type="int", metavar="<n>", help="Maximum acceptable security strength factor") - self.conn_group.add_option("--conn-option", action="append", default=[], metavar="<NAME=VALUE>", help="Additional connection option(s)") - self.option_parser.add_option_group(self.conn_group) - - self.qmf_group = optparse.OptionGroup(self.option_parser, "QMF Session Options") - self.qmf_group.add_option("--domain", action="store", type="string", help="QMF Domain") - self.qmf_group.add_option("--agent-age", action="store", type="int", metavar="<n>", help="Time, in minutes, to age out non-communicating agents") - self.qmf_group.add_option("--qmf-option", action="append", default=[], metavar="<NAME=VALUE>", help="Additional QMF session option(s)") - self.option_parser.add_option_group(self.qmf_group) - - def parse(self): - host = "localhost" - conn_options = {} - qmf_options = [] - - options, encArgs = self.option_parser.parse_args(args=self.argv) - try: - encoding = locale.getpreferredencoding() - args = [a.decode(encoding) for a in encArgs] - except: - args = encArgs - - if len(args) > 1: - host = args[1] - - if options.user: - conn_options["username"] = options.user - if options.password: - conn_options["password"] = options.password - if options.transport: - conn_options["transport"] = options.transport - if options.mechanism: - conn_options["sasl_mechanisms"] = options.mechanism - if options.service: - conn_options["sasl_service"] = options.service - if options.min_ssf: - conn_options["sasl_min_ssf"] = options.min_ssf - if options.max_ssf: - conn_options["sasl_max_ssf"] = options.max_ssf - for x in options.conn_option: - try: - key, val = x.split('=') - conn_options[key] = val - except: - raise Exception("Improperly formatted text for --conn-option: '%s'" % x) - - if options.domain: - qmf_options.append("domain:'%s'" % options.domain) - if options.agent_age: - qmf_options.append("max-agent-age:%d" % options.agent_age) - for x in options.qmf_option: - try: - key, val = x.split('=') - qmf_options.append("%s:%s" % (key, val)) - except: - raise Exception("Improperly formatted text for --qmf-option: '%s'" % x) - - qmf_string = '{' - first = True - for x in qmf_options: - if first: - first = None - else: - qmf_string += ',' - qmf_string += x - qmf_string += '}' - - return host, conn_options, qmf_string - - - -class Mcli(Cmd): - """ Management Command Interpreter """ - - def __init__(self, dataObject, dispObject): - Cmd.__init__(self) - self.dataObject = dataObject - self.dispObject = dispObject - self.dataObject.setCli(self) - self.prompt = "qmf: " - - def emptyline(self): - pass - - def setPromptMessage(self, p=None): - if p == None: - self.prompt = "qmf: " - else: - self.prompt = "qmf[%s]: " % p - - def do_help(self, data): - print "Management Tool for QMF" - print - print "Agent Commands:" - print " set filter <filter-string> - Filter the list of agents" - print " list agents - Print a list of the known Agents" - print " set default <item-number> - Set the default agent for operations" - print " show filter - Show the agent filter currently in effect" - print " show agent <item-number> - Print detailed information about an Agent" - print " show options - Show option strings used in the QMF session" - print - print "Schema Commands:" - print " list packages - Print a list of packages supported by the default agent" - print " list classes [<package-name>] - Print all classes supported byt the default agent" - print " show class <class-name> [<package-name>] - Show details of a class" - print - print "Data Commands:" - print " query <class-name> [<package-name>] [<predicate>] - Query for data from the agent" - print " list - List accumulated query results" - print " clear - Clear accumulated query results" - print " show <id> - Show details from a data object" - print " call <id> <method> [<args>] - Call a method on a data object" - print - print "General Commands:" - print " set time-format short - Select short timestamp format (default)" - print " set time-format long - Select long timestamp format" - print " quit or ^D - Exit the program" - print - - def complete_set(self, text, line, begidx, endidx): - """ Command completion for the 'set' command """ - tokens = split(line[:begidx]) - if len(tokens) == 1: - return [i for i in ('filter ', 'default ', 'time-format ') if i.startswith(text)] - if len(tokens) == 2 and tokens[1] == 'time-format': - return [i for i in ('long', 'short') if i.startswith(text)] - return [] - - def do_set(self, data): - tokens = split(data) - try: - if tokens[0] == "time-format": - self.dispObject.do_setTimeFormat(tokens[1]) - else: - self.dataObject.do_set(data) - except Exception, e: - print "Exception in set command:", e - - def complete_list(self, text, line, begidx, endidx): - tokens = split(line[:begidx]) - if len(tokens) == 1: - return [i for i in ('agents', 'packages', 'classes ') if i.startswith(text)] - return [] - - def do_list(self, data): - try: - self.dataObject.do_list(data) - except Exception, e: - print "Exception in list command:", e - - def complete_show(self, text, line, begidx, endidx): - tokens = split(line[:begidx]) - if len(tokens) == 1: - return [i for i in ('options', 'filter', 'agent ', 'class ') if i.startswith(text)] - return [] - - def do_show(self, data): - try: - self.dataObject.do_show(data) - except Exception, e: - print "Exception in show command:", e - - def complete_query(self, text, line, begidx, endidx): - return [] - - def do_query(self, data): - try: - self.dataObject.do_query(data) - except Exception, e: - if e.message.__class__ == qmf2.Data: - e = e.message.getProperties() - print "Exception in query command:", e - - def do_call(self, data): - try: - self.dataObject.do_call(data) - except Exception, e: - if e.message.__class__ == qmf2.Data: - e = e.message.getProperties() - print "Exception in call command:", e - - def do_clear(self, data): - try: - self.dataObject.do_clear(data) - except Exception, e: - print "Exception in clear command:", e - - def do_EOF(self, data): - print "quit" - try: - self.dataObject.do_exit() - except: - pass - return True - - def do_quit(self, data): - try: - self.dataObject.do_exit() - except: - pass - return True - - def postcmd(self, stop, line): - return stop - - def postloop(self): - print "Exiting..." - self.dataObject.close() - - -#====================================================================================================== -# QmfData -#====================================================================================================== -class QmfData: - """ - """ - def __init__(self, disp, url, conn_options, qmf_options): - self.disp = disp - self.url = url - self.conn_options = conn_options - self.qmf_options = qmf_options - self.agent_filter = '[]' - self.connection = qpid_messaging.Connection(self.url, **self.conn_options) - self.connection.open() - self.session = qmf2.ConsoleSession(self.connection, self.qmf_options) - self.session.setAgentFilter(self.agent_filter) - self.session.open() - self.lock = Lock() - self.cli = None - self.agents = {} # Map of number => agent object - self.deleted_agents = {} # Map of number => agent object - self.agent_numbers = {} # Map of agent name => number - self.next_number = 1 - self.focus_agent = None - self.data_list = {} - self.next_data_index = 1 - - #======================= - # Methods to support CLI - #======================= - def setCli(self, cli): - self.cli = cli - - def close(self): - try: - self.session.close() - self.connection.close() - except: - pass # we're shutting down - ignore any errors - - def do_list(self, data): - tokens = data.split() - if len(tokens) == 0: - self.listData() - elif tokens[0] == 'agents' or tokens[0] == 'agent': - self.listAgents() - elif tokens[0] == 'packages' or tokens[0] == 'package': - self.listPackages() - elif tokens[0] == 'classes' or tokens[0] == 'class': - self.listClasses(tokens[1:]) - - def do_set(self, data): - tokens = split(data) - if len(tokens) == 0: - print "What do you want to set? type 'help' for more information." - return - if tokens[0] == 'filter': - if len(tokens) == 2: - self.setAgentFilter(tokens[1]) - elif tokens[0] == 'default': - if len(tokens) == 2: - self.updateAgents() - number = int(tokens[1]) - self.focus_agent = self.agents[number] - print "Default Agent: %s" % self.focus_agent.getName() - - def do_show(self, data): - tokens = split(data) - if len(tokens) == 0: - print "What do you want to show? Type 'help' for more information." - return - - if tokens[0] == 'options': - print "Options used in this session:" - print " Connection Options : %s" % self.scrubConnOptions() - print " QMF Session Options: %s" % self.qmf_options - return - - if tokens[0] == 'agent': - self.showAgent(tokens[1:]) - return - - if tokens[0] == 'filter': - print self.agent_filter - return - - if tokens[0] == "default": - if not self.focus_agent: - self.updateAgents() - if self.focus_agent: - print "Default Agent: %s" % self.focus_agent.getName() - else: - print "Default Agent not set" - return - - if tokens[0] == "class": - self.showClass(tokens[1:]) - return - - if tokens[0].isdigit(): - self.showData(tokens[0]) - return - - print "What do you want to show? Type 'help' for more information." - return - - def do_query(self, data): - tokens = split(data) - if len(tokens) == 0: - print "Class name not specified." - return - cname = tokens[0] - pname = None - pred = None - if len(tokens) >= 2: - if tokens[1][0] == '[': - pred = tokens[1] - else: - pname = tokens[1] - if len(tokens) >= 3: - pred = tokens[2] - query = "{class:'%s'" % cname - if pname: - query += ",package:'%s'" % pname - if pred: - query += ",where:%s" % pred - query += "}" - if not self.focus_agent: - self.updateAgents() - d_list = self.focus_agent.query(query) - local_data_list = {} - for d in d_list: - local_data_list[self.next_data_index] = d - self.next_data_index += 1 - rows = [] - for index,val in local_data_list.items(): - rows.append((index, val.getAddr().getName())) - self.data_list[index] = val - self.disp.table("Data Objects Returned: %d:" % len(d_list), ("Number", "Data Address"), rows) - - def do_call(self, data): - tokens = split(data) - if len(tokens) < 2: - print "Data ID and method-name not specified." - return - idx = int(tokens[0]) - methodName = tokens[1] - args = [] - for arg in tokens[2:]: - ## - ## If the argument is a map, list, boolean, integer, or floating (one decimal point), - ## run it through the Python evaluator so it is converted to the correct type. - ## - ## TODO: use a regex for this instead of this convoluted logic - if arg[0] == '{' or arg[0] == '[' or arg == "True" or arg == "False" or \ - ((arg.count('.') < 2 and (arg.count('-') == 0 or \ - (arg.count('-') == 1 and arg[0] == '-')) and \ - arg.replace('.','').replace('-','').isdigit())): - args.append(eval(arg)) - else: - args.append(arg) - - if not idx in self.data_list: - print "Unknown data index, run 'query' to get a list of data indices" - return - - data = self.data_list[idx] - data._getSchema() - result = data._invoke(methodName, args, {}) - rows = [] - for k,v in result.items(): - rows.append((k,v)) - self.disp.table("Output Parameters:", ("Name", "Value"), rows) - - def do_clear(self, data): - self.data_list = {} - self.next_data_index = 1 - print "Accumulated query results cleared" - - def do_exit(self): - pass - - #==================== - # Sub-Command Methods - #==================== - def setAgentFilter(self, filt): - self.agent_filter = filt - self.session.setAgentFilter(filt) - - def updateAgents(self): - agents = self.session.getAgents() - number_list = [] - for agent in agents: - if agent.getName() not in self.agent_numbers: - number = self.next_number - number_list.append(number) - self.next_number += 1 - self.agent_numbers[agent.getName()] = number - self.agents[number] = agent - else: - ## Track seen agents so we can clean out deleted ones - number = self.agent_numbers[agent.getName()] - number_list.append(number) - if number in self.deleted_agents: - self.agents[number] = self.deleted_agents.pop(number) - deleted = [] - for number in self.agents: - if number not in number_list: - deleted.append(number) - for number in deleted: - self.deleted_agents[number] = self.agents.pop(number) - if not self.focus_agent: - self.focus_agent = self.session.getConnectedBrokerAgent() - - def listAgents(self): - self.updateAgents() - rows = [] - for number in self.agents: - agent = self.agents[number] - if self.focus_agent and agent.getName() == self.focus_agent.getName(): - d = '*' - else: - d = '' - rows.append((d, number, agent.getVendor(), agent.getProduct(), agent.getInstance(), agent.getEpoch())) - self.disp.table("QMF Agents:", ("", "Id", "Vendor", "Product", "Instance", "Epoch"), rows) - - def listPackages(self): - if not self.focus_agent: - raise "Default Agent not set - use 'set default'" - self.focus_agent.loadSchemaInfo() - packages = self.focus_agent.getPackages() - for p in packages: - print " %s" % p - - def getClasses(self, tokens): - if not self.focus_agent: - raise "Default Agent not set - use 'set default'" - return - self.focus_agent.loadSchemaInfo() - if len(tokens) == 1: - classes = self.focus_agent.getSchemaIds(tokens[0]); - else: - packages = self.focus_agent.getPackages() - classes = [] - for p in packages: - classes.extend(self.focus_agent.getSchemaIds(p)) - return classes - - def listClasses(self, tokens): - classes = self.getClasses(tokens) - rows = [] - for c in classes: - rows.append((c.getPackageName(), c.getName(), self.classTypeName(c.getType()))) - self.disp.table("Classes:", ("Package", "Class", "Type"), rows) - - def showClass(self, tokens): - if len(tokens) < 1: - return - classes = self.getClasses([]) - c = tokens[0] - p = None - if len(tokens) == 2: - p = tokens[1] - schema = None - sid = None - for cls in classes: - if c == cls.getName(): - if not p or p == cls.getPackageName(): - schema = self.focus_agent.getSchema(cls) - sid = cls - break - if not sid: - return - print "Class: %s:%s (%s) - %s" % \ - (sid.getPackageName(), sid.getName(), self.classTypeName(sid.getType()), schema.getDesc()) - print " hash: %r" % sid.getHash() - props = schema.getProperties() - methods = schema.getMethods() - rows = [] - for prop in props: - name = prop.getName() - dtype = self.typeName(prop.getType()) - if len(prop.getSubtype()) > 0: - dtype += "(%s)" % prop.getSubtype() - access = self.accessName(prop.getAccess()) - idx = self.yes_blank(prop.isIndex()) - opt = self.yes_blank(prop.isOptional()) - unit = prop.getUnit() - desc = prop.getDesc() - rows.append((name, dtype, idx, access, opt, unit, desc)) - self.disp.table("Properties:", ("Name", "Type", "Index", "Access", "Optional", "Unit", "Description"), rows) - if len(methods) > 0: - for meth in methods: - name = meth.getName() - desc = meth.getDesc() - if len(desc) > 0: - desc = " - " + desc - args = meth.getArguments() - rows = [] - for prop in args: - aname = prop.getName() - dtype = self.typeName(prop.getType()) - if len(prop.getSubtype()) > 0: - dtype += "(%s)" % prop.getSubtype() - unit = prop.getUnit() - adesc = prop.getDesc() - io = self.dirName(prop.getDirection()) - rows.append((aname, dtype, io, unit, adesc)) - print - print " Method: %s%s" % (name, desc) - self.disp.table("Arguments:", ("Name", "Type", "Dir", "Unit", "Description"), rows) - - def showAgent(self, tokens): - self.updateAgents() - for token in tokens: - number = int(token) - agent = self.agents[number] - print - print " ==================================================================================" - print " Agent Id: %d" % number - print " Agent Name: %s" % agent.getName() - print " Epoch: %d" % agent.getEpoch() - print " Attributes:" - attrs = agent.getAttributes() - keys = attrs.keys() - keys.sort() - pairs = [] - for key in keys: - if key == '_timestamp' or key == '_schema_updated': - val = disp.timestamp(attrs[key]) - else: - val = attrs[key] - pairs.append((key, val)) - self.printAlignedPairs(pairs) - agent.loadSchemaInfo() - print " Packages:" - packages = agent.getPackages() - for package in packages: - print " %s" % package - - def showData(self, idx): - num = int(idx) - if not num in self.data_list: - print "Data ID not known, run 'query' first to get data" - return - data = self.data_list[num] - props = data.getProperties() - rows = [] - for k,v in props.items(): - rows.append((k, v)) - self.disp.table("Properties:", ("Name", "Value"), rows) - - def listData(self): - if len(self.data_list) == 0: - print "No Query Results - Use the 'query' command" - return - rows = [] - for index,val in self.data_list.items(): - rows.append((index, val.getAgent().getName(), val.getAddr().getName())) - self.disp.table("Accumulated Query Results:", ('Number', 'Agent', 'Data Address'), rows) - - def printAlignedPairs(self, rows, indent=8): - maxlen = 0 - for first, second in rows: - if len(first) > maxlen: - maxlen = len(first) - maxlen += indent - for first, second in rows: - for i in range(maxlen - len(first)): - print "", - print "%s : %s" % (first, second) - - def classTypeName(self, code): - if code == qmf2.SCHEMA_TYPE_DATA: return "Data" - if code == qmf2.SCHEMA_TYPE_EVENT: return "Event" - return "Unknown" - - def typeName (self, typecode): - """ Convert type-codes to printable strings """ - if typecode == qmf2.SCHEMA_DATA_VOID: return "void" - elif typecode == qmf2.SCHEMA_DATA_BOOL: return "bool" - elif typecode == qmf2.SCHEMA_DATA_INT: return "int" - elif typecode == qmf2.SCHEMA_DATA_FLOAT: return "float" - elif typecode == qmf2.SCHEMA_DATA_STRING: return "string" - elif typecode == qmf2.SCHEMA_DATA_MAP: return "map" - elif typecode == qmf2.SCHEMA_DATA_LIST: return "list" - elif typecode == qmf2.SCHEMA_DATA_UUID: return "uuid" - else: - raise ValueError ("Invalid type code: %s" % str(typecode)) - - def valueByType(self, typecode, val): - if typecode == 1: return "%d" % val - elif typecode == 2: return "%d" % val - elif typecode == 3: return "%d" % val - elif typecode == 4: return "%d" % val - elif typecode == 6: return val - elif typecode == 7: return val - elif typecode == 8: return strftime("%c", gmtime(val / 1000000000)) - elif typecode == 9: - if val < 0: val = 0 - sec = val / 1000000000 - min = sec / 60 - hour = min / 60 - day = hour / 24 - result = "" - if day > 0: - result = "%dd " % day - if hour > 0 or result != "": - result += "%dh " % (hour % 24) - if min > 0 or result != "": - result += "%dm " % (min % 60) - result += "%ds" % (sec % 60) - return result - - elif typecode == 10: return str(self.idRegistry.displayId(val)) - elif typecode == 11: - if val: - return "True" - else: - return "False" - - elif typecode == 12: return "%f" % val - elif typecode == 13: return "%f" % val - elif typecode == 14: return "%r" % val - elif typecode == 15: return "%r" % val - elif typecode == 16: return "%d" % val - elif typecode == 17: return "%d" % val - elif typecode == 18: return "%d" % val - elif typecode == 19: return "%d" % val - elif typecode == 20: return "%r" % val - elif typecode == 21: return "%r" % val - elif typecode == 22: return "%r" % val - else: - raise ValueError ("Invalid type code: %s" % str(typecode)) - - def accessName (self, code): - """ Convert element access codes to printable strings """ - if code == qmf2.ACCESS_READ_CREATE: return "ReadCreate" - elif code == qmf2.ACCESS_READ_WRITE: return "ReadWrite" - elif code == qmf2.ACCESS_READ_ONLY: return "ReadOnly" - else: - raise ValueError ("Invalid access code: %s" % str(code)) - - def dirName(self, io): - if io == qmf2.DIR_IN: return "in" - elif io == qmf2.DIR_OUT: return "out" - elif io == qmf2.DIR_IN_OUT: return "in_out" - else: - raise ValueError("Invalid direction code: %r" % io) - - def notNone (self, text): - if text == None: - return "" - else: - return text - - def yes_blank(self, val): - if val: - return "Y" - return "" - - def objectIndex(self, obj): - if obj._objectId.isV2: - return obj._objectId.getObject() - result = "" - first = True - props = obj.getProperties() - for prop in props: - if prop[0].index: - if not first: - result += "." - result += self.valueByType(prop[0].type, prop[1]) - first = None - return result - - def scrubConnOptions(self): - scrubbed = {} - for key, val in self.conn_options.items(): - if key == "password": - val = "***" - scrubbed[key] = val - return str(scrubbed) - - -#========================================================= -# Main Program -#========================================================= -try: - oa = OptsAndArgs(sys.argv) - host, conn_options, qmf_options = oa.parse() -except Exception, e: - print "Parse Error: %s" % e - sys.exit(1) - -disp = Display() - -# Attempt to make a connection to the target broker -try: - data = QmfData(disp, host, conn_options, qmf_options) -except Exception, e: - if str(e).find("Exchange not found") != -1: - print "Management not enabled on broker: Use '-m yes' option on broker startup." - else: - print "Failed: %s - %s" % (e.__class__.__name__, e) - sys.exit(1) - -# Instantiate the CLI interpreter and launch it. -cli = Mcli(data, disp) -print("Management Tool for QMF") -try: - cli.cmdloop() -except KeyboardInterrupt: - print - print "Exiting..." -except Exception, e: - print "Failed: %s - %s" % (e.__class__.__name__, e) - -# alway attempt to cleanup broker resources -data.close() |
