class Sender(object): __slots__ = ('__conn', '__session') __exchange = 'amq.topic' def __init__(self, host='localhost', port=5672, timeout=5): self.__conn = None qpid.util.socket.setdefaulttimeout(timeout) if __debug__: print 'Connecting to %s:%d' % (host, port) sock = qpid.util.connect(host, port) self.__conn = Connection(sock=sock) self.__conn.start() self.__session = self.__conn.session(str(uuid4())) def __del__(self): if self.__conn: self.__conn.close() def send(self, routing_key, msg_text): propDelivery = self.__session.delivery_properties( routing_key = routing_key.__str__(), exchange = self.__exchange ) contentType = 'application/x-protobuf' propMessage = self.__session.message_properties( content_type = contentType) self.__session.message_transfer(destination = self.__exchange, message = Message(propDelivery, propMessage, msg_text))
def run(self): # Create connection and session socket = connect( self.host, self.port) connection = Connection(sock=socket, username=self.username, password=self.password) print("consumer "+self.queueName+": starting connection...") connection.start() print("consumer "+self.queueName+": ...connection started") print("consumer "+self.queueName+": getting session...") session = connection.session(str(uuid4())) print("consumer "+self.queueName+": ...session got") # Define local queue local_queue_name = 'my_local_queue_' +self.queueName # Create local queue print("consumer "+self.queueName+": getting queue...") queue = session.incoming(local_queue_name) print("consumer "+self.queueName+": ...queue got") # Route messages from message_queue to my_local_queue print("consumer "+self.queueName+": subscribing...") session.message_subscribe(queue = self.queueName, destination=local_queue_name) print("consumer "+self.queueName+": ...subscribed") print("consumer "+self.queueName+": starting queue...") queue.start() print("consumer "+self.queueName+": ...queue started") content = '' index = 0 while (self.running): try: # Get message from the local queue, timeout 5 seconds message = queue.get(timeout=5) except: break # exit this thread, consumer # Get body of the message content = message.body #message_properties = message.get("message_properties") # Accept message (removes it from the queue) session.message_accept(RangedSet(message.id)) if (content != ""): try: self.readGPB(content) except Exception, e: print( "Unexpected error: %s\n" % str(e) )
class IngestViaQPID: def __init__(self, host='localhost', port=5672, ssl=None): ''' Connect to QPID and make bindings to route message to external.dropbox queue @param host: string hostname of computer running EDEX and QPID (default localhost) @param port: integer port used to connect to QPID (default 5672) @param ssl: boolean to determine whether ssl is used, default value of None will use ssl only if a client certificate is found. ''' try: # socket = connect(host, port) if "QPID_SSL_CERT_DB" in os.environ: certdb = os.environ["QPID_SSL_CERT_DB"] else: certdb = os.path.expanduser("~/.qpid/") if "QPID_SSL_CERT_NAME" in os.environ: certname = os.environ["QPID_SSL_CERT_NAME"] else: certname = QPID_USERNAME certfile = os.path.join(certdb, certname + ".crt") if ssl or (ssl is None and os.path.exists(certfile)): keyfile = os.path.join(certdb, certname + ".key") trustfile = os.path.join(certdb, "root.crt") socket = qpid.util.ssl(socket, keyfile=keyfile, certfile=certfile, ca_certs=trustfile) self.connection = Connection (sock=socket, username=QPID_USERNAME, password=QPID_PASSWORD) self.connection.start() self.session = self.connection.session(str(uuid4())) self.session.exchange_bind(exchange='amq.direct', queue='external.dropbox', binding_key='external.dropbox') print 'Connected to Qpid' except: print 'Unable to connect to Qpid' def sendmessage(self, filepath, header): ''' This function sends a message to the external.dropbox queue providing the path to the file to be ingested and a header to determine the plugin to be used to decode the file. @param filepath: string full path to file to be ingested @param header: string header used to determine plugin decoder to use ''' props = self.session.delivery_properties(routing_key='external.dropbox') head = self.session.message_properties(application_headers={'header':header}, user_id=QPID_USERNAME) # For issue QPID-5569. Fixed in Qpid 0.27 self.session.message_transfer(destination='amq.direct', message=Message(props, head, filepath)) def close(self): ''' After all messages are sent call this function to close connection and make sure there are no threads left open ''' self.session.close(timeout=10) print 'Connection to Qpid closed'
class Receiver(object): __slots__ = ('__conn', '__session', '__queue') __exchange = 'amq.topic' def __init__(self, host='localhost', port=5672, timeout=5): self.__conn = self.__session = None if __debug__: print 'Connecting to %s:%d' % (host, port) qpid.util.socket.setdefaulttimeout(timeout) sock = qpid.util.connect(host, port) self.__conn = Connection(sock=sock) self.__conn.start() self.__session = self.__conn.session(str(uuid4())) def __del__(self): if self.__session: self.__session.close() if self.__conn: self.__conn.close() def setup(self, binding_keys, queue_name = 'queue_%d' % os.getpid()): # Setup queue self.__session.queue_declare(queue = queue_name, auto_delete = True, exclusive = False) for k in binding_keys: if __debug__: print 'Binding', k self.__session.exchange_bind(exchange = self.__exchange, queue = queue_name, binding_key = k) localQueueName = 'local_queue_%d' % os.getpid() self.__queue = self.__session.incoming(localQueueName) # Route messages from message_queue to my_local_queue self.__session.message_subscribe(queue = queue_name, destination = localQueueName) if __debug__: print 'Queue info:', self.__session.queue_query(queue_name) self.__queue.start() return self def fetch(self, timeout=None): message = self.__queue.get(timeout=timeout) self.__session.message_accept(RangedSet(message.id)) return message
class IngestViaQPID: def __init__(self, host='localhost', port=5672): ''' Connect to QPID and make bindings to route message to external.dropbox queue @param host: string hostname of computer running EDEX and QPID (default localhost) @param port: integer port used to connect to QPID (default 5672) ''' try: # self.socket = connect(host, port) self.connection = Connection(sock=self.socket, username=QPID_USERNAME, password=QPID_PASSWORD) self.connection.start() self.session = self.connection.session(str(uuid4())) self.session.exchange_bind(exchange='amq.direct', queue='external.dropbox', binding_key='external.dropbox') print('Connected to Qpid') except: print('Unable to connect to Qpid') def sendmessage(self, filepath, header): ''' This function sends a message to the external.dropbox queue providing the path to the file to be ingested and a header to determine the plugin to be used to decode the file. @param filepath: string full path to file to be ingested @param header: string header used to determine plugin decoder to use ''' props = self.session.delivery_properties( routing_key='external.dropbox') head = self.session.message_properties( application_headers={'header': header}, user_id=QPID_USERNAME) # For issue QPID-5569. Fixed in Qpid 0.27 self.session.message_transfer(destination='amq.direct', message=Message(props, head, filepath)) def close(self): ''' After all messages are sent call this function to close connection and make sure there are no threads left open ''' self.session.close(timeout=10) print('Connection to Qpid closed')
def start(self): """ Enable AMQP queueing. This method puts up the event processor and sets it to "active". """ self.log.debug("enabling AMQP queueing") # Evaluate username user = self.config.get("amqp.id", default=None) if not user: user = self.env.uuid password = self.config.get("amqp.key") # Create initial broker connection url = "%s:%s" % (self.url['host'], self.url['port']) self._conn = Connection.establish(url, reconnect=self.reconnect, username=user, password=password, transport=self.url['transport'], reconnect_interval=self.reconnect_interval, reconnect_limit=self.reconnect_limit) # Do automatic broker failover if requested if self.config.get('amqp.failover', False): auto_fetch_reconnect_urls(self._conn) # Create event exchange socket = connect(self.url['host'], self.url['port']) if self.url['scheme'][-1] == 's': socket = ssl(socket) user = self.config.get("amqp.id", default=None) if not user: user = self.env.uuid connection = DirectConnection(sock=socket, username=user, password=self.config.get("amqp.key")) connection.start() session = connection.session(str(uuid4())) # pylint: disable=E1103 session.exchange_declare(exchange=self.env.domain, type="xml") connection.close() # Create event provider self._eventProvider = EventProvider(self.env, self.getConnection())
class IngestViaQPID: def __init__(self, host='localhost', port=5672): ''' Connect to QPID and make bindings to route message to external.dropbox queue @param host: string hostname of computer running EDEX and QPID (default localhost) @param port: integer port used to connect to QPID (default 5672) ''' try: # self.socket = connect(host, port) self.connection = Connection (sock=self.socket, username=QPID_USERNAME, password=QPID_PASSWORD) self.connection.start() self.session = self.connection.session(str(uuid4())) self.session.exchange_bind(exchange='amq.direct', queue='external.dropbox', binding_key='external.dropbox') print('Connected to Qpid') except: print('Unable to connect to Qpid') def sendmessage(self, filepath, header): ''' This function sends a message to the external.dropbox queue providing the path to the file to be ingested and a header to determine the plugin to be used to decode the file. @param filepath: string full path to file to be ingested @param header: string header used to determine plugin decoder to use ''' props = self.session.delivery_properties(routing_key='external.dropbox') head = self.session.message_properties(application_headers={'header':header}, user_id=QPID_USERNAME) # For issue QPID-5569. Fixed in Qpid 0.27 self.session.message_transfer(destination='amq.direct', message=Message(props, head, filepath)) def close(self): ''' After all messages are sent call this function to close connection and make sure there are no threads left open ''' self.session.close(timeout=10) print('Connection to Qpid closed')
class BasilConnection(object): def __init__(self, model, host, port): self.model = model self.host = host self.port = port self.broker_id = "%s:%i" % (self.host, self.port) self.conn = Connection(connect(host, port), self.model.spec) self.mclient = managementClient( self.model.spec, None, self.model.on_props, self.model.on_stats, self.model.on_callback ) self.mclient.schemaListener(self.model.on_schema) self.chan = None self.model.connections[self.broker_id] = self def open(self): self.conn.start() self.chan = self.mclient.addChannel(self.conn.session(str(uuid4())), self) def close(self): self.mclient.removeChannel(self.chan)
def get_session(self, user, passwd): socket = connect(self.broker.host, self.broker.port) connection = Connection (sock=socket, username=user, password=passwd, mechanism="PLAIN") connection.start() return connection.session(str(uuid4()))
def dump_queue(binfo, queue_name, to): # Create a client and log in to it. child_connection = Connection(sock=connect(str(binfo['ip']), int(binfo['port']))) child_connection.start() child_session = child_connection.session(str(uuid4())) child_session.queue_declare(queue=queue_name, exclusive=True) child_session.exchange_bind(exchange='amq.direct', queue=queue_name, binding_key=queue_name) print 'Messages queue: ' + queue_name # Create the local queue. Use the queue name as destination name dest = queue_name queue = child_session.incoming(dest) # Subscribe the local queue to the queue on the server child_session.message_subscribe(queue=queue_name, destination=dest, accept_mode=child_session.accept_mode.explicit) child_session.message_flow(dest, child_session.credit_unit.message, 0xFFFFFFFFL) child_session.message_flow(dest, child_session.credit_unit.byte, 0xFFFFFFFFL) # Read responses as they come in and print to the screen. message = 0 count = 0 while True: try: message = queue.get(timeout=to) count = count + 1 if count == 1: print 'Received first reponse: %s ' % str(time.time()) except Empty: print 'Received %s messages: %s' % (str(count), str(time.time() - to)) break # except qpid.session.Closed: # print "Re-establishing" # try: # child_connection.close() # except: # pass # # # Give broker time to stablize and accept connections # time.sleep(2) # child_connection = Connection(sock=connect(str(binfo['ip']), int(binfo['port']))) # child_connection.start() # child_session = child_connection.session(str(uuid4())) # child_session.queue_declare(queue=queue_name, exclusive=True) # child_session.exchange_bind(exchange='amq.direct', queue=queue_name, binding_key=queue_name) # # # Create the local queue. Use the queue name as destination name # queue = child_session.incoming(dest) # # # Subscribe the local queue to the queue on the server # child_session.message_subscribe(queue=queue_name, destination=dest, accept_mode=child_session.accept_mode.explicit) # child_session.message_flow(dest, child_session.credit_unit.message, 0xFFFFFFFFL) # child_session.message_flow(dest, child_session.credit_unit.byte, 0xFFFFFFFFL) except: print 'Unexpected exception!' break if message != 0: child_session.message_accept(RangedSet(message.id)) child_session.close(timeout=10) child_connection.close() return (0)
class QpidAMQPHubExtension(BaseAMQPHubExtension): """ Initialize the Moksha Hub. `broker` [amqps://][<user>[/<password>]@]<host>[:<port>] """ def __init__(self, hub, config): self.config = config self.set_broker(self.config.get('amqp_broker')) self.socket = connect(self.host, self.port) if self.url.scheme == URL.AMQPS: self.socket = ssl(self.socket) self.connection = Connection(sock=self.socket, username=self.user, password=self.password) self.connection.start() log.info("Connected to AMQP Broker %s" % self.host) self.session = self.connection.session(str(uuid4())) self.local_queues = [] super(QpidAMQPHubExtension, self).__init__() def set_broker(self, broker): self.url = URL(broker) self.user = self.url.password or 'guest' self.password = self.url.password or 'guest' self.host = self.url.host if self.url.scheme == URL.AMQPS: self.ssl = True default_port = 5671 else: self.ssl = False default_port = 5672 self.port = self.url.port or default_port def send_message(self, topic, message, **headers): headers['routing_key'] = headers.get('routing_key', topic) props = self.session.delivery_properties(**headers) msg = Message(props, message) self.session.message_transfer(destination=headers.get( 'exchange', 'amq.topic'), message=msg) super(QpidAMQPHubExtension, self).send_message(topic, message, **headers) def subscribe_queue(self, server_queue_name, local_queue_name): queue = self.session.incoming(local_queue_name) self.session.message_subscribe(queue=server_queue_name, destination=local_queue_name) queue.start() return queue def queue_declare(self, queue, durable=True, exclusive=False, auto_delete=False, **kw): self.session.queue_declare(queue=queue, exclusive=exclusive, auto_delete=auto_delete, arguments={ 'qpid.max_count': 0, 'qpid.max_size': 0 }, **kw) def exchange_bind(self, queue, exchange='amq.topic', binding_key=None): self.session.exchange_bind(exchange=exchange, queue=queue, binding_key=binding_key) def message_subscribe(self, queue, destination): return self.session.message_subscribe(queue=queue, destination=destination) def message_accept(self, message): try: self.session.message_accept(RangedSet(message.id)) except SessionClosed: log.debug("Accepted message on closed session: %s" % message.id) pass def subscribe(self, topic, callback): queue_name = '_'.join([ "moksha_consumer", self.session.name, str(uuid4()), ]) server_queue_name = local_queue_name = queue_name self.queue_declare(queue=server_queue_name, exclusive=True, auto_delete=True) self.exchange_bind(server_queue_name, binding_key=topic) self.local_queues.append(self.session.incoming(local_queue_name)) self.message_subscribe(queue=server_queue_name, destination=local_queue_name) self.local_queues[-1].start() self.local_queues[-1].listen(callback) super(QpidAMQPHubExtension, self).subscribe(topic, callback) def close(self): self.session.close(timeout=2) self.connection.close(timeout=2) self.socket.close()
class QpidAMQPHubExtension(BaseAMQPHubExtension): """ Initialize the Moksha Hub. `broker` [amqps://][<user>[/<password>]@]<host>[:<port>] """ def __init__(self, hub, config): self.config = config self.set_broker(self.config.get('amqp_broker')) self.socket = connect(self.host, self.port) if self.url.scheme == URL.AMQPS: self.socket = ssl(self.socket) self.connection = Connection(sock=self.socket, username=self.user, password=self.password) self.connection.start() log.info("Connected to AMQP Broker %s" % self.host) self.session = self.connection.session(str(uuid4())) self.local_queues = [] super(QpidAMQPHubExtension, self).__init__() def set_broker(self, broker): self.url = URL(broker) self.user = self.url.password or 'guest' self.password = self.url.password or 'guest' self.host = self.url.host if self.url.scheme == URL.AMQPS: self.ssl = True default_port = 5671 else: self.ssl = False default_port = 5672 self.port = self.url.port or default_port def send_message(self, topic, message, **headers): headers['routing_key'] = headers.get('routing_key', topic) props = self.session.delivery_properties(**headers) msg = Message(props, message) self.session.message_transfer( destination=headers.get('exchange', 'amq.topic'), message=msg) super(QpidAMQPHubExtension, self).send_message( topic, message, **headers) def subscribe_queue(self, server_queue_name, local_queue_name): queue = self.session.incoming(local_queue_name) self.session.message_subscribe(queue=server_queue_name, destination=local_queue_name) queue.start() return queue def queue_declare(self, queue, durable=True, exclusive=False, auto_delete=False, **kw): self.session.queue_declare(queue=queue, exclusive=exclusive, auto_delete=auto_delete, arguments={'qpid.max_count': 0, 'qpid.max_size': 0}, **kw) def exchange_bind(self, queue, exchange='amq.topic', binding_key=None): self.session.exchange_bind(exchange=exchange, queue=queue, binding_key=binding_key) def message_subscribe(self, queue, destination): return self.session.message_subscribe(queue=queue, destination=destination) def message_accept(self, message): try: self.session.message_accept(RangedSet(message.id)) except SessionClosed: log.debug("Accepted message on closed session: %s" % message.id) pass def subscribe(self, topic, callback): queue_name = '_'.join([ "moksha_consumer", self.session.name, str(uuid4()), ]) server_queue_name = local_queue_name = queue_name self.queue_declare(queue=server_queue_name, exclusive=True, auto_delete=True) self.exchange_bind(server_queue_name, binding_key=topic) self.local_queues.append(self.session.incoming(local_queue_name)) self.message_subscribe(queue=server_queue_name, destination=local_queue_name) self.local_queues[-1].start() self.local_queues[-1].listen(callback) super(QpidAMQPHubExtension, self).subscribe(topic, callback) def close(self): self.session.close(timeout=2) self.connection.close(timeout=2) self.socket.close()
import time from qpid.datatypes import Message, RangedSet, serial from qpid.ops import * logging.basicConfig(level=logging.DEBUG) address = "amq.topic" sock = connect("127.0.0.1", "5672") conn = Connection(sock, username="******", password="******", vhost="/ssw", client_properties={"client_process": "aa"}) conn.start(timeout=10000) session = conn.session("PYTHON_SESSION") time.sleep(5) session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True) session.exchange_declare("test", "direct") session.exchange_bind(queue="test-queue", exchange="test", binding_key="key") session.message_subscribe(queue="test-queue", destination="consumer_tag", accept_mode=session.accept_mode.none, acquire_mode=session.acquire_mode.pre_acquired) session.message_flow(destination="consumer_tag", unit=session.credit_unit.message, value=0xFFFFFFFFL)
class ManagementData: # # Data Structure: # # Please note that this data structure holds only the most recent # configuration and instrumentation data for each object. It does # not hold the detailed historical data that is sent from the broker. # The only historical data it keeps are the high and low watermarks # for hi-lo statistics. # # tables :== {class-key} # {<obj-id>} # (timestamp, config-record, inst-record) # class-key :== (<package-name>, <class-name>, <class-hash>) # timestamp :== (<last-interval-time>, <create-time>, <delete-time>) # config-record :== [element] # inst-record :== [element] # element :== (<element-name>, <element-value>) # def registerObjId(self, objId): if not objId.index() in self.idBackMap: self.idBackMap[objId.index()] = self.nextId self.idMap[self.nextId] = objId self.nextId += 1 def displayObjId(self, objIdIndex): if objIdIndex in self.idBackMap: return self.idBackMap[objIdIndex] else: return 0 def rawObjId(self, displayId): if displayId in self.idMap: return self.idMap[displayId] else: return None def displayClassName(self, cls): (packageName, className, hash) = cls rev = self.schema[cls][4] if rev == 0: suffix = "" else: suffix = ".%d" % rev return packageName + ":" + className + suffix def dataHandler(self, context, className, list, timestamps): """ Callback for configuration and instrumentation data updates """ self.lock.acquire() try: # If this class has not been seen before, create an empty dictionary to # hold objects of this class if className not in self.tables: self.tables[className] = {} # Register the ID so a more friendly presentation can be displayed objId = list[0][1] oidx = objId.index() self.registerObjId(objId) # If this object hasn't been seen before, create a new object record with # the timestamps and empty lists for configuration and instrumentation data. if oidx not in self.tables[className]: self.tables[className][oidx] = (timestamps, [], []) (unused, oldConf, oldInst) = self.tables[className][oidx] # For config updates, simply replace old config list with the new one. if context == 0: #config self.tables[className][oidx] = (timestamps, list, oldInst) # For instrumentation updates, carry the minimum and maximum values for # "hi-lo" stats forward. elif context == 1: #inst if len(oldInst) == 0: newInst = list else: newInst = [] for idx in range(len(list)): (key, value) = list[idx] if key.find("High") == len(key) - 4: if oldInst[idx][1] > value: value = oldInst[idx][1] if key.find("Low") == len(key) - 3: if oldInst[idx][1] < value: value = oldInst[idx][1] newInst.append((key, value)) self.tables[className][oidx] = (timestamps, oldConf, newInst) finally: self.lock.release() def ctrlHandler(self, context, op, data): if op == self.mclient.CTRL_BROKER_INFO: pass elif op == self.mclient.CTRL_HEARTBEAT: pass def configHandler(self, context, className, list, timestamps): self.dataHandler(0, className, list, timestamps) def instHandler(self, context, className, list, timestamps): self.dataHandler(1, className, list, timestamps) def methodReply(self, broker, sequence, status, sText, args): """ Callback for method-reply messages """ self.lock.acquire() try: line = "Call Result: " + self.methodsPending[sequence] + \ " " + str (status) + " (" + sText + ")" print line, args del self.methodsPending[sequence] finally: self.lock.release() def closeHandler(self, context, reason): if self.operational: print "Connection to broker lost:", reason self.operational = False if self.cli != None: self.cli.setPromptMessage("Broker Disconnected") def schemaHandler(self, context, classKey, configs, insts, methods, events): """ Callback for schema updates """ if classKey not in self.schema: schemaRev = 0 for key in self.schema: if classKey[0] == key[0] and classKey[1] == key[1]: schemaRev += 1 self.schema[classKey] = (configs, insts, methods, events, schemaRev) def setCli(self, cliobj): self.cli = cliobj def __init__(self, disp, host, username="******", password="******"): self.lock = Lock() self.tables = {} self.schema = {} self.bootSequence = 0 self.operational = False self.disp = disp self.cli = None self.lastUnit = None self.methodSeq = 1 self.methodsPending = {} self.sessionId = "%s.%d" % (platform.uname()[1], os.getpid()) self.broker = Broker(host) sock = connect(self.broker.host, self.broker.port) oldTimeout = sock.gettimeout() sock.settimeout(10) self.conn = Connection(sock, username=self.broker.username, password=self.broker.password) def aborted(): raise Timeout( "Waiting for connection to be established with broker") oldAborted = self.conn.aborted self.conn.aborted = aborted self.conn.start() sock.settimeout(oldTimeout) self.conn.aborted = oldAborted self.mclient = managementClient("unused", self.ctrlHandler, self.configHandler, self.instHandler, self.methodReply, self.closeHandler) self.mclient.schemaListener(self.schemaHandler) self.mch = self.mclient.addChannel(self.conn.session(self.sessionId)) self.operational = True self.idMap = {} self.idBackMap = {} self.nextId = 101 def close(self): pass def refName(self, oid): if oid == None: return "NULL" return str(self.displayObjId(oid.index())) def valueDisplay(self, classKey, key, value): if value == None: return "<NULL>" for kind in range(2): schema = self.schema[classKey][kind] for item in schema: if item[0] == key: typecode = item[1] unit = item[2] if (typecode >= 1 and typecode <= 5) or typecode == 12 or typecode == 13 or \ (typecode >= 16 and typecode <= 19): if unit == None or unit == self.lastUnit: return str(value) else: self.lastUnit = unit suffix = "" if value != 1: suffix = "s" return str(value) + " " + unit + suffix elif typecode == 6 or typecode == 7: # strings return value elif typecode == 8: if value == 0: return "--" return self.disp.timestamp(value) elif typecode == 9: return str(value) elif typecode == 10: return self.refName(value) elif typecode == 11: if value == 0: return "False" else: return "True" elif typecode == 14: return str(value) elif typecode == 15: return str(value) return "*type-error*" def getObjIndex(self, classKey, config): """ Concatenate the values from index columns to form a unique object name """ result = "" schemaConfig = self.schema[classKey][0] for item in schemaConfig: if item[5] == 1 and item[0] != "id": if result != "": result = result + "." for key, val in config: if key == item[0]: result = result + self.valueDisplay(classKey, key, val) return result def getClassKey(self, className): delimPos = className.find(":") if delimPos == -1: schemaRev = 0 delim = className.find(".") if delim != -1: schemaRev = int(className[delim + 1:]) name = className[0:delim] else: name = className for key in self.schema: if key[1] == name and self.schema[key][4] == schemaRev: return key else: package = className[0:delimPos] name = className[delimPos + 1:] schemaRev = 0 delim = name.find(".") if delim != -1: schemaRev = int(name[delim + 1:]) name = name[0:delim] for key in self.schema: if key[0] == package and key[1] == name: if self.schema[key][4] == schemaRev: return key return None def classCompletions(self, prefix): """ Provide a list of candidate class names for command completion """ self.lock.acquire() complist = [] try: for name in self.tables: if name.find(prefix) == 0: complist.append(name) finally: self.lock.release() return complist def typeName(self, typecode): """ Convert type-codes to printable strings """ if typecode == 1: return "uint8" elif typecode == 2: return "uint16" elif typecode == 3: return "uint32" elif typecode == 4: return "uint64" elif typecode == 5: return "bool" elif typecode == 6: return "short-string" elif typecode == 7: return "long-string" elif typecode == 8: return "abs-time" elif typecode == 9: return "delta-time" elif typecode == 10: return "reference" elif typecode == 11: return "boolean" elif typecode == 12: return "float" elif typecode == 13: return "double" elif typecode == 14: return "uuid" elif typecode == 15: return "field-table" elif typecode == 16: return "int8" elif typecode == 17: return "int16" elif typecode == 18: return "int32" elif typecode == 19: return "int64" elif typecode == 20: return "object" elif typecode == 21: return "list" elif typecode == 22: return "array" else: raise ValueError("Invalid type code: %d" % typecode) def accessName(self, code): """ Convert element access codes to printable strings """ if code == 1: return "ReadCreate" elif code == 2: return "ReadWrite" elif code == 3: return "ReadOnly" else: raise ValueError("Invalid access code: %d" % code) def notNone(self, text): if text == None: return "" else: return text def isOid(self, id): for char in str(id): if not char.isdigit() and not char == '-': return False return True def listOfIds(self, classKey, tokens): """ Generate a tuple of object ids for a classname based on command tokens. """ list = [] if len(tokens) == 0 or tokens[0] == "all": for id in self.tables[classKey]: list.append(self.displayObjId(id)) elif tokens[0] == "active": for id in self.tables[classKey]: if self.tables[classKey][id][0][2] == 0: list.append(self.displayObjId(id)) else: for token in tokens: if self.isOid(token): if token.find("-") != -1: ids = token.split("-", 2) for id in range(int(ids[0]), int(ids[1]) + 1): if self.getClassForId(self.rawObjId( long(id))) == classKey: list.append(id) else: list.append(int(token)) list.sort() result = () for item in list: result = result + (item, ) return result def listClasses(self): """ Generate a display of the list of classes """ self.lock.acquire() try: rows = [] sorted = self.tables.keys() sorted.sort() for name in sorted: active = 0 deleted = 0 for record in self.tables[name]: isdel = False ts = self.tables[name][record][0] if ts[2] > 0: isdel = True if isdel: deleted = deleted + 1 else: active = active + 1 rows.append((self.displayClassName(name), active, deleted)) if len(rows) != 0: self.disp.table("Management Object Types:", ("ObjectType", "Active", "Deleted"), rows) else: print "Waiting for next periodic update" finally: self.lock.release() def listObjects(self, tokens): """ Generate a display of a list of objects in a class """ if len(tokens) == 0: print "Error - No class name provided" return self.lock.acquire() try: classKey = self.getClassKey(tokens[0]) if classKey == None: print("Object type %s not known" % tokens[0]) else: rows = [] if classKey in self.tables: ids = self.listOfIds(classKey, tokens[1:]) for objId in ids: (ts, config, inst) = self.tables[classKey][ self.rawObjId(objId).index()] createTime = self.disp.timestamp(ts[1]) destroyTime = "-" if ts[2] > 0: destroyTime = self.disp.timestamp(ts[2]) objIndex = self.getObjIndex(classKey, config) row = (objId, createTime, destroyTime, objIndex) rows.append(row) self.disp.table( "Objects of type %s" % self.displayClassName(classKey), ("ID", "Created", "Destroyed", "Index"), rows) finally: self.lock.release() def showObjects(self, tokens): """ Generate a display of object data for a particular class """ self.lock.acquire() try: self.lastUnit = None if self.isOid(tokens[0]): if tokens[0].find("-") != -1: rootId = int(tokens[0][0:tokens[0].find("-")]) else: rootId = int(tokens[0]) classKey = self.getClassForId(self.rawObjId(rootId)) remaining = tokens if classKey == None: print "Id not known: %d" % int(tokens[0]) raise ValueError() else: classKey = self.getClassKey(tokens[0]) remaining = tokens[1:] if classKey not in self.tables: print "Class not known: %s" % tokens[0] raise ValueError() userIds = self.listOfIds(classKey, remaining) if len(userIds) == 0: print "No object IDs supplied" raise ValueError() ids = [] for id in userIds: if self.getClassForId(self.rawObjId(long(id))) == classKey: ids.append(self.rawObjId(long(id))) rows = [] timestamp = None config = self.tables[classKey][ids[0].index()][1] for eIdx in range(len(config)): key = config[eIdx][0] if key != "id": row = ("property", key) for id in ids: if timestamp == None or \ timestamp < self.tables[classKey][id.index()][0][0]: timestamp = self.tables[classKey][id.index()][0][0] (key, value) = self.tables[classKey][id.index()][1][eIdx] row = row + (self.valueDisplay(classKey, key, value), ) rows.append(row) inst = self.tables[classKey][ids[0].index()][2] for eIdx in range(len(inst)): key = inst[eIdx][0] if key != "id": row = ("statistic", key) for id in ids: (key, value) = self.tables[classKey][id.index()][2][eIdx] row = row + (self.valueDisplay(classKey, key, value), ) rows.append(row) titleRow = ("Type", "Element") for id in ids: titleRow = titleRow + (self.refName(id), ) caption = "Object of type %s:" % self.displayClassName(classKey) if timestamp != None: caption = caption + " (last sample time: " + self.disp.timestamp( timestamp) + ")" self.disp.table(caption, titleRow, rows) except: pass self.lock.release() def schemaSummary(self): """ Generate a display of the list of classes in the schema """ self.lock.acquire() try: rows = [] sorted = self.schema.keys() sorted.sort() for classKey in sorted: tuple = self.schema[classKey] row = (self.displayClassName(classKey), len(tuple[0]), len(tuple[1]), len(tuple[2])) rows.append(row) self.disp.table("Classes in Schema:", ("Class", "Properties", "Statistics", "Methods"), rows) finally: self.lock.release() def schemaTable(self, className): """ Generate a display of details of the schema of a particular class """ self.lock.acquire() try: classKey = self.getClassKey(className) if classKey == None: print("Class name %s not known" % className) raise ValueError() rows = [] schemaRev = self.schema[classKey][4] for config in self.schema[classKey][0]: name = config[0] if name != "id": typename = self.typeName(config[1]) unit = self.notNone(config[2]) desc = self.notNone(config[3]) access = self.accessName(config[4]) extra = "" if config[5] == 1: extra += "index " if config[6] != None: extra += "Min: " + str(config[6]) + " " if config[7] != None: extra += "Max: " + str(config[7]) + " " if config[8] != None: extra += "MaxLen: " + str(config[8]) + " " if config[9] == 1: extra += "optional " rows.append((name, typename, unit, access, extra, desc)) for config in self.schema[classKey][1]: name = config[0] if name != "id": typename = self.typeName(config[1]) unit = self.notNone(config[2]) desc = self.notNone(config[3]) rows.append((name, typename, unit, "", "", desc)) titles = ("Element", "Type", "Unit", "Access", "Notes", "Description") self.disp.table( "Schema for class '%s':" % self.displayClassName(classKey), titles, rows) for mname in self.schema[classKey][2]: (mdesc, args) = self.schema[classKey][2][mname] caption = "\nMethod '%s' %s" % (mname, self.notNone(mdesc)) rows = [] for arg in args: name = arg[0] typename = self.typeName(arg[1]) dir = arg[2] unit = self.notNone(arg[3]) desc = self.notNone(arg[4]) extra = "" if arg[5] != None: extra = extra + "Min: " + str(arg[5]) if arg[6] != None: extra = extra + "Max: " + str(arg[6]) if arg[7] != None: extra = extra + "MaxLen: " + str(arg[7]) if arg[8] != None: extra = extra + "Default: " + str(arg[8]) rows.append((name, typename, dir, unit, extra, desc)) titles = ("Argument", "Type", "Direction", "Unit", "Notes", "Description") self.disp.table(caption, titles, rows) except Exception, e: pass self.lock.release()
print '%s' % error.msg print 'Attempting to retrieve config from %s' % conf_file try: broker_info = read_config_file(conf_file, 'Broker') except ConfigError, error: print '%s' % error.msg print 'Exiting' return(FAILURE) replyTo = str(uuid4()) # Create a client and log in to it. connection = Connection(sock=connect(str(broker_info['ip']), int(broker_info['port']))) connection.start() session = connection.session(str(uuid4())) session.queue_declare(queue=replyTo, exclusive=True, auto_delete=True) session.queue_declare(queue=broker_info['queue'], exclusive=False, durable="true") session.exchange_bind(exchange='amq.direct', queue=broker_info['queue'], binding_key='grid') session.exchange_bind(exchange='amq.direct', queue=replyTo, binding_key=replyTo) # Create the local queue. Use the queue name as destination name dest = replyTo recv_queue = session.incoming(dest) print 'Messages queue: ' + dest # Subscribe the local queue to the queue on the server session.message_subscribe(queue=replyTo, destination=dest, accept_mode=session.accept_mode.explicit) session.message_flow(dest, session.credit_unit.message, 0xFFFFFFFFL) session.message_flow(dest, session.credit_unit.byte, 0xFFFFFFFFL)
options.targets = [t.strip() for t in options.targets.split(',')] # Create connection and session session_dicts = [] for target in options.targets: print "Attempting to setup connection with", target try: socket = connect(target, 5672) connection = Connection( socket, username='******', password='******', ) connection.start(timeout=10000) session = connection.session(str(uuid4())) # Setup routing properties print "Talking to %s on topic %s" % (target, options.topic) properties = session.delivery_properties(routing_key=options.topic) session_dicts.append({ 'target': target, 'socket': socket, 'connection': connection, 'session': session, 'properties': properties, }) print " Created target", target except Exception as e: print " Failed to create target", target print str(e)
def dump_queue(queue, ses, con, num_msgs, to, dest, broker): # Read responses as they come in and print to the screen. message = 0 count = 0 expected = 2*int(num_msgs) while True: try: message = queue.get(timeout=to) content = message.body count = count + 1 job_data = message.get('message_properties').application_headers print 'Reply Message ID: ' + str(message.get('message_properties').message_id) print 'Correlation ID: ' + str(message.get('message_properties').correlation_id) print 'Headers:' for header in job_data.keys(): print header + ': ' + str(job_data[header]) # print '' # print 'Body: ' # print content print '' except Empty: if count < expected: print 'Only received %d messages but expected %d. TEST FAILED!' % (count, expected) else: print 'Received %d messages. TEST PASSED.' % count break except qpid.session.Closed: try: con.close() except: pass # Give broker time to stablize and accept connections time.sleep(2) con = Connection(sock=connect(str(broker['ip']), int(broker['port']))) con.start() ses = con.session(str(uuid4())) ses.queue_declare(queue=dest, exclusive=True) ses.queue_declare(queue=broker['queue'], exclusive=False, durable=True) ses.exchange_bind(exchange='amq.direct', queue=broker['queue'], binding_key='grid') ses.exchange_bind(exchange='amq.direct', queue=dest, binding_key=dest) # Create the local queue. Use the queue name as destination name queue = ses.incoming(dest) # Subscribe the local queue to the queue on the server ses.message_subscribe(queue=dest, destination=dest, accept_mode=ses.accept_mode.explicit) ses.message_flow(dest, ses.credit_unit.message, 0xFFFFFFFFL) ses.message_flow(dest, ses.credit_unit.byte, 0xFFFFFFFFL) except: print 'Unexpected exception!' break if message != 0: ses.message_accept(RangedSet(message.id)) return (0)
class ManagementData: # # Data Structure: # # Please note that this data structure holds only the most recent # configuration and instrumentation data for each object. It does # not hold the detailed historical data that is sent from the broker. # The only historical data it keeps are the high and low watermarks # for hi-lo statistics. # # tables :== {class-key} # {<obj-id>} # (timestamp, config-record, inst-record) # class-key :== (<package-name>, <class-name>, <class-hash>) # timestamp :== (<last-interval-time>, <create-time>, <delete-time>) # config-record :== [element] # inst-record :== [element] # element :== (<element-name>, <element-value>) # def registerObjId (self, objId): if not objId.index() in self.idBackMap: self.idBackMap[objId.index()] = self.nextId self.idMap[self.nextId] = objId self.nextId += 1 def displayObjId (self, objIdIndex): if objIdIndex in self.idBackMap: return self.idBackMap[objIdIndex] else: return 0 def rawObjId (self, displayId): if displayId in self.idMap: return self.idMap[displayId] else: return None def displayClassName (self, cls): (packageName, className, hash) = cls rev = self.schema[cls][4] if rev == 0: suffix = "" else: suffix = ".%d" % rev return packageName + ":" + className + suffix def dataHandler (self, context, className, list, timestamps): """ Callback for configuration and instrumentation data updates """ self.lock.acquire () try: # If this class has not been seen before, create an empty dictionary to # hold objects of this class if className not in self.tables: self.tables[className] = {} # Register the ID so a more friendly presentation can be displayed objId = list[0][1] oidx = objId.index() self.registerObjId (objId) # If this object hasn't been seen before, create a new object record with # the timestamps and empty lists for configuration and instrumentation data. if oidx not in self.tables[className]: self.tables[className][oidx] = (timestamps, [], []) (unused, oldConf, oldInst) = self.tables[className][oidx] # For config updates, simply replace old config list with the new one. if context == 0: #config self.tables[className][oidx] = (timestamps, list, oldInst) # For instrumentation updates, carry the minimum and maximum values for # "hi-lo" stats forward. elif context == 1: #inst if len (oldInst) == 0: newInst = list else: newInst = [] for idx in range (len (list)): (key, value) = list[idx] if key.find ("High") == len (key) - 4: if oldInst[idx][1] > value: value = oldInst[idx][1] if key.find ("Low") == len (key) - 3: if oldInst[idx][1] < value: value = oldInst[idx][1] newInst.append ((key, value)) self.tables[className][oidx] = (timestamps, oldConf, newInst) finally: self.lock.release () def ctrlHandler (self, context, op, data): if op == self.mclient.CTRL_BROKER_INFO: pass elif op == self.mclient.CTRL_HEARTBEAT: pass def configHandler (self, context, className, list, timestamps): self.dataHandler (0, className, list, timestamps); def instHandler (self, context, className, list, timestamps): self.dataHandler (1, className, list, timestamps); def methodReply (self, broker, sequence, status, sText, args): """ Callback for method-reply messages """ self.lock.acquire () try: line = "Call Result: " + self.methodsPending[sequence] + \ " " + str (status) + " (" + sText + ")" print line, args del self.methodsPending[sequence] finally: self.lock.release () def closeHandler (self, context, reason): if self.operational: print "Connection to broker lost:", reason self.operational = False if self.cli != None: self.cli.setPromptMessage ("Broker Disconnected") def schemaHandler (self, context, classKey, configs, insts, methods, events): """ Callback for schema updates """ if classKey not in self.schema: schemaRev = 0 for key in self.schema: if classKey[0] == key[0] and classKey[1] == key[1]: schemaRev += 1 self.schema[classKey] = (configs, insts, methods, events, schemaRev) def setCli (self, cliobj): self.cli = cliobj def __init__ (self, disp, host, username="******", password="******"): self.lock = Lock () self.tables = {} self.schema = {} self.bootSequence = 0 self.operational = False self.disp = disp self.cli = None self.lastUnit = None self.methodSeq = 1 self.methodsPending = {} self.sessionId = "%s.%d" % (platform.uname()[1], os.getpid()) self.broker = Broker (host) sock = connect (self.broker.host, self.broker.port) oldTimeout = sock.gettimeout() sock.settimeout(10) self.conn = Connection (sock, username=self.broker.username, password=self.broker.password) def aborted(): raise Timeout("Waiting for connection to be established with broker") oldAborted = self.conn.aborted self.conn.aborted = aborted self.conn.start () sock.settimeout(oldTimeout) self.conn.aborted = oldAborted self.mclient = managementClient ("unused", self.ctrlHandler, self.configHandler, self.instHandler, self.methodReply, self.closeHandler) self.mclient.schemaListener (self.schemaHandler) self.mch = self.mclient.addChannel (self.conn.session(self.sessionId)) self.operational = True self.idMap = {} self.idBackMap = {} self.nextId = 101 def close (self): pass def refName (self, oid): if oid == None: return "NULL" return str (self.displayObjId (oid.index())) def valueDisplay (self, classKey, key, value): if value == None: return "<NULL>" for kind in range (2): schema = self.schema[classKey][kind] for item in schema: if item[0] == key: typecode = item[1] unit = item[2] if (typecode >= 1 and typecode <= 5) or typecode == 12 or typecode == 13 or \ (typecode >= 16 and typecode <= 19): if unit == None or unit == self.lastUnit: return str (value) else: self.lastUnit = unit suffix = "" if value != 1: suffix = "s" return str (value) + " " + unit + suffix elif typecode == 6 or typecode == 7: # strings return value elif typecode == 8: if value == 0: return "--" return self.disp.timestamp (value) elif typecode == 9: return str (value) elif typecode == 10: return self.refName (value) elif typecode == 11: if value == 0: return "False" else: return "True" elif typecode == 14: return str (value) elif typecode == 15: return str (value) return "*type-error*" def getObjIndex (self, classKey, config): """ Concatenate the values from index columns to form a unique object name """ result = "" schemaConfig = self.schema[classKey][0] for item in schemaConfig: if item[5] == 1 and item[0] != "id": if result != "": result = result + "." for key,val in config: if key == item[0]: result = result + self.valueDisplay (classKey, key, val) return result def getClassKey (self, className): delimPos = className.find(":") if delimPos == -1: schemaRev = 0 delim = className.find(".") if delim != -1: schemaRev = int(className[delim + 1:]) name = className[0:delim] else: name = className for key in self.schema: if key[1] == name and self.schema[key][4] == schemaRev: return key else: package = className[0:delimPos] name = className[delimPos + 1:] schemaRev = 0 delim = name.find(".") if delim != -1: schemaRev = int(name[delim + 1:]) name = name[0:delim] for key in self.schema: if key[0] == package and key[1] == name: if self.schema[key][4] == schemaRev: return key return None def classCompletions (self, prefix): """ Provide a list of candidate class names for command completion """ self.lock.acquire () complist = [] try: for name in self.tables: if name.find (prefix) == 0: complist.append (name) finally: self.lock.release () return complist def typeName (self, typecode): """ Convert type-codes to printable strings """ if typecode == 1: return "uint8" elif typecode == 2: return "uint16" elif typecode == 3: return "uint32" elif typecode == 4: return "uint64" elif typecode == 5: return "bool" elif typecode == 6: return "short-string" elif typecode == 7: return "long-string" elif typecode == 8: return "abs-time" elif typecode == 9: return "delta-time" elif typecode == 10: return "reference" elif typecode == 11: return "boolean" elif typecode == 12: return "float" elif typecode == 13: return "double" elif typecode == 14: return "uuid" elif typecode == 15: return "field-table" elif typecode == 16: return "int8" elif typecode == 17: return "int16" elif typecode == 18: return "int32" elif typecode == 19: return "int64" elif typecode == 20: return "object" elif typecode == 21: return "list" elif typecode == 22: return "array" else: raise ValueError ("Invalid type code: %d" % typecode) def accessName (self, code): """ Convert element access codes to printable strings """ if code == 1: return "ReadCreate" elif code == 2: return "ReadWrite" elif code == 3: return "ReadOnly" else: raise ValueError ("Invalid access code: %d" %code) def notNone (self, text): if text == None: return "" else: return text def isOid (self, id): for char in str (id): if not char.isdigit () and not char == '-': return False return True def listOfIds (self, classKey, tokens): """ Generate a tuple of object ids for a classname based on command tokens. """ list = [] if len(tokens) == 0 or tokens[0] == "all": for id in self.tables[classKey]: list.append (self.displayObjId (id)) elif tokens[0] == "active": for id in self.tables[classKey]: if self.tables[classKey][id][0][2] == 0: list.append (self.displayObjId (id)) else: for token in tokens: if self.isOid (token): if token.find ("-") != -1: ids = token.split("-", 2) for id in range (int (ids[0]), int (ids[1]) + 1): if self.getClassForId (self.rawObjId (long (id))) == classKey: list.append (id) else: list.append (int(token)) list.sort () result = () for item in list: result = result + (item,) return result def listClasses (self): """ Generate a display of the list of classes """ self.lock.acquire () try: rows = [] sorted = self.tables.keys () sorted.sort () for name in sorted: active = 0 deleted = 0 for record in self.tables[name]: isdel = False ts = self.tables[name][record][0] if ts[2] > 0: isdel = True if isdel: deleted = deleted + 1 else: active = active + 1 rows.append ((self.displayClassName (name), active, deleted)) if len (rows) != 0: self.disp.table ("Management Object Types:", ("ObjectType", "Active", "Deleted"), rows) else: print "Waiting for next periodic update" finally: self.lock.release () def listObjects (self, tokens): """ Generate a display of a list of objects in a class """ if len(tokens) == 0: print "Error - No class name provided" return self.lock.acquire () try: classKey = self.getClassKey (tokens[0]) if classKey == None: print ("Object type %s not known" % tokens[0]) else: rows = [] if classKey in self.tables: ids = self.listOfIds(classKey, tokens[1:]) for objId in ids: (ts, config, inst) = self.tables[classKey][self.rawObjId(objId).index()] createTime = self.disp.timestamp (ts[1]) destroyTime = "-" if ts[2] > 0: destroyTime = self.disp.timestamp (ts[2]) objIndex = self.getObjIndex (classKey, config) row = (objId, createTime, destroyTime, objIndex) rows.append (row) self.disp.table ("Objects of type %s" % self.displayClassName(classKey), ("ID", "Created", "Destroyed", "Index"), rows) finally: self.lock.release () def showObjects (self, tokens): """ Generate a display of object data for a particular class """ self.lock.acquire () try: self.lastUnit = None if self.isOid (tokens[0]): if tokens[0].find ("-") != -1: rootId = int (tokens[0][0:tokens[0].find ("-")]) else: rootId = int (tokens[0]) classKey = self.getClassForId (self.rawObjId (rootId)) remaining = tokens if classKey == None: print "Id not known: %d" % int (tokens[0]) raise ValueError () else: classKey = self.getClassKey (tokens[0]) remaining = tokens[1:] if classKey not in self.tables: print "Class not known: %s" % tokens[0] raise ValueError () userIds = self.listOfIds (classKey, remaining) if len (userIds) == 0: print "No object IDs supplied" raise ValueError () ids = [] for id in userIds: if self.getClassForId (self.rawObjId (long (id))) == classKey: ids.append (self.rawObjId (long (id))) rows = [] timestamp = None config = self.tables[classKey][ids[0].index()][1] for eIdx in range (len (config)): key = config[eIdx][0] if key != "id": row = ("property", key) for id in ids: if timestamp == None or \ timestamp < self.tables[classKey][id.index()][0][0]: timestamp = self.tables[classKey][id.index()][0][0] (key, value) = self.tables[classKey][id.index()][1][eIdx] row = row + (self.valueDisplay (classKey, key, value),) rows.append (row) inst = self.tables[classKey][ids[0].index()][2] for eIdx in range (len (inst)): key = inst[eIdx][0] if key != "id": row = ("statistic", key) for id in ids: (key, value) = self.tables[classKey][id.index()][2][eIdx] row = row + (self.valueDisplay (classKey, key, value),) rows.append (row) titleRow = ("Type", "Element") for id in ids: titleRow = titleRow + (self.refName(id),) caption = "Object of type %s:" % self.displayClassName(classKey) if timestamp != None: caption = caption + " (last sample time: " + self.disp.timestamp (timestamp) + ")" self.disp.table (caption, titleRow, rows) except: pass self.lock.release () def schemaSummary (self): """ Generate a display of the list of classes in the schema """ self.lock.acquire () try: rows = [] sorted = self.schema.keys () sorted.sort () for classKey in sorted: tuple = self.schema[classKey] row = (self.displayClassName(classKey), len (tuple[0]), len (tuple[1]), len (tuple[2])) rows.append (row) self.disp.table ("Classes in Schema:", ("Class", "Properties", "Statistics", "Methods"), rows) finally: self.lock.release () def schemaTable (self, className): """ Generate a display of details of the schema of a particular class """ self.lock.acquire () try: classKey = self.getClassKey (className) if classKey == None: print ("Class name %s not known" % className) raise ValueError () rows = [] schemaRev = self.schema[classKey][4] for config in self.schema[classKey][0]: name = config[0] if name != "id": typename = self.typeName(config[1]) unit = self.notNone (config[2]) desc = self.notNone (config[3]) access = self.accessName (config[4]) extra = "" if config[5] == 1: extra += "index " if config[6] != None: extra += "Min: " + str(config[6]) + " " if config[7] != None: extra += "Max: " + str(config[7]) + " " if config[8] != None: extra += "MaxLen: " + str(config[8]) + " " if config[9] == 1: extra += "optional " rows.append ((name, typename, unit, access, extra, desc)) for config in self.schema[classKey][1]: name = config[0] if name != "id": typename = self.typeName(config[1]) unit = self.notNone (config[2]) desc = self.notNone (config[3]) rows.append ((name, typename, unit, "", "", desc)) titles = ("Element", "Type", "Unit", "Access", "Notes", "Description") self.disp.table ("Schema for class '%s':" % self.displayClassName(classKey), titles, rows) for mname in self.schema[classKey][2]: (mdesc, args) = self.schema[classKey][2][mname] caption = "\nMethod '%s' %s" % (mname, self.notNone (mdesc)) rows = [] for arg in args: name = arg[0] typename = self.typeName (arg[1]) dir = arg[2] unit = self.notNone (arg[3]) desc = self.notNone (arg[4]) extra = "" if arg[5] != None: extra = extra + "Min: " + str (arg[5]) if arg[6] != None: extra = extra + "Max: " + str (arg[6]) if arg[7] != None: extra = extra + "MaxLen: " + str (arg[7]) if arg[8] != None: extra = extra + "Default: " + str (arg[8]) rows.append ((name, typename, dir, unit, extra, desc)) titles = ("Argument", "Type", "Direction", "Unit", "Notes", "Description") self.disp.table (caption, titles, rows) except Exception,e: pass self.lock.release ()