|
#!/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() |