summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRafael H. Schloming <rhs@apache.org>2010-02-14 14:59:24 +0000
committerRafael H. Schloming <rhs@apache.org>2010-02-14 14:59:24 +0000
commit074811c4bf1531f04b11db25f348e6c520bc4799 (patch)
treedd46e4aa9bdaca64974bbddc810f3212d935edd5 /python
parenta025819835829ea7658e4886ddb6e5e488f916eb (diff)
downloadqpid-python-074811c4bf1531f04b11db25f348e6c520bc4799.tar.gz
moved qpid-* tools out of qpid/python into qpid/tools; moved qmf library into extras/qmf
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@910016 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'python')
-rw-r--r--python/Makefile8
-rwxr-xr-xpython/commands/qpid-cluster327
-rwxr-xr-xpython/commands/qpid-config572
-rwxr-xr-xpython/commands/qpid-printevents74
-rwxr-xr-xpython/commands/qpid-queue-stats146
-rwxr-xr-xpython/commands/qpid-route524
-rwxr-xr-xpython/commands/qpid-stat459
-rwxr-xr-xpython/commands/qpid-tool197
-rw-r--r--python/qmf/__init__.py18
-rw-r--r--python/qmf/console.py1972
-rw-r--r--python/qmf2/__init__.py18
-rw-r--r--python/qmf2/agent.py961
-rw-r--r--python/qmf2/common.py1943
-rw-r--r--python/qmf2/console.py2295
-rw-r--r--python/qmf2/tests/__init__.py29
-rw-r--r--python/qmf2/tests/agent_discovery.py484
-rw-r--r--python/qmf2/tests/agent_test.py167
-rw-r--r--python/qmf2/tests/async_method.py362
-rw-r--r--python/qmf2/tests/async_query.py462
-rw-r--r--python/qmf2/tests/basic_method.py406
-rw-r--r--python/qmf2/tests/basic_query.py516
-rw-r--r--python/qmf2/tests/console_test.py175
-rw-r--r--python/qmf2/tests/events.py208
-rw-r--r--python/qmf2/tests/multi_response.py295
-rw-r--r--python/qmf2/tests/obj_gets.py599
-rw-r--r--python/setup.py11
26 files changed, 4 insertions, 13224 deletions
diff --git a/python/Makefile b/python/Makefile
index 59d38bd53f..ebae6a8ea4 100644
--- a/python/Makefile
+++ b/python/Makefile
@@ -31,7 +31,7 @@ else
AMQP_SPEC_DIR=$(PWD)/$(DATA_DIR)/amqp
endif
-DIRS=qmf qpid mllib examples
+DIRS=qpid mllib examples
SRCS=$(shell find $(DIRS) -name "*.py") qpid_config.py
BUILD=build
TARGETS=$(SRCS:%.py=$(BUILD)/%.py)
@@ -71,12 +71,8 @@ install: build
install -pm 0644 $(BUILD)/qpid/tests/*.* $(PYTHON_LIB)/qpid/tests
$(PYCC) $(PYTHON_LIB)/qpid
- install -d $(PYTHON_LIB)/qmf
- install -pm 0644 LICENSE.txt NOTICE.txt qmf/*.* $(PYTHON_LIB)/qmf
- $(PYCC) $(PYTHON_LIB)/qmf
-
install -d $(EXEC_PREFIX)
- install -pm 0755 qpid-python-test commands/* $(EXEC_PREFIX)
+ install -pm 0755 qpid-python-test $(EXEC_PREFIX)
clean:
rm -rf $(BUILD)
diff --git a/python/commands/qpid-cluster b/python/commands/qpid-cluster
deleted file mode 100755
index 6d64765184..0000000000
--- a/python/commands/qpid-cluster
+++ /dev/null
@@ -1,327 +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 getopt
-import sys
-import locale
-import socket
-import re
-from qmf.console import Session
-
-class Config:
- def __init__(self):
- self._host = "localhost"
- self._connTimeout = 10
- self._stopId = None
- self._stopAll = False
- self._force = False
- self._numeric = False
- self._showConn = False
- self._delConn = None
-
-def usage ():
- print "Usage: qpid-cluster [OPTIONS] [broker-addr]"
- print
- print " broker-addr is in the form: [username/password@] hostname | ip-address [:<port>]"
- print " ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost"
- print
- print "Options:"
- print " --timeout seconds (10) Maximum time to wait for broker connection"
- print " -C [--all-connections] View client connections to all cluster members"
- print " -c [--connections] ID View client connections to specified member"
- print " -d [--del-connection] HOST:PORT"
- print " Disconnect a client connection"
- print " -s [--stop] ID Stop one member of the cluster by its ID"
- print " -k [--all-stop] Shut down the whole cluster"
- print " -f [--force] Suppress the 'are-you-sure?' prompt"
- print " -n [--numeric] Don't resolve names"
- print
-
-class IpAddr:
- def __init__(self, text):
- if text.find("@") != -1:
- tokens = text.split("@")
- text = tokens[1]
- if text.find(":") != -1:
- tokens = text.split(":")
- text = tokens[0]
- self.port = int(tokens[1])
- else:
- self.port = 5672
- self.dottedQuad = socket.gethostbyname(text)
- nums = self.dottedQuad.split(".")
- self.addr = (int(nums[0]) << 24) + (int(nums[1]) << 16) + (int(nums[2]) << 8) + int(nums[3])
-
- def bestAddr(self, addrPortList):
- bestDiff = 0xFFFFFFFFL
- bestAddr = None
- for addrPort in addrPortList:
- diff = IpAddr(addrPort[0]).addr ^ self.addr
- if diff < bestDiff:
- bestDiff = diff
- bestAddr = addrPort
- return bestAddr
-
-class BrokerManager:
- def __init__(self, config):
- self.config = config
- self.brokerName = None
- self.qmf = None
- self.broker = None
-
- def SetBroker(self, brokerUrl):
- self.url = brokerUrl
- self.qmf = Session()
- self.broker = self.qmf.addBroker(brokerUrl, self.config._connTimeout)
- agents = self.qmf.getAgents()
- for a in agents:
- if a.getAgentBank() == 0:
- self.brokerAgent = a
-
- def Disconnect(self):
- if self.broker:
- self.qmf.delBroker(self.broker)
-
- def _getClusters(self):
- packages = self.qmf.getPackages()
- if "org.apache.qpid.cluster" not in packages:
- raise Exception("Clustering is not installed on the broker.")
-
- clusters = self.qmf.getObjects(_class="cluster", _agent=self.brokerAgent)
- if len(clusters) == 0:
- raise Exception("Clustering is installed but not enabled on the broker.")
-
- return clusters
-
- def _getHostList(self, urlList):
- hosts = []
- hostAddr = IpAddr(self.config._host)
- for url in urlList:
- if url.find("amqp:") != 0:
- raise Exception("Invalid URL 1")
- url = url[5:]
- addrs = str(url).split(",")
- addrList = []
- for addr in addrs:
- tokens = addr.split(":")
- if len(tokens) != 3:
- raise Exception("Invalid URL 2")
- addrList.append((tokens[1], tokens[2]))
-
- # Find the address in the list that is most likely to be in the same subnet as the address
- # with which we made the original QMF connection. This increases the probability that we will
- # be able to reach the cluster member.
-
- best = hostAddr.bestAddr(addrList)
- bestUrl = best[0] + ":" + best[1]
- hosts.append(bestUrl)
- return hosts
-
- def overview(self):
- clusters = self._getClusters()
- cluster = clusters[0]
- memberList = cluster.members.split(";")
- idList = cluster.memberIDs.split(";")
-
- print " Cluster Name: %s" % cluster.clusterName
- print "Cluster Status: %s" % cluster.status
- print " Cluster Size: %d" % cluster.clusterSize
- print " Members: ID=%s URL=%s" % (idList[0], memberList[0])
- for idx in range(1,len(idList)):
- print " : ID=%s URL=%s" % (idList[idx], memberList[idx])
-
- def stopMember(self, id):
- clusters = self._getClusters()
- cluster = clusters[0]
- idList = cluster.memberIDs.split(";")
- if id not in idList:
- raise Exception("No member with matching ID found")
-
- if not self.config._force:
- prompt = "Warning: "
- if len(idList) == 1:
- prompt += "This command will shut down the last running cluster member."
- else:
- prompt += "This command will shut down a cluster member."
- prompt += " Are you sure? [N]: "
-
- confirm = raw_input(prompt)
- if len(confirm) == 0 or confirm[0].upper() != 'Y':
- raise Exception("Operation canceled")
-
- cluster.stopClusterNode(id)
-
- def stopAll(self):
- clusters = self._getClusters()
- if not self.config._force:
- prompt = "Warning: This command will shut down the entire cluster."
- prompt += " Are you sure? [N]: "
-
- confirm = raw_input(prompt)
- if len(confirm) == 0 or confirm[0].upper() != 'Y':
- raise Exception("Operation canceled")
-
- cluster = clusters[0]
- cluster.stopFullCluster()
-
- def showConnections(self):
- clusters = self._getClusters()
- cluster = clusters[0]
- memberList = cluster.members.split(";")
- idList = cluster.memberIDs.split(";")
- displayList = []
- hostList = self._getHostList(memberList)
- self.qmf.delBroker(self.broker)
- self.broker = None
- self.brokers = []
-
- idx = 0
- for host in hostList:
- if self.config._showConn == "all" or self.config._showConn == idList[idx] or self.config._delConn:
- self.brokers.append(self.qmf.addBroker(host, self.config._connTimeout))
- displayList.append(idList[idx])
- idx += 1
-
- idx = 0
- found = False
- for broker in self.brokers:
- if not self.config._delConn:
- print "Clients on Member: ID=%s:" % displayList[idx]
- connList = self.qmf.getObjects(_class="connection", _package="org.apache.qpid.broker", _broker=broker)
- for conn in connList:
- if not conn.shadow:
- if self.config._numeric or self.config._delConn:
- a = conn.address
- else:
- tokens = conn.address.split(":")
- try:
- hostList = socket.gethostbyaddr(tokens[0])
- host = hostList[0]
- except:
- host = tokens[0]
- a = host + ":" + tokens[1]
- if self.config._delConn:
- tokens = self.config._delConn.split(":")
- ip = socket.gethostbyname(tokens[0])
- toDelete = ip + ":" + tokens[1]
- if a == toDelete:
- print "Closing connection from client: %s" % a
- conn.close()
- found = True
- else:
- print " %s" % a
- idx += 1
- if not self.config._delConn:
- print
- if self.config._delConn and not found:
- print "Client connection '%s' not found" % self.config._delConn
-
- for broker in self.brokers:
- self.qmf.delBroker(broker)
-
-
-def main(argv=None):
- if argv is None: argv = sys.argv
- try:
- config = Config()
- try:
- longOpts = ("stop=", "all-stop", "force", "connections=", "all-connections" "del-connection=", "numeric", "timeout=")
- (optlist, encArgs) = getopt.gnu_getopt(argv[1:], "s:kfCc:d:n", longOpts)
- except:
- usage()
- return 1
-
- try:
- encoding = locale.getpreferredencoding()
- cargs = [a.decode(encoding) for a in encArgs]
- except:
- cargs = encArgs
-
- count = 0
- for opt in optlist:
- if opt[0] == "--timeout":
- config._connTimeout = int(opt[1])
- if config._connTimeout == 0:
- config._connTimeout = None
- if opt[0] == "-s" or opt[0] == "--stop":
- config._stopId = opt[1]
- if len(config._stopId.split(":")) != 2:
- raise Exception("Member ID must be of form: <host or ip>:<number>")
- count += 1
- if opt[0] == "-k" or opt[0] == "--all-stop":
- config._stopAll = True
- count += 1
- if opt[0] == "-f" or opt[0] == "--force":
- config._force = True
- if opt[0] == "-n" or opt[0] == "--numeric":
- config._numeric = True
- if opt[0] == "-C" or opt[0] == "--all-connections":
- config._showConn = "all"
- count += 1
- if opt[0] == "-c" or opt[0] == "--connections":
- config._showConn = opt[1]
- if len(config._showConn.split(":")) != 2:
- raise Exception("Member ID must be of form: <host or ip>:<number>")
- count += 1
- if opt[0] == "-d" or opt[0] == "--del-connection":
- config._delConn = opt[1]
- if len(config._delConn.split(":")) != 2:
- raise Exception("Connection must be of form: <host or ip>:<port>")
- count += 1
-
- if count > 1:
- print "Only one command option may be supplied"
- print
- usage()
- return 1
-
- nargs = len(cargs)
- bm = BrokerManager(config)
-
- if nargs == 1:
- config._host = cargs[0]
-
- try:
- bm.SetBroker(config._host)
- if config._stopId:
- bm.stopMember(config._stopId)
- elif config._stopAll:
- bm.stopAll()
- elif config._showConn or config._delConn:
- bm.showConnections()
- else:
- bm.overview()
- except KeyboardInterrupt:
- print
- except Exception,e:
- if str(e).find("connection aborted") > 0:
- # we expect this when asking the connected broker to shut down
- return 0
- raise Exception("Failed: %s - %s" % (e.__class__.__name__, e))
-
- bm.Disconnect()
- except Exception, e:
- print str(e)
- return 1
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/python/commands/qpid-config b/python/commands/qpid-config
deleted file mode 100755
index 0db42bc6c7..0000000000
--- a/python/commands/qpid-config
+++ /dev/null
@@ -1,572 +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 getopt
-import sys
-import locale
-from qmf.console import Session
-
-_recursive = False
-_host = "localhost"
-_connTimeout = 10
-_altern_ex = None
-_passive = False
-_durable = False
-_clusterDurable = False
-_if_empty = True
-_if_unused = True
-_fileCount = 8
-_fileSize = 24
-_maxQueueSize = None
-_maxQueueCount = None
-_limitPolicy = None
-_order = None
-_msgSequence = False
-_ive = False
-_eventGeneration = None
-_file = None
-
-FILECOUNT = "qpid.file_count"
-FILESIZE = "qpid.file_size"
-MAX_QUEUE_SIZE = "qpid.max_size"
-MAX_QUEUE_COUNT = "qpid.max_count"
-POLICY_TYPE = "qpid.policy_type"
-CLUSTER_DURABLE = "qpid.persist_last_node"
-LVQ = "qpid.last_value_queue"
-LVQNB = "qpid.last_value_queue_no_browse"
-MSG_SEQUENCE = "qpid.msg_sequence"
-IVE = "qpid.ive"
-QUEUE_EVENT_GENERATION = "qpid.queue_event_generation"
-
-def Usage ():
- print "Usage: qpid-config [OPTIONS]"
- print " qpid-config [OPTIONS] exchanges [filter-string]"
- print " qpid-config [OPTIONS] queues [filter-string]"
- print " qpid-config [OPTIONS] add exchange <type> <name> [AddExchangeOptions]"
- print " qpid-config [OPTIONS] del exchange <name>"
- print " qpid-config [OPTIONS] add queue <name> [AddQueueOptions]"
- print " qpid-config [OPTIONS] del queue <name> [DelQueueOptions]"
- print " qpid-config [OPTIONS] bind <exchange-name> <queue-name> [binding-key]"
- print " <for type xml> [-f -|filename]"
- print " <for type header> [all|any] k1=v1 [, k2=v2...]"
- print " qpid-config [OPTIONS] unbind <exchange-name> <queue-name> [binding-key]"
- print
- print "Options:"
- print " --timeout seconds (10) Maximum time to wait for broker connection"
- print " -b [ --bindings ] Show bindings in queue or exchange list"
- print " -a [ --broker-addr ] Address (localhost) Address of qpidd broker"
- print " broker-addr is in the form: [username/password@] hostname | ip-address [:<port>]"
- print " ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost"
- print
- print "Add Queue Options:"
- print " --alternate-exchange [name of the alternate exchange]"
- print " The alternate-exchange field specifies how messages on this queue should"
- print " be treated when they are rejected by a subscriber, or when they are"
- print " orphaned by queue deletion. When present, rejected or orphaned messages"
- print " MUST be routed to the alternate-exchange. In all cases the messages MUST"
- print " be removed from the queue."
- print " --passive Do not actually change the broker state (queue will not be created)"
- print " --durable Queue is durable"
- print " --cluster-durable Queue becomes durable if there is only one functioning cluster node"
- print " --file-count N (8) Number of files in queue's persistence journal"
- print " --file-size N (24) File size in pages (64Kib/page)"
- print " --max-queue-size N Maximum in-memory queue size as bytes"
- print " --max-queue-count N Maximum in-memory queue size as a number of messages"
- print " --limit-policy [none | reject | flow-to-disk | ring | ring-strict]"
- print " Action taken when queue limit is reached:"
- print " none (default) - Use broker's default policy"
- print " reject - Reject enqueued messages"
- print " flow-to-disk - Page messages to disk"
- print " ring - Replace oldest unacquired message with new"
- print " ring-strict - Replace oldest message, reject if oldest is acquired"
- print " --order [fifo | lvq | lvq-no-browse]"
- print " Set queue ordering policy:"
- print " fifo (default) - First in, first out"
- print " lvq - Last Value Queue ordering, allows queue browsing"
- print " lvq-no-browse - Last Value Queue ordering, browsing clients may lose data"
- print " --generate-queue-events N"
- print " If set to 1, every enqueue will generate an event that can be processed by"
- print " registered listeners (e.g. for replication). If set to 2, events will be"
- print " generated for enqueues and dequeues"
- print
- print "Del Queue Options:"
- print " --force Force delete of queue even if it's currently used or it's not empty"
- print " --force-if-not-empty Force delete of queue even if it's not empty"
- print " --force-if-used Force delete of queue even if it's currently used"
- print
- print "Add Exchange <type> values:"
- print " direct Direct exchange for point-to-point communication"
- print " fanout Fanout exchange for broadcast communication"
- print " topic Topic exchange that routes messages using binding keys with wildcards"
- print " headers Headers exchange that matches header fields against the binding keys"
- print
- print "Add Exchange Options:"
- print " --alternate-exchange [name of the alternate exchange]"
- print " In the event that a message cannot be routed, this is the name of the exchange to"
- print " which the message will be sent. Messages transferred using message.transfer will"
- print " be routed to the alternate-exchange only if they are sent with the \"none\""
- print " accept-mode, and the discard-unroutable delivery property is set to false, and"
- print " there is no queue to route to for the given message according to the bindings"
- print " on this exchange."
- print " --passive Do not actually change the broker state (exchange will not be created)"
- print " --durable Exchange is durable"
- print " --sequence Exchange will insert a 'qpid.msg_sequence' field in the message header"
- print " with a value that increments for each message forwarded."
- print " --ive Exchange will behave as an 'initial-value-exchange', keeping a reference"
- print " to the last message forwarded and enqueuing that message to newly bound"
- print " queues."
- print
- sys.exit (1)
-
-
-#
-# helpers for the arg parsing in bind(). return multiple values; "ok"
-# followed by the resultant args
-
-#
-# accept -f followed by either
-# a filename or "-", for stdin. pull the bits into a string, to be
-# passed to the xml binding.
-#
-def snarf_xquery_args():
- if not _file:
- print "Invalid args to bind xml: need an input file or stdin"
- return [False]
- if _file == "-":
- res = sys.stdin.read()
- else:
- f = open(_file) # let this signal if it can't find it
- res = f.read()
- f.close()
- return [True, res]
-
-#
-# look for "any"/"all" and grok the rest of argv into a map
-#
-def snarf_header_args(cargs):
- if len(cargs) < 2:
- print "Invalid args to bind headers: need 'any'/'all' plus conditions"
- return [False]
- op = cargs[0]
- if op == "all" or op == "any":
- kv = {}
- for thing in cargs[1:]:
- k_and_v = thing.split("=")
- kv[k_and_v[0]] = k_and_v[1]
- return [True, op, kv]
- else:
- print "Invalid condition arg to bind headers, need 'any' or 'all', not '" + op + "'"
- return [False]
-
-class BrokerManager:
- def __init__ (self):
- self.brokerName = None
- self.qmf = None
- self.broker = None
-
- def SetBroker (self, brokerUrl):
- self.url = brokerUrl
- self.qmf = Session()
- self.broker = self.qmf.addBroker(brokerUrl, _connTimeout)
- agents = self.qmf.getAgents()
- for a in agents:
- if a.getAgentBank() == 0:
- self.brokerAgent = a
-
- def Disconnect(self):
- if self.broker:
- self.qmf.delBroker(self.broker)
-
- def Overview (self):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
- print "Total Exchanges: %d" % len (exchanges)
- etype = {}
- for ex in exchanges:
- if ex.type not in etype:
- etype[ex.type] = 1
- else:
- etype[ex.type] = etype[ex.type] + 1
- for typ in etype:
- print "%15s: %d" % (typ, etype[typ])
-
- print
- print " Total Queues: %d" % len (queues)
- _durable = 0
- for queue in queues:
- if queue.durable:
- _durable = _durable + 1
- print " durable: %d" % _durable
- print " non-durable: %d" % (len (queues) - _durable)
-
- def ExchangeList (self, filter):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- caption1 = "Type "
- caption2 = "Exchange Name"
- maxNameLen = len(caption2)
- for ex in exchanges:
- if self.match(ex.name, filter):
- if len(ex.name) > maxNameLen: maxNameLen = len(ex.name)
- print "%s%-*s Attributes" % (caption1, maxNameLen, caption2)
- line = ""
- for i in range(((maxNameLen + len(caption1)) / 5) + 5):
- line += "====="
- print line
-
- for ex in exchanges:
- if self.match (ex.name, filter):
- print "%-10s%-*s " % (ex.type, maxNameLen, ex.name),
- args = ex.arguments
- if ex.durable: print "--durable",
- if MSG_SEQUENCE in args and args[MSG_SEQUENCE] == 1: print "--sequence",
- if IVE in args and args[IVE] == 1: print "--ive",
- if ex.altExchange:
- print "--alternate-exchange=%s" % ex._altExchange_.name,
- print
-
- def ExchangeListRecurse (self, filter):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent)
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
- for ex in exchanges:
- if self.match (ex.name, filter):
- print "Exchange '%s' (%s)" % (ex.name, ex.type)
- for bind in bindings:
- if bind.exchangeRef == ex.getObjectId():
- qname = "<unknown>"
- queue = self.findById (queues, bind.queueRef)
- if queue != None:
- qname = queue.name
- print " bind [%s] => %s" % (bind.bindingKey, qname)
-
-
- def QueueList (self, filter):
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
-
- caption = "Queue Name"
- maxNameLen = len(caption)
- for q in queues:
- if self.match (q.name, filter):
- if len(q.name) > maxNameLen: maxNameLen = len(q.name)
- print "%-*s Attributes" % (maxNameLen, caption)
- line = ""
- for i in range((maxNameLen / 5) + 5):
- line += "====="
- print line
-
- for q in queues:
- if self.match (q.name, filter):
- print "%-*s " % (maxNameLen, q.name),
- args = q.arguments
- if q.durable: print "--durable",
- if CLUSTER_DURABLE in args and args[CLUSTER_DURABLE] == 1: print "--cluster-durable",
- if q.autoDelete: print "auto-del",
- if q.exclusive: print "excl",
- if FILESIZE in args: print "--file-size=%d" % args[FILESIZE],
- if FILECOUNT in args: print "--file-count=%d" % args[FILECOUNT],
- if MAX_QUEUE_SIZE in args: print "--max-queue-size=%d" % args[MAX_QUEUE_SIZE],
- if MAX_QUEUE_COUNT in args: print "--max-queue-count=%d" % args[MAX_QUEUE_COUNT],
- if POLICY_TYPE in args: print "--limit-policy=%s" % args[POLICY_TYPE].replace("_", "-"),
- if LVQ in args and args[LVQ] == 1: print "--order lvq",
- if LVQNB in args and args[LVQNB] == 1: print "--order lvq-no-browse",
- if QUEUE_EVENT_GENERATION in args: print "--generate-queue-events=%d" % args[QUEUE_EVENT_GENERATION],
- if q.altExchange:
- print "--alternate-exchange=%s" % q._altExchange_.name,
- print
-
- def QueueListRecurse (self, filter):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent)
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
- for queue in queues:
- if self.match (queue.name, filter):
- print "Queue '%s'" % queue.name
- for bind in bindings:
- if bind.queueRef == queue.getObjectId():
- ename = "<unknown>"
- ex = self.findById (exchanges, bind.exchangeRef)
- if ex != None:
- ename = ex.name
- if ename == "":
- ename = "''"
- print " bind [%s] => %s" % (bind.bindingKey, ename)
-
- def AddExchange (self, args):
- if len (args) < 2:
- Usage ()
- etype = args[0]
- ename = args[1]
- declArgs = {}
- if _msgSequence:
- declArgs[MSG_SEQUENCE] = 1
- if _ive:
- declArgs[IVE] = 1
- if _altern_ex != None:
- self.broker.getAmqpSession().exchange_declare (exchange=ename, type=etype, alternate_exchange=_altern_ex, passive=_passive, durable=_durable, arguments=declArgs)
- else:
- self.broker.getAmqpSession().exchange_declare (exchange=ename, type=etype, passive=_passive, durable=_durable, arguments=declArgs)
-
- def DelExchange (self, args):
- if len (args) < 1:
- Usage ()
- ename = args[0]
- self.broker.getAmqpSession().exchange_delete (exchange=ename)
-
- def AddQueue (self, args):
- if len (args) < 1:
- Usage ()
- qname = args[0]
- declArgs = {}
- if _durable:
- declArgs[FILECOUNT] = _fileCount
- declArgs[FILESIZE] = _fileSize
-
- if _maxQueueSize:
- declArgs[MAX_QUEUE_SIZE] = _maxQueueSize
- if _maxQueueCount:
- declArgs[MAX_QUEUE_COUNT] = _maxQueueCount
- if _limitPolicy:
- if _limitPolicy == "none":
- pass
- elif _limitPolicy == "reject":
- declArgs[POLICY_TYPE] = "reject"
- elif _limitPolicy == "flow-to-disk":
- declArgs[POLICY_TYPE] = "flow_to_disk"
- elif _limitPolicy == "ring":
- declArgs[POLICY_TYPE] = "ring"
- elif _limitPolicy == "ring-strict":
- declArgs[POLICY_TYPE] = "ring_strict"
-
- if _clusterDurable:
- declArgs[CLUSTER_DURABLE] = 1
- if _order:
- if _order == "fifo":
- pass
- elif _order == "lvq":
- declArgs[LVQ] = 1
- elif _order == "lvq-no-browse":
- declArgs[LVQNB] = 1
- if _eventGeneration:
- declArgs[QUEUE_EVENT_GENERATION] = _eventGeneration
-
- if _altern_ex != None:
- self.broker.getAmqpSession().queue_declare (queue=qname, alternate_exchange=_altern_ex, passive=_passive, durable=_durable, arguments=declArgs)
- else:
- self.broker.getAmqpSession().queue_declare (queue=qname, passive=_passive, durable=_durable, arguments=declArgs)
-
- def DelQueue (self, args):
- if len (args) < 1:
- Usage ()
- qname = args[0]
- self.broker.getAmqpSession().queue_delete (queue=qname, if_empty=_if_empty, if_unused=_if_unused)
-
- def Bind (self, args):
- if len (args) < 2:
- Usage ()
- ename = args[0]
- qname = args[1]
- key = ""
- if len (args) > 2:
- key = args[2]
-
- # query the exchange to determine its type.
- res = self.broker.getAmqpSession().exchange_query(ename)
-
- # type of the xchg determines the processing of the rest of
- # argv. if it's an xml xchg, we want to find a file
- # containing an x-query, and pass that. if it's a headers
- # exchange, we need to pass either "any" or all, followed by a
- # map containing key/value pairs. if neither of those, extra
- # args are ignored.
- ok = True
- args = None
- if res.type == "xml":
- # this checks/imports the -f arg
- [ok, xquery] = snarf_xquery_args()
- args = { "xquery" : xquery }
- # print args
- else:
- if res.type == "headers":
- [ok, op, kv] = snarf_header_args(cargs[4:])
- args = kv
- args["x-match"] = op
-
- if not ok:
- sys.exit(1)
-
- self.broker.getAmqpSession().exchange_bind (queue=qname,
- exchange=ename,
- binding_key=key,
- arguments=args)
-
- def Unbind (self, args):
- if len (args) < 2:
- Usage ()
- ename = args[0]
- qname = args[1]
- key = ""
- if len (args) > 2:
- key = args[2]
- self.broker.getAmqpSession().exchange_unbind (queue=qname, exchange=ename, binding_key=key)
-
- def findById (self, items, id):
- for item in items:
- if item.getObjectId() == id:
- return item
- return None
-
- def match (self, name, filter):
- if filter == "":
- return True
- if name.find (filter) == -1:
- return False
- return True
-
-def YN (bool):
- if bool:
- return 'Y'
- return 'N'
-
-
-##
-## Main Program
-##
-
-try:
- longOpts = ("durable", "cluster-durable", "bindings", "broker-addr=", "file-count=",
- "file-size=", "max-queue-size=", "max-queue-count=", "limit-policy=",
- "order=", "sequence", "ive", "generate-queue-events=", "force", "force-if-not-empty",
- "force_if_used", "alternate-exchange=", "passive", "timeout=", "file=")
- (optlist, encArgs) = getopt.gnu_getopt (sys.argv[1:], "a:bf:", longOpts)
-except:
- Usage ()
-
-try:
- encoding = locale.getpreferredencoding()
- cargs = [a.decode(encoding) for a in encArgs]
-except:
- cargs = encArgs
-
-for opt in optlist:
- if opt[0] == "-b" or opt[0] == "--bindings":
- _recursive = True
- if opt[0] == "-a" or opt[0] == "--broker-addr":
- _host = opt[1]
- if opt[0] == "-f" or opt[0] == "--file":
- _file = opt[1]
- if opt[0] == "--timeout":
- _connTimeout = int(opt[1])
- if _connTimeout == 0:
- _connTimeout = None
- if opt[0] == "--alternate-exchange":
- _altern_ex = opt[1]
- if opt[0] == "--passive":
- _passive = True
- if opt[0] == "--durable":
- _durable = True
- if opt[0] == "--cluster-durable":
- _clusterDurable = True
- if opt[0] == "--file-count":
- _fileCount = int (opt[1])
- if opt[0] == "--file-size":
- _fileSize = int (opt[1])
- if opt[0] == "--max-queue-size":
- _maxQueueSize = int (opt[1])
- if opt[0] == "--max-queue-count":
- _maxQueueCount = int (opt[1])
- if opt[0] == "--limit-policy":
- _limitPolicy = opt[1]
- if _limitPolicy not in ("none", "reject", "flow-to-disk", "ring", "ring-strict"):
- print "Error: Invalid --limit-policy argument"
- sys.exit(1)
- if opt[0] == "--order":
- _order = opt[1]
- if _order not in ("fifo", "lvq", "lvq-no-browse"):
- print "Error: Invalid --order argument"
- sys.exit(1)
- if opt[0] == "--sequence":
- _msgSequence = True
- if opt[0] == "--ive":
- _ive = True
- if opt[0] == "--generate-queue-events":
- _eventGeneration = int (opt[1])
- if opt[0] == "--force":
- _if_empty = False
- _if_unused = False
- if opt[0] == "--force-if-not-empty":
- _if_empty = False
- if opt[0] == "--force-if-used":
- _if_unused = False
-
-
-nargs = len (cargs)
-bm = BrokerManager ()
-
-try:
- bm.SetBroker(_host)
- if nargs == 0:
- bm.Overview ()
- else:
- cmd = cargs[0]
- modifier = ""
- if nargs > 1:
- modifier = cargs[1]
- if cmd == "exchanges":
- if _recursive:
- bm.ExchangeListRecurse (modifier)
- else:
- bm.ExchangeList (modifier)
- elif cmd == "queues":
- if _recursive:
- bm.QueueListRecurse (modifier)
- else:
- bm.QueueList (modifier)
- elif cmd == "add":
- if modifier == "exchange":
- bm.AddExchange (cargs[2:])
- elif modifier == "queue":
- bm.AddQueue (cargs[2:])
- else:
- Usage ()
- elif cmd == "del":
- if modifier == "exchange":
- bm.DelExchange (cargs[2:])
- elif modifier == "queue":
- bm.DelQueue (cargs[2:])
- else:
- Usage ()
- elif cmd == "bind":
- bm.Bind (cargs[1:])
- elif cmd == "unbind":
- bm.Unbind (cargs[1:])
- else:
- Usage ()
-except KeyboardInterrupt:
- print
-except IOError, e:
- print e
- sys.exit(1)
-except Exception,e:
- print "Failed: %s: %s" % (e.__class__.__name__, e)
- sys.exit(1)
-
-bm.Disconnect()
diff --git a/python/commands/qpid-printevents b/python/commands/qpid-printevents
deleted file mode 100755
index 0c1b618a1f..0000000000
--- a/python/commands/qpid-printevents
+++ /dev/null
@@ -1,74 +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 time import time, strftime, gmtime, sleep
-from qmf.console import Console, Session
-
-class EventConsole(Console):
- def event(self, broker, event):
- print event
-
- def brokerConnected(self, broker):
- print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerConnected broker=%s" % broker.getUrl()
-
- def brokerDisconnected(self, broker):
- print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerDisconnected broker=%s" % broker.getUrl()
-
-
-##
-## Main Program
-##
-def main():
- _usage = "%prog [options] [broker-addr]..."
- _description = \
-"""Collect and print events from one or more Qpid message brokers. If no broker-addr is
-supplied, %prog will connect to 'localhost:5672'.
-broker-addr is of the form: [username/password@] hostname | ip-address [:<port>]
-ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost
-"""
- p = optparse.OptionParser(usage=_usage, description=_description)
-
- options, arguments = p.parse_args()
- if len(arguments) == 0:
- arguments.append("localhost")
-
- console = EventConsole()
- session = Session(console, rcvObjects=False, rcvHeartbeats=False, manageConnections=True)
- brokers = []
- for host in arguments:
- brokers.append(session.addBroker(host))
-
- try:
- while (True):
- sleep(10)
- except KeyboardInterrupt:
- for broker in brokers:
- session.delBroker(broker)
- print
- sys.exit(0)
-
-if __name__ == '__main__':
- main()
-
diff --git a/python/commands/qpid-queue-stats b/python/commands/qpid-queue-stats
deleted file mode 100755
index 3b8a0dcb19..0000000000
--- a/python/commands/qpid-queue-stats
+++ /dev/null
@@ -1,146 +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 re
-import socket
-import qpid
-from threading import Condition
-from qmf.console import Session, Console
-from qpid.peer import Closed
-from qpid.connection import Connection, ConnectionFailed
-from time import sleep
-
-class BrokerManager(Console):
- def __init__(self, host):
- self.url = host
- self.objects = {}
- self.filter = None
- self.session = Session(self, rcvEvents=False, rcvHeartbeats=False,
- userBindings=True, manageConnections=True)
- self.broker = self.session.addBroker(self.url)
- self.firstError = True
-
- def setFilter(self,filter):
- self.filter = filter
-
- def brokerConnected(self, broker):
- if not self.firstError:
- print "*** Broker connected"
- self.firstError = False
-
- def brokerDisconnected(self, broker):
- print "*** Broker connection lost - %s, retrying..." % broker.getError()
- self.firstError = False
- self.objects.clear()
-
- def objectProps(self, broker, record):
- className = record.getClassKey().getClassName()
- if className != "queue":
- return
-
- id = record.getObjectId().__repr__()
- if id not in self.objects:
- self.objects[id] = (record.name, None, None)
-
- def objectStats(self, broker, record):
- className = record.getClassKey().getClassName()
- if className != "queue":
- return
-
- id = record.getObjectId().__repr__()
- if id not in self.objects:
- return
-
- (name, first, last) = self.objects[id]
- if first == None:
- self.objects[id] = (name, record, None)
- return
-
- if len(self.filter) > 0 :
- match = False
-
- for x in self.filter:
- if x.match(name):
- match = True
- break
- if match == False:
- return
-
- if last == None:
- lastSample = first
- else:
- lastSample = last
-
- self.objects[id] = (name, first, record)
-
- deltaTime = float (record.getTimestamps()[0] - lastSample.getTimestamps()[0])
- if deltaTime < 1000000000.0:
- return
- enqueueRate = float (record.msgTotalEnqueues - lastSample.msgTotalEnqueues) / \
- (deltaTime / 1000000000.0)
- dequeueRate = float (record.msgTotalDequeues - lastSample.msgTotalDequeues) / \
- (deltaTime / 1000000000.0)
- print "%-41s%10.2f%11d%13.2f%13.2f" % \
- (name, deltaTime / 1000000000, record.msgDepth, enqueueRate, dequeueRate)
- sys.stdout.flush()
-
-
- def Display (self):
- self.session.bindClass("org.apache.qpid.broker", "queue")
- print "Queue Name Sec Depth Enq Rate Deq Rate"
- print "========================================================================================"
- sys.stdout.flush()
- try:
- while True:
- sleep (1)
- if self.firstError and self.broker.getError():
- self.firstError = False
- print "*** Error: %s, retrying..." % self.broker.getError()
- except KeyboardInterrupt:
- print
- self.session.delBroker(self.broker)
-
-##
-## Main Program
-##
-def main():
- p = optparse.OptionParser()
- p.add_option('--broker-address','-a', default='localhost' , help='broker-addr is in the form: [username/password@] hostname | ip-address [:<port>] \n ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost')
- p.add_option('--filter','-f' ,default=None ,help='a list of comma separated queue names (regex are accepted) to show')
-
- options, arguments = p.parse_args()
-
- host = options.broker_address
- filter = []
- if options.filter != None:
- for s in options.filter.split(","):
- filter.append(re.compile(s))
-
- bm = BrokerManager(host)
- bm.setFilter(filter)
- bm.Display()
-
-if __name__ == '__main__':
- main()
-
diff --git a/python/commands/qpid-route b/python/commands/qpid-route
deleted file mode 100755
index 9965047000..0000000000
--- a/python/commands/qpid-route
+++ /dev/null
@@ -1,524 +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 getopt
-import sys
-import socket
-import os
-import locale
-from qmf.console import Session, BrokerURL
-
-def Usage():
- print "Usage: qpid-route [OPTIONS] dynamic add <dest-broker> <src-broker> <exchange> [tag] [exclude-list]"
- print " qpid-route [OPTIONS] dynamic del <dest-broker> <src-broker> <exchange>"
- print
- print " qpid-route [OPTIONS] route add <dest-broker> <src-broker> <exchange> <routing-key> [tag] [exclude-list]"
- print " qpid-route [OPTIONS] route del <dest-broker> <src-broker> <exchange> <routing-key>"
- print " qpid-route [OPTIONS] queue add <dest-broker> <src-broker> <exchange> <queue>"
- print " qpid-route [OPTIONS] queue del <dest-broker> <src-broker> <exchange> <queue>"
- print " qpid-route [OPTIONS] route list [<dest-broker>]"
- print " qpid-route [OPTIONS] route flush [<dest-broker>]"
- print " qpid-route [OPTIONS] route map [<broker>]"
- print
- print " qpid-route [OPTIONS] link add <dest-broker> <src-broker>"
- print " qpid-route [OPTIONS] link del <dest-broker> <src-broker>"
- print " qpid-route [OPTIONS] link list [<dest-broker>]"
- print
- print "Options:"
- print " --timeout seconds (10) Maximum time to wait for broker connection"
- print " -v [ --verbose ] Verbose output"
- print " -q [ --quiet ] Quiet output, don't print duplicate warnings"
- print " -d [ --durable ] Added configuration shall be durable"
- print " -e [ --del-empty-link ] Delete link after deleting last route on the link"
- print " -s [ --src-local ] Make connection to source broker (push route)"
- print " --ack N Acknowledge transfers over the bridge in batches of N"
- print " -t <transport> [ --transport <transport>]"
- print " Specify transport to use for links, defaults to tcp"
- print
- print " dest-broker and src-broker are in the form: [username/password@] hostname | ip-address [:<port>]"
- print " ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost"
- print
- sys.exit(1)
-
-_verbose = False
-_quiet = False
-_durable = False
-_dellink = False
-_srclocal = False
-_transport = "tcp"
-_ack = 0
-_connTimeout = 10
-
-class RouteManager:
- def __init__(self, localBroker):
- self.local = BrokerURL(localBroker)
- self.remote = None
- self.qmf = Session()
- self.broker = self.qmf.addBroker(localBroker, _connTimeout)
-
- def disconnect(self):
- self.qmf.delBroker(self.broker)
-
- def getLink(self):
- links = self.qmf.getObjects(_class="link")
- for link in links:
- if self.remote.match(link.host, link.port):
- return link
- return None
-
- def addLink(self, remoteBroker):
- self.remote = BrokerURL(remoteBroker)
- if self.local.match(self.remote.host, self.remote.port):
- raise Exception("Linking broker to itself is not permitted")
-
- brokers = self.qmf.getObjects(_class="broker")
- broker = brokers[0]
- link = self.getLink()
- if link == None:
- if not self.remote.authName or self.remote.authName == "anonymous":
- mech = "ANONYMOUS"
- else:
- mech = "PLAIN"
- res = broker.connect(self.remote.host, self.remote.port, _durable,
- mech, self.remote.authName or "", self.remote.authPass or "",
- _transport)
- if _verbose:
- print "Connect method returned:", res.status, res.text
-
- def delLink(self, remoteBroker):
- self.remote = BrokerURL(remoteBroker)
- brokers = self.qmf.getObjects(_class="broker")
- broker = brokers[0]
- link = self.getLink()
- if link == None:
- raise Exception("Link not found")
-
- res = link.close()
- if _verbose:
- print "Close method returned:", res.status, res.text
-
- def listLinks(self):
- links = self.qmf.getObjects(_class="link")
- if len(links) == 0:
- print "No Links Found"
- else:
- print
- print "Host Port Transport Durable State Last Error"
- print "============================================================================="
- for link in links:
- print "%-16s%-8d%-13s%c %-18s%s" % \
- (link.host, link.port, link.transport, YN(link.durable), link.state, link.lastError)
-
- def mapRoutes(self):
- qmf = self.qmf
- print
- print "Finding Linked Brokers:"
-
- brokerList = {}
- brokerList[self.local.name()] = self.broker
- print " %s... Ok" % self.local
-
- added = True
- while added:
- added = False
- links = qmf.getObjects(_class="link")
- for link in links:
- url = BrokerURL("%s:%d" % (link.host, link.port))
- if url.name() not in brokerList:
- print " %s..." % url.name(),
- try:
- b = qmf.addBroker("%s:%d" % (link.host, link.port), _connTimeout)
- brokerList[url.name()] = b
- added = True
- print "Ok"
- except Exception, e:
- print e
-
- print
- print "Dynamic Routes:"
- bridges = qmf.getObjects(_class="bridge", dynamic=True)
- fedExchanges = []
- for bridge in bridges:
- if bridge.src not in fedExchanges:
- fedExchanges.append(bridge.src)
- if len(fedExchanges) == 0:
- print " none found"
- print
-
- for ex in fedExchanges:
- print " Exchange %s:" % ex
- pairs = []
- for bridge in bridges:
- if bridge.src == ex:
- link = bridge._linkRef_
- fromUrl = "%s:%s" % (link.host, link.port)
- toUrl = bridge.getBroker().getUrl()
- found = False
- for pair in pairs:
- if pair.matches(fromUrl, toUrl):
- found = True
- if not found:
- pairs.append(RoutePair(fromUrl, toUrl))
- for pair in pairs:
- print " %s" % pair
- print
-
- print "Static Routes:"
- bridges = qmf.getObjects(_class="bridge", dynamic=False)
- if len(bridges) == 0:
- print " none found"
- print
-
- for bridge in bridges:
- link = bridge._linkRef_
- fromUrl = "%s:%s" % (link.host, link.port)
- toUrl = bridge.getBroker().getUrl()
- leftType = "ex"
- rightType = "ex"
- if bridge.srcIsLocal:
- arrow = "=>"
- left = bridge.src
- right = bridge.dest
- if bridge.srcIsQueue:
- leftType = "queue"
- else:
- arrow = "<="
- left = bridge.dest
- right = bridge.src
- if bridge.srcIsQueue:
- rightType = "queue"
-
- if bridge.srcIsQueue:
- print " %s(%s=%s) %s %s(%s=%s)" % \
- (toUrl, leftType, left, arrow, fromUrl, rightType, right)
- else:
- print " %s(%s=%s) %s %s(%s=%s) key=%s" % \
- (toUrl, leftType, left, arrow, fromUrl, rightType, right, bridge.key)
- print
-
- for broker in brokerList:
- if broker != self.local.name():
- qmf.delBroker(brokerList[broker])
-
-
- def addRoute(self, remoteBroker, exchange, routingKey, tag, excludes, dynamic=False):
- if dynamic and _srclocal:
- raise Exception("--src-local is not permitted on dynamic routes")
-
- self.addLink(remoteBroker)
- link = self.getLink()
- if link == None:
- raise Exception("Link failed to create")
-
- bridges = self.qmf.getObjects(_class="bridge")
- for bridge in bridges:
- if bridge.linkRef == link.getObjectId() and \
- bridge.dest == exchange and bridge.key == routingKey and not bridge.srcIsQueue:
- if not _quiet:
- raise Exception("Duplicate Route - ignoring: %s(%s)" % (exchange, routingKey))
- sys.exit(0)
-
- if _verbose:
- print "Creating inter-broker binding..."
- res = link.bridge(_durable, exchange, exchange, routingKey, tag, excludes, False, _srclocal, dynamic, _ack)
- if res.status != 0:
- raise Exception(res.text)
- if _verbose:
- print "Bridge method returned:", res.status, res.text
-
- def addQueueRoute(self, remoteBroker, exchange, queue):
- self.addLink(remoteBroker)
- link = self.getLink()
- if link == None:
- raise Exception("Link failed to create")
-
- bridges = self.qmf.getObjects(_class="bridge")
- for bridge in bridges:
- if bridge.linkRef == link.getObjectId() and \
- bridge.dest == exchange and bridge.src == queue and bridge.srcIsQueue:
- if not _quiet:
- raise Exception("Duplicate Route - ignoring: %s(%s)" % (exchange, queue))
- sys.exit(0)
-
- if _verbose:
- print "Creating inter-broker binding..."
- res = link.bridge(_durable, queue, exchange, "", "", "", True, _srclocal, False, _ack)
- if res.status != 0:
- raise Exception(res.text)
- if _verbose:
- print "Bridge method returned:", res.status, res.text
-
- def delQueueRoute(self, remoteBroker, exchange, queue):
- self.remote = BrokerURL(remoteBroker)
- link = self.getLink()
- if link == None:
- if not _quiet:
- raise Exception("No link found from %s to %s" % (self.remote.name(), self.local.name()))
- sys.exit(0)
-
- bridges = self.qmf.getObjects(_class="bridge")
- for bridge in bridges:
- if bridge.linkRef == link.getObjectId() and \
- bridge.dest == exchange and bridge.src == queue and bridge.srcIsQueue:
- if _verbose:
- print "Closing bridge..."
- res = bridge.close()
- if res.status != 0:
- raise Exception("Error closing bridge: %d - %s" % (res.status, res.text))
- if len(bridges) == 1 and _dellink:
- link = self.getLink()
- if link == None:
- sys.exit(0)
- if _verbose:
- print "Last bridge on link, closing link..."
- res = link.close()
- if res.status != 0:
- raise Exception("Error closing link: %d - %s" % (res.status, res.text))
- sys.exit(0)
- if not _quiet:
- raise Exception("Route not found")
-
- def delRoute(self, remoteBroker, exchange, routingKey, dynamic=False):
- self.remote = BrokerURL(remoteBroker)
- link = self.getLink()
- if link == None:
- if not _quiet:
- raise Exception("No link found from %s to %s" % (self.remote.name(), self.local.name()))
- sys.exit(0)
-
- bridges = self.qmf.getObjects(_class="bridge")
- for bridge in bridges:
- if bridge.linkRef == link.getObjectId() and bridge.dest == exchange and bridge.key == routingKey \
- and bridge.dynamic == dynamic:
- if _verbose:
- print "Closing bridge..."
- res = bridge.close()
- if res.status != 0:
- raise Exception("Error closing bridge: %d - %s" % (res.status, res.text))
- if len(bridges) == 1 and _dellink:
- link = self.getLink()
- if link == None:
- sys.exit(0)
- if _verbose:
- print "Last bridge on link, closing link..."
- res = link.close()
- if res.status != 0:
- raise Exception("Error closing link: %d - %s" % (res.status, res.text))
- sys.exit(0)
- if not _quiet:
- raise Exception("Route not found")
-
- def listRoutes(self):
- links = self.qmf.getObjects(_class="link")
- bridges = self.qmf.getObjects(_class="bridge")
-
- for bridge in bridges:
- myLink = None
- for link in links:
- if bridge.linkRef == link.getObjectId():
- myLink = link
- break
- if myLink != None:
- if bridge.dynamic:
- keyText = "<dynamic>"
- else:
- keyText = bridge.key
- print "%s %s:%d %s %s" % (self.local.name(), myLink.host, myLink.port, bridge.dest, keyText)
-
- def clearAllRoutes(self):
- links = self.qmf.getObjects(_class="link")
- bridges = self.qmf.getObjects(_class="bridge")
-
- for bridge in bridges:
- if _verbose:
- myLink = None
- for link in links:
- if bridge.linkRef == link.getObjectId():
- myLink = link
- break
- if myLink != None:
- print "Deleting Bridge: %s:%d %s %s... " % (myLink.host, myLink.port, bridge.dest, bridge.key),
- res = bridge.close()
- if res.status != 0:
- print "Error: %d - %s" % (res.status, res.text)
- elif _verbose:
- print "Ok"
-
- if _dellink:
- links = self.qmf.getObjects(_class="link")
- for link in links:
- if _verbose:
- print "Deleting Link: %s:%d... " % (link.host, link.port),
- res = link.close()
- if res.status != 0:
- print "Error: %d - %s" % (res.status, res.text)
- elif _verbose:
- print "Ok"
-
-class RoutePair:
- def __init__(self, fromUrl, toUrl):
- self.fromUrl = fromUrl
- self.toUrl = toUrl
- self.bidir = False
-
- def __repr__(self):
- if self.bidir:
- delimit = "<=>"
- else:
- delimit = " =>"
- return "%s %s %s" % (self.fromUrl, delimit, self.toUrl)
-
- def matches(self, fromUrl, toUrl):
- if fromUrl == self.fromUrl and toUrl == self.toUrl:
- return True
- if toUrl == self.fromUrl and fromUrl == self.toUrl:
- self.bidir = True
- return True
- return False
-
-
-def YN(val):
- if val == 1:
- return 'Y'
- return 'N'
-
-##
-## Main Program
-##
-
-try:
- longOpts = ("verbose", "quiet", "durable", "del-empty-link", "src-local", "transport=", "ack=", "timeout=")
- (optlist, encArgs) = getopt.gnu_getopt(sys.argv[1:], "vqdest:", longOpts)
-except:
- Usage()
-
-try:
- encoding = locale.getpreferredencoding()
- cargs = [a.decode(encoding) for a in encArgs]
-except:
- cargs = encArgs
-
-for opt in optlist:
- if opt[0] == "--timeout":
- _connTimeout = int(opt[1])
- if _connTimeout == 0:
- _connTimeout = None
- if opt[0] == "-v" or opt[0] == "--verbose":
- _verbose = True
- if opt[0] == "-q" or opt[0] == "--quiet":
- _quiet = True
- if opt[0] == "-d" or opt[0] == "--durable":
- _durable = True
- if opt[0] == "-e" or opt[0] == "--del-empty-link":
- _dellink = True
- if opt[0] == "-s" or opt[0] == "--src-local":
- _srclocal = True
- if opt[0] == "-t" or opt[0] == "--transport":
- _transport = opt[1]
- if opt[0] == "--ack":
- _ack = int(opt[1])
-
-nargs = len(cargs)
-if nargs < 2:
- Usage()
-if nargs == 2:
- localBroker = "localhost"
-else:
- if _srclocal:
- localBroker = cargs[3]
- remoteBroker = cargs[2]
- else:
- localBroker = cargs[2]
- if nargs > 3:
- remoteBroker = cargs[3]
-
-group = cargs[0]
-cmd = cargs[1]
-
-try:
- rm = RouteManager(localBroker)
- if group == "link":
- if cmd == "add":
- if nargs != 4:
- Usage()
- rm.addLink(remoteBroker)
- elif cmd == "del":
- if nargs != 4:
- Usage()
- rm.delLink(remoteBroker)
- elif cmd == "list":
- rm.listLinks()
-
- elif group == "dynamic":
- if cmd == "add":
- if nargs < 5 or nargs > 7:
- Usage()
-
- tag = ""
- excludes = ""
- if nargs > 5: tag = cargs[5]
- if nargs > 6: excludes = cargs[6]
- rm.addRoute(remoteBroker, cargs[4], "", tag, excludes, dynamic=True)
- elif cmd == "del":
- if nargs != 5:
- Usage()
- else:
- rm.delRoute(remoteBroker, cargs[4], "", dynamic=True)
-
- elif group == "route":
- if cmd == "add":
- if nargs < 6 or nargs > 8:
- Usage()
-
- tag = ""
- excludes = ""
- if nargs > 6: tag = cargs[6]
- if nargs > 7: excludes = cargs[7]
- rm.addRoute(remoteBroker, cargs[4], cargs[5], tag, excludes, dynamic=False)
- elif cmd == "del":
- if nargs != 6:
- Usage()
- rm.delRoute(remoteBroker, cargs[4], cargs[5], dynamic=False)
- elif cmd == "map":
- rm.mapRoutes()
- else:
- if cmd == "list":
- rm.listRoutes()
- elif cmd == "flush":
- rm.clearAllRoutes()
- else:
- Usage()
-
- elif group == "queue":
- if nargs != 6:
- Usage()
- if cmd == "add":
- rm.addQueueRoute(remoteBroker, exchange=cargs[4], queue=cargs[5])
- elif cmd == "del":
- rm.delQueueRoute(remoteBroker, exchange=cargs[4], queue=cargs[5])
- else:
- Usage()
-
-except Exception,e:
- print "Failed: %s - %s" % (e.__class__.__name__, e)
- sys.exit(1)
-
-rm.disconnect()
diff --git a/python/commands/qpid-stat b/python/commands/qpid-stat
deleted file mode 100755
index c6fc5ef0da..0000000000
--- a/python/commands/qpid-stat
+++ /dev/null
@@ -1,459 +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 getopt
-import sys
-import locale
-import socket
-import re
-from qmf.console import Session, Console
-from qpid.disp import Display, Header, Sorter
-
-_host = "localhost"
-_connTimeout = 10
-_types = ""
-_limit = 50
-_increasing = False
-_sortcol = None
-
-def Usage ():
- print "Usage: qpid-stat [OPTIONS] [broker-addr]"
- print
- print " broker-addr is in the form: [username/password@] hostname | ip-address [:<port>]"
- print " ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost"
- print
- print "General Options:"
- print " --timeout seconds (10) Maximum time to wait for broker connection"
-# print " -n [--numeric] Don't resolve names"
- print
- print "Display Options:"
- print
- print " -b Show Brokers"
- print " -c Show Connections"
-# print " -s Show Sessions"
- print " -e Show Exchanges"
- print " -q Show Queues"
- print
- print " -S [--sort-by] COLNAME Sort by column name"
- print " -I [--increasing] Sort by increasing value (default = decreasing)"
- print " -L [--limit] NUM Limit output to NUM rows (default = 50)"
- print
- sys.exit (1)
-
-class IpAddr:
- def __init__(self, text):
- if text.find("@") != -1:
- tokens = text.split("@")
- text = tokens[1]
- if text.find(":") != -1:
- tokens = text.split(":")
- text = tokens[0]
- self.port = int(tokens[1])
- else:
- self.port = 5672
- self.dottedQuad = socket.gethostbyname(text)
- nums = self.dottedQuad.split(".")
- self.addr = (int(nums[0]) << 24) + (int(nums[1]) << 16) + (int(nums[2]) << 8) + int(nums[3])
-
- def bestAddr(self, addrPortList):
- bestDiff = 0xFFFFFFFFL
- bestAddr = None
- for addrPort in addrPortList:
- diff = IpAddr(addrPort[0]).addr ^ self.addr
- if diff < bestDiff:
- bestDiff = diff
- bestAddr = addrPort
- return bestAddr
-
-class Broker(object):
- def __init__(self, qmf, broker):
- self.broker = broker
-
- agents = qmf.getAgents()
- for a in agents:
- if a.getAgentBank() == 0:
- self.brokerAgent = a
-
- bobj = qmf.getObjects(_class="broker", _package="org.apache.qpid.broker", _agent=self.brokerAgent)[0]
- self.currentTime = bobj.getTimestamps()[0]
- try:
- self.uptime = bobj.uptime
- except:
- self.uptime = 0
- self.connections = {}
- self.sessions = {}
- self.exchanges = {}
- self.queues = {}
- package = "org.apache.qpid.broker"
-
- list = qmf.getObjects(_class="connection", _package=package, _agent=self.brokerAgent)
- for conn in list:
- if not conn.shadow:
- self.connections[conn.getObjectId()] = conn
-
- list = qmf.getObjects(_class="session", _package=package, _agent=self.brokerAgent)
- for sess in list:
- if sess.connectionRef in self.connections:
- self.sessions[sess.getObjectId()] = sess
-
- list = qmf.getObjects(_class="exchange", _package=package, _agent=self.brokerAgent)
- for exchange in list:
- self.exchanges[exchange.getObjectId()] = exchange
-
- list = qmf.getObjects(_class="queue", _package=package, _agent=self.brokerAgent)
- for queue in list:
- self.queues[queue.getObjectId()] = queue
-
- def getName(self):
- return self.broker.getUrl()
-
- def getCurrentTime(self):
- return self.currentTime
-
- def getUptime(self):
- return self.uptime
-
-class BrokerManager(Console):
- def __init__(self):
- self.brokerName = None
- self.qmf = None
- self.broker = None
- self.brokers = []
- self.cluster = None
-
- def SetBroker(self, brokerUrl):
- self.url = brokerUrl
- self.qmf = Session()
- self.broker = self.qmf.addBroker(brokerUrl, _connTimeout)
- agents = self.qmf.getAgents()
- for a in agents:
- if a.getAgentBank() == 0:
- self.brokerAgent = a
-
- def Disconnect(self):
- if self.broker:
- self.qmf.delBroker(self.broker)
-
- def _getCluster(self):
- packages = self.qmf.getPackages()
- if "org.apache.qpid.cluster" not in packages:
- return None
-
- clusters = self.qmf.getObjects(_class="cluster", _agent=self.brokerAgent)
- if len(clusters) == 0:
- print "Clustering is installed but not enabled on the broker."
- return None
-
- self.cluster = clusters[0]
-
- def _getHostList(self, urlList):
- hosts = []
- hostAddr = IpAddr(_host)
- for url in urlList:
- if url.find("amqp:") != 0:
- raise Exception("Invalid URL 1")
- url = url[5:]
- addrs = str(url).split(",")
- addrList = []
- for addr in addrs:
- tokens = addr.split(":")
- if len(tokens) != 3:
- raise Exception("Invalid URL 2")
- addrList.append((tokens[1], tokens[2]))
-
- # Find the address in the list that is most likely to be in the same subnet as the address
- # with which we made the original QMF connection. This increases the probability that we will
- # be able to reach the cluster member.
-
- best = hostAddr.bestAddr(addrList)
- bestUrl = best[0] + ":" + best[1]
- hosts.append(bestUrl)
- return hosts
-
- def displaySubs(self, subs, indent, broker=None, conn=None, sess=None, exchange=None, queue=None):
- if len(subs) == 0:
- return
- this = subs[0]
- remaining = subs[1:]
- newindent = indent + " "
- if this == 'b':
- pass
- elif this == 'c':
- if broker:
- for oid in broker.connections:
- iconn = broker.connections[oid]
- self.printConnSub(indent, broker.getName(), iconn)
- self.displaySubs(remaining, newindent, broker=broker, conn=iconn,
- sess=sess, exchange=exchange, queue=queue)
- elif this == 's':
- pass
- elif this == 'e':
- pass
- elif this == 'q':
- pass
- print
-
- def displayBroker(self, subs):
- disp = Display(prefix=" ")
- heads = []
- heads.append(Header('broker'))
- heads.append(Header('cluster'))
- heads.append(Header('uptime', Header.DURATION))
- heads.append(Header('conn', Header.KMG))
- heads.append(Header('sess', Header.KMG))
- heads.append(Header('exch', Header.KMG))
- heads.append(Header('queue', Header.KMG))
- rows = []
- for broker in self.brokers:
- if self.cluster:
- ctext = "%s(%s)" % (self.cluster.clusterName, self.cluster.status)
- else:
- ctext = "<standalone>"
- row = (broker.getName(), ctext, broker.getUptime(),
- len(broker.connections), len(broker.sessions),
- len(broker.exchanges), len(broker.queues))
- rows.append(row)
- title = "Brokers"
- if _sortcol:
- sorter = Sorter(heads, rows, _sortcol, _limit, _increasing)
- dispRows = sorter.getSorted()
- else:
- dispRows = rows
- disp.formattedTable(title, heads, dispRows)
-
- def displayConn(self, subs):
- disp = Display(prefix=" ")
- heads = []
- if self.cluster:
- heads.append(Header('broker'))
- heads.append(Header('client-addr'))
- heads.append(Header('cproc'))
- heads.append(Header('cpid'))
- heads.append(Header('auth'))
- heads.append(Header('connected', Header.DURATION))
- heads.append(Header('idle', Header.DURATION))
- heads.append(Header('msgIn', Header.KMG))
- heads.append(Header('msgOut', Header.KMG))
- rows = []
- for broker in self.brokers:
- for oid in broker.connections:
- conn = broker.connections[oid]
- row = []
- if self.cluster:
- row.append(broker.getName())
- row.append(conn.address)
- row.append(conn.remoteProcessName)
- row.append(conn.remotePid)
- row.append(conn.authIdentity)
- row.append(broker.getCurrentTime() - conn.getTimestamps()[1])
- idle = broker.getCurrentTime() - conn.getTimestamps()[0]
- row.append(broker.getCurrentTime() - conn.getTimestamps()[0])
- row.append(conn.framesFromClient)
- row.append(conn.framesToClient)
- rows.append(row)
- title = "Connections"
- if self.cluster:
- title += " for cluster '%s'" % self.cluster.clusterName
- if _sortcol:
- sorter = Sorter(heads, rows, _sortcol, _limit, _increasing)
- dispRows = sorter.getSorted()
- else:
- dispRows = rows
- disp.formattedTable(title, heads, dispRows)
-
- def displaySession(self, subs):
- disp = Display(prefix=" ")
-
- def displayExchange(self, subs):
- disp = Display(prefix=" ")
- heads = []
- if self.cluster:
- heads.append(Header('broker'))
- heads.append(Header("exchange"))
- heads.append(Header("type"))
- heads.append(Header("dur", Header.Y))
- heads.append(Header("bind", Header.KMG))
- heads.append(Header("msgIn", Header.KMG))
- heads.append(Header("msgOut", Header.KMG))
- heads.append(Header("msgDrop", Header.KMG))
- heads.append(Header("byteIn", Header.KMG))
- heads.append(Header("byteOut", Header.KMG))
- heads.append(Header("byteDrop", Header.KMG))
- rows = []
- for broker in self.brokers:
- for oid in broker.exchanges:
- ex = broker.exchanges[oid]
- row = []
- if self.cluster:
- row.append(broker.getName())
- row.append(ex.name)
- row.append(ex.type)
- row.append(ex.durable)
- row.append(ex.bindingCount)
- row.append(ex.msgReceives)
- row.append(ex.msgRoutes)
- row.append(ex.msgDrops)
- row.append(ex.byteReceives)
- row.append(ex.byteRoutes)
- row.append(ex.byteDrops)
- rows.append(row)
- title = "Exchanges"
- if self.cluster:
- title += " for cluster '%s'" % self.cluster.clusterName
- if _sortcol:
- sorter = Sorter(heads, rows, _sortcol, _limit, _increasing)
- dispRows = sorter.getSorted()
- else:
- dispRows = rows
- disp.formattedTable(title, heads, dispRows)
-
- def displayQueue(self, subs):
- disp = Display(prefix=" ")
- heads = []
- if self.cluster:
- heads.append(Header('broker'))
- heads.append(Header("queue"))
- heads.append(Header("dur", Header.Y))
- heads.append(Header("autoDel", Header.Y))
- heads.append(Header("excl", Header.Y))
- heads.append(Header("msg", Header.KMG))
- heads.append(Header("msgIn", Header.KMG))
- heads.append(Header("msgOut", Header.KMG))
- heads.append(Header("bytes", Header.KMG))
- heads.append(Header("bytesIn", Header.KMG))
- heads.append(Header("bytesOut", Header.KMG))
- heads.append(Header("cons", Header.KMG))
- heads.append(Header("bind", Header.KMG))
- rows = []
- for broker in self.brokers:
- for oid in broker.queues:
- q = broker.queues[oid]
- row = []
- if self.cluster:
- row.append(broker.getName())
- row.append(q.name)
- row.append(q.durable)
- row.append(q.autoDelete)
- row.append(q.exclusive)
- row.append(q.msgDepth)
- row.append(q.msgTotalEnqueues)
- row.append(q.msgTotalDequeues)
- row.append(q.byteDepth)
- row.append(q.byteTotalEnqueues)
- row.append(q.byteTotalDequeues)
- row.append(q.consumerCount)
- row.append(q.bindingCount)
- rows.append(row)
- title = "Queues"
- if self.cluster:
- title += " for cluster '%s'" % self.cluster.clusterName
- if _sortcol:
- sorter = Sorter(heads, rows, _sortcol, _limit, _increasing)
- dispRows = sorter.getSorted()
- else:
- dispRows = rows
- disp.formattedTable(title, heads, dispRows)
-
- def displayMain(self, main, subs):
- if main == 'b': self.displayBroker(subs)
- elif main == 'c': self.displayConn(subs)
- elif main == 's': self.displaySession(subs)
- elif main == 'e': self.displayExchange(subs)
- elif main == 'q': self.displayQueue(subs)
-
- def display(self):
- self._getCluster()
- if self.cluster:
- memberList = self.cluster.members.split(";")
- hostList = self._getHostList(memberList)
- self.qmf.delBroker(self.broker)
- self.broker = None
- if _host.find("@") > 0:
- authString = _host.split("@")[0] + "@"
- else:
- authString = ""
- for host in hostList:
- b = self.qmf.addBroker(authString + host, _connTimeout)
- self.brokers.append(Broker(self.qmf, b))
- else:
- self.brokers.append(Broker(self.qmf, self.broker))
-
- self.displayMain(_types[0], _types[1:])
-
-
-##
-## Main Program
-##
-
-try:
- longOpts = ("top", "numeric", "sort-by=", "limit=", "increasing", "timeout=")
- (optlist, encArgs) = getopt.gnu_getopt(sys.argv[1:], "bceqS:L:I", longOpts)
-except:
- Usage()
-
-try:
- encoding = locale.getpreferredencoding()
- cargs = [a.decode(encoding) for a in encArgs]
-except:
- cargs = encArgs
-
-for opt in optlist:
- if opt[0] == "--timeout":
- _connTimeout = int(opt[1])
- if _connTimeout == 0:
- _connTimeout = None
- elif opt[0] == "-n" or opt[0] == "--numeric":
- _numeric = True
- elif opt[0] == "-S" or opt[0] == "--sort-by":
- _sortcol = opt[1]
- elif opt[0] == "-I" or opt[0] == "--increasing":
- _increasing = True
- elif opt[0] == "-L" or opt[0] == "--limit":
- _limit = int(opt[1])
- elif len(opt[0]) == 2:
- char = opt[0][1]
- if "bcseq".find(char) != -1:
- _types += char
- else:
- Usage()
- else:
- Usage()
-
-if len(_types) == 0:
- Usage()
-
-nargs = len(cargs)
-bm = BrokerManager()
-
-if nargs == 1:
- _host = cargs[0]
-
-try:
- bm.SetBroker(_host)
- bm.display()
-except KeyboardInterrupt:
- print
-except Exception,e:
- print "Failed: %s - %s" % (e.__class__.__name__, e)
- sys.exit(1)
-
-bm.Disconnect()
diff --git a/python/commands/qpid-tool b/python/commands/qpid-tool
deleted file mode 100755
index 05afcc9732..0000000000
--- a/python/commands/qpid-tool
+++ /dev/null
@@ -1,197 +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 getopt
-import sys
-import socket
-from cmd import Cmd
-from qpid.connection import ConnectionFailed, Timeout
-from qpid.managementdata import ManagementData
-from shlex import split
-from qpid.disp import Display
-from qpid.peer import Closed
-
-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 = "qpid: "
-
- def emptyline (self):
- pass
-
- def setPromptMessage (self, p):
- if p == None:
- self.prompt = "qpid: "
- else:
- self.prompt = "qpid[%s]: " % p
-
- def do_help (self, data):
- print "Management Tool for QPID"
- print
- print "Commands:"
- print " list - Print summary of existing objects by class"
- print " list <className> - Print list of objects of the specified class"
- print " list <className> active - Print list of non-deleted objects of the specified class"
- print " show <className> - Print contents of all objects of specified class"
- print " show <className> active - Print contents of all non-deleted objects of specified class"
- print " show <list-of-IDs> - Print contents of one or more objects (infer className)"
- print " show <className> <list-of-IDs> - Print contents of one or more objects"
- print " list is space-separated, ranges may be specified (i.e. 1004-1010)"
- print " call <ID> <methodName> [<args>] - Invoke a method on an object"
- print " schema - Print summary of object classes seen on the target"
- print " schema <className> - Print details of an object class"
- print " set time-format short - Select short timestamp format (default)"
- print " set time-format long - Select long timestamp format"
- print " id [<ID>] - Display translations of display object ids"
- 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)
- if len (tokens) < 2:
- return ["time-format "]
- elif tokens[1] == "time-format":
- if len (tokens) == 2:
- return ["long", "short"]
- elif len (tokens) == 3:
- if "long".find (text) == 0:
- return ["long"]
- elif "short".find (text) == 0:
- return ["short"]
- elif "time-format".find (text) == 0:
- return ["time-format "]
- return []
-
- def do_set (self, data):
- tokens = split (data)
- try:
- if tokens[0] == "time-format":
- self.dispObject.do_setTimeFormat (tokens[1])
- except:
- pass
-
- def do_id (self, data):
- self.dataObject.do_id(data)
-
- def complete_schema (self, text, line, begidx, endidx):
- tokens = split (line)
- if len (tokens) > 2:
- return []
- return self.dataObject.classCompletions (text)
-
- def do_schema (self, data):
- self.dataObject.do_schema (data)
-
- def complete_list (self, text, line, begidx, endidx):
- tokens = split (line)
- if len (tokens) > 2:
- return []
- return self.dataObject.classCompletions (text)
-
- def do_list (self, data):
- self.dataObject.do_list (data)
-
- def do_show (self, data):
- self.dataObject.do_show (data)
-
- def do_call (self, data):
- try:
- self.dataObject.do_call (data)
- except ValueError, e:
- print "ValueError:", 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 ()
-
-def Usage ():
- print "Usage: qpid-tool [[<username>/<password>@]<target-host>[:<tcp-port>]]"
- print
- sys.exit (1)
-
-#=========================================================
-# Main Program
-#=========================================================
-
-# Get host name and port if specified on the command line
-cargs = sys.argv[1:]
-_host = "localhost"
-
-if len (cargs) > 0:
- _host = cargs[0]
-
-if _host[0] == '-':
- Usage()
-
-disp = Display ()
-
-# Attempt to make a connection to the target broker
-try:
- data = ManagementData (disp, _host)
-except socket.error, e:
- print "Socket Error (%s):" % _host, e[1]
- sys.exit (1)
-except IOError, e:
- print "IOError: %d - %s: %s" % (e.errno, e.strerror, e.filename)
- sys.exit (1)
-except ConnectionFailed, e:
- print "Connect Failed %d - %s" % (e[0], e[1])
- sys.exit(1)
-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 QPID")
-try:
- cli.cmdloop ()
-except Closed, e:
- print "Connection to Broker Lost:", e
- sys.exit (1)
diff --git a/python/qmf/__init__.py b/python/qmf/__init__.py
deleted file mode 100644
index 31d5a2ef58..0000000000
--- a/python/qmf/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# 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.
-#
diff --git a/python/qmf/console.py b/python/qmf/console.py
deleted file mode 100644
index 45004716a8..0000000000
--- a/python/qmf/console.py
+++ /dev/null
@@ -1,1972 +0,0 @@
-#
-# 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.
-#
-
-""" Console API for Qpid Management Framework """
-
-import os
-import platform
-import qpid
-import struct
-import socket
-import re
-from qpid.datatypes import UUID
-from qpid.datatypes import timestamp
-from qpid.datatypes import datetime
-from qpid.exceptions import Closed
-from qpid.session import SessionDetached
-from qpid.connection import Connection, ConnectionFailed, Timeout
-from qpid.datatypes import Message, RangedSet, UUID
-from qpid.util import connect, ssl, URL
-from qpid.codec010 import StringCodec as Codec
-from threading import Lock, Condition, Thread
-from time import time, strftime, gmtime
-from cStringIO import StringIO
-
-#import qpid.log
-#qpid.log.enable(name="qpid.io.cmd", level=qpid.log.DEBUG)
-
-class Console:
- """ To access the asynchronous operations, a class must be derived from
- Console with overrides of any combination of the available methods. """
-
- def brokerConnected(self, broker):
- """ Invoked when a connection is established to a broker """
- pass
-
- def brokerDisconnected(self, broker):
- """ Invoked when the connection to a broker is lost """
- pass
-
- def newPackage(self, name):
- """ Invoked when a QMF package is discovered. """
- pass
-
- def newClass(self, kind, classKey):
- """ Invoked when a new class is discovered. Session.getSchema can be
- used to obtain details about the class."""
- pass
-
- def newAgent(self, agent):
- """ Invoked when a QMF agent is discovered. """
- pass
-
- def delAgent(self, agent):
- """ Invoked when a QMF agent disconects. """
- pass
-
- def objectProps(self, broker, record):
- """ Invoked when an object is updated. """
- pass
-
- def objectStats(self, broker, record):
- """ Invoked when an object is updated. """
- pass
-
- def event(self, broker, event):
- """ Invoked when an event is raised. """
- pass
-
- def heartbeat(self, agent, timestamp):
- """ Invoked when an agent heartbeat is received. """
- pass
-
- def brokerInfo(self, broker):
- """ Invoked when the connection sequence reaches the point where broker information is available. """
- pass
-
- def methodResponse(self, broker, seq, response):
- """ Invoked when a method response from an asynchronous method call is received. """
- pass
-
-class BrokerURL(URL):
- def __init__(self, text):
- URL.__init__(self, text)
- if self.port is None:
- if self.scheme == URL.AMQPS:
- self.port = 5671
- else:
- self.port = 5672
- self.authName = None
- self.authPass = None
- if self.user:
- self.authName = str(self.user)
- if self.password:
- self.authPass = str(self.password)
-
- def name(self):
- return self.host + ":" + str(self.port)
-
- def match(self, host, port):
- return socket.getaddrinfo(self.host, self.port)[0][4] == socket.getaddrinfo(host, port)[0][4]
-
-class Object(object):
- """ This class defines a 'proxy' object representing a real managed object on an agent.
- Actions taken on this proxy are remotely affected on the real managed object.
- """
- def __init__(self, session, broker, schema, codec, prop, stat, managed=True, kwargs={}):
- self._session = session
- self._broker = broker
- self._schema = schema
- self._managed = managed
- if self._managed:
- self._currentTime = codec.read_uint64()
- self._createTime = codec.read_uint64()
- self._deleteTime = codec.read_uint64()
- self._objectId = ObjectId(codec)
- else:
- self._currentTime = None
- self._createTime = None
- self._deleteTime = None
- self._objectId = None
- self._properties = []
- self._statistics = []
- if codec:
- if prop:
- notPresent = self._parsePresenceMasks(codec, schema)
- for property in schema.getProperties():
- if property.name in notPresent:
- self._properties.append((property, None))
- else:
- self._properties.append((property, self._session._decodeValue(codec, property.type, broker)))
- if stat:
- for statistic in schema.getStatistics():
- self._statistics.append((statistic, self._session._decodeValue(codec, statistic.type, broker)))
- else:
- for property in schema.getProperties():
- if property.optional:
- self._properties.append((property, None))
- else:
- self._properties.append((property, self._session._defaultValue(property, broker, kwargs)))
- for statistic in schema.getStatistics():
- self._statistics.append((statistic, self._session._defaultValue(statistic, broker, kwargs)))
-
- def getBroker(self):
- """ Return the broker from which this object was sent """
- return self._broker
-
- def getObjectId(self):
- """ Return the object identifier for this object """
- return self._objectId
-
- def getClassKey(self):
- """ Return the class-key that references the schema describing this object. """
- return self._schema.getKey()
-
- def getSchema(self):
- """ Return the schema that describes this object. """
- return self._schema
-
- def getMethods(self):
- """ Return a list of methods available for this object. """
- return self._schema.getMethods()
-
- def getTimestamps(self):
- """ Return the current, creation, and deletion times for this object. """
- return self._currentTime, self._createTime, self._deleteTime
-
- def isDeleted(self):
- """ Return True iff this object has been deleted. """
- return self._deleteTime != 0
-
- def isManaged(self):
- """ Return True iff this object is a proxy for a managed object on an agent. """
- return self._managed
-
- def getIndex(self):
- """ Return a string describing this object's primary key. """
- result = u""
- for property, value in self._properties:
- if property.index:
- if result != u"":
- result += u":"
- try:
- valstr = unicode(self._session._displayValue(value, property.type))
- except:
- valstr = u"<undecodable>"
- result += valstr
- return result
-
- def getProperties(self):
- """ Return a list of object properties """
- return self._properties
-
- def getStatistics(self):
- """ Return a list of object statistics """
- return self._statistics
-
- def mergeUpdate(self, newer):
- """ Replace properties and/or statistics with a newly received update """
- if not self.isManaged():
- raise Exception("Object is not managed")
- if self._objectId != newer._objectId:
- raise Exception("Objects with different object-ids")
- if len(newer.getProperties()) > 0:
- self._properties = newer.getProperties()
- if len(newer.getStatistics()) > 0:
- self._statistics = newer.getStatistics()
-
- def update(self):
- """ Contact the agent and retrieve the lastest property and statistic values for this object. """
- if not self.isManaged():
- raise Exception("Object is not managed")
- obj = self._session.getObjects(_objectId = self._objectId, _broker=self._broker)
- if obj:
- self.mergeUpdate(obj[0])
- else:
- raise Exception("Underlying object no longer exists")
-
- def __repr__(self):
- if self.isManaged():
- id = self.getObjectId().__repr__()
- else:
- id = "unmanaged"
- key = self.getClassKey()
- return key.getPackageName() + ":" + key.getClassName() +\
- "[" + id + "] " + self.getIndex().encode("utf8")
-
- def __getattr__(self, name):
- for method in self._schema.getMethods():
- if name == method.name:
- return lambda *args, **kwargs : self._invoke(name, args, kwargs)
- for property, value in self._properties:
- if name == property.name:
- return value
- if name == "_" + property.name + "_" and property.type == 10: # Dereference references
- deref = self._session.getObjects(_objectId=value, _broker=self._broker)
- if len(deref) != 1:
- return None
- else:
- return deref[0]
- for statistic, value in self._statistics:
- if name == statistic.name:
- return value
- raise Exception("Type Object has no attribute '%s'" % name)
-
- def __setattr__(self, name, value):
- if name[0] == '_':
- super.__setattr__(self, name, value)
- return
-
- for prop, unusedValue in self._properties:
- if name == prop.name:
- newprop = (prop, value)
- newlist = []
- for old, val in self._properties:
- if name == old.name:
- newlist.append(newprop)
- else:
- newlist.append((old, val))
- self._properties = newlist
- return
- super.__setattr__(self, name, value)
-
- def _sendMethodRequest(self, name, args, kwargs, synchronous=False, timeWait=None):
- for method in self._schema.getMethods():
- if name == method.name:
- aIdx = 0
- sendCodec = Codec()
- seq = self._session.seqMgr._reserve((method, synchronous))
- self._broker._setHeader(sendCodec, 'M', seq)
- self._objectId.encode(sendCodec)
- self._schema.getKey().encode(sendCodec)
- sendCodec.write_str8(name)
-
- count = 0
- for arg in method.arguments:
- if arg.dir.find("I") != -1:
- count += 1
- if count != len(args):
- raise Exception("Incorrect number of arguments: expected %d, got %d" % (count, len(args)))
-
- for arg in method.arguments:
- if arg.dir.find("I") != -1:
- self._session._encodeValue(sendCodec, args[aIdx], arg.type)
- aIdx += 1
- if timeWait:
- ttl = timeWait * 1000
- else:
- ttl = None
- smsg = self._broker._message(sendCodec.encoded, "agent.%d.%d" %
- (self._objectId.getBrokerBank(), self._objectId.getAgentBank()),
- ttl=ttl)
- if synchronous:
- try:
- self._broker.cv.acquire()
- self._broker.syncInFlight = True
- finally:
- self._broker.cv.release()
- self._broker._send(smsg)
- return seq
- return None
-
- def _invoke(self, name, args, kwargs):
- if not self.isManaged():
- raise Exception("Object is not managed")
- if "_timeout" in kwargs:
- timeout = kwargs["_timeout"]
- else:
- timeout = self._broker.SYNC_TIME
-
- if "_async" in kwargs and kwargs["_async"]:
- sync = False
- if "_timeout" not in kwargs:
- timeout = None
- else:
- sync = True
-
- seq = self._sendMethodRequest(name, args, kwargs, sync, timeout)
- if seq:
- if not sync:
- return seq
- try:
- self._broker.cv.acquire()
- starttime = time()
- while self._broker.syncInFlight and self._broker.error == None:
- self._broker.cv.wait(timeout)
- if time() - starttime > timeout:
- self._session.seqMgr._release(seq)
- raise RuntimeError("Timed out waiting for method to respond")
- finally:
- self._broker.cv.release()
- if self._broker.error != None:
- errorText = self._broker.error
- self._broker.error = None
- raise Exception(errorText)
- return self._broker.syncResult
- raise Exception("Invalid Method (software defect) [%s]" % name)
-
- def _encodeUnmanaged(self, codec):
-
- codec.write_uint8(20)
- codec.write_str8(self._schema.getKey().getPackageName())
- codec.write_str8(self._schema.getKey().getClassName())
- codec.write_bin128(self._schema.getKey().getHash())
-
- # emit presence masks for optional properties
- mask = 0
- bit = 0
- for prop, value in self._properties:
- if prop.optional:
- if bit == 0:
- bit = 1
- if value:
- mask |= bit
- bit = bit << 1
- if bit == 256:
- bit = 0
- codec.write_uint8(mask)
- mask = 0
- if bit != 0:
- codec.write_uint8(mask)
-
- # encode properties
- for prop, value in self._properties:
- if value != None:
- self._session._encodeValue(codec, value, prop.type)
-
- # encode statistics
- for stat, value in self._statistics:
- self._session._encodeValue(codec, value, stat.type)
-
- def _parsePresenceMasks(self, codec, schema):
- excludeList = []
- bit = 0
- for property in schema.getProperties():
- if property.optional:
- if bit == 0:
- mask = codec.read_uint8()
- bit = 1
- if (mask & bit) == 0:
- excludeList.append(property.name)
- bit *= 2
- if bit == 256:
- bit = 0
- return excludeList
-
-class Session:
- """
- An instance of the Session class represents a console session running
- against one or more QMF brokers. A single instance of Session is needed
- to interact with the management framework as a console.
- """
- _CONTEXT_SYNC = 1
- _CONTEXT_STARTUP = 2
- _CONTEXT_MULTIGET = 3
-
- DEFAULT_GET_WAIT_TIME = 60
-
- ENCODINGS = {
- str: 7,
- timestamp: 8,
- datetime: 8,
- int: 9,
- long: 9,
- float: 13,
- UUID: 14,
- Object: 20,
- list: 21
- }
-
- def __init__(self, console=None, rcvObjects=True, rcvEvents=True, rcvHeartbeats=True,
- manageConnections=False, userBindings=False):
- """
- Initialize a session. If the console argument is provided, the
- more advanced asynchronous features are available. If console is
- defaulted, the session will operate in a simpler, synchronous manner.
-
- The rcvObjects, rcvEvents, and rcvHeartbeats arguments are meaningful only if 'console'
- is provided. They control whether object updates, events, and agent-heartbeats are
- subscribed to. If the console is not interested in receiving one or more of the above,
- setting the argument to False will reduce tha bandwidth used by the API.
-
- If manageConnections is set to True, the Session object will manage connections to
- the brokers. This means that if a broker is unreachable, it will retry until a connection
- can be established. If a connection is lost, the Session will attempt to reconnect.
-
- If manageConnections is set to False, the user is responsible for handing failures. In
- this case, an unreachable broker will cause addBroker to raise an exception.
-
- If userBindings is set to False (the default) and rcvObjects is True, the console will
- receive data for all object classes. If userBindings is set to True, the user must select
- which classes the console shall receive by invoking the bindPackage or bindClass methods.
- This allows the console to be configured to receive only information that is relavant to
- a particular application. If rcvObjects id False, userBindings has no meaning.
- """
- self.console = console
- self.brokers = []
- self.packages = {}
- self.seqMgr = SequenceManager()
- self.cv = Condition()
- self.syncSequenceList = []
- self.getResult = []
- self.getSelect = []
- self.error = None
- self.rcvObjects = rcvObjects
- self.rcvEvents = rcvEvents
- self.rcvHeartbeats = rcvHeartbeats
- self.userBindings = userBindings
- if self.console == None:
- self.rcvObjects = False
- self.rcvEvents = False
- self.rcvHeartbeats = False
- self.bindingKeyList = self._bindingKeys()
- self.manageConnections = manageConnections
-
- if self.userBindings and not self.rcvObjects:
- raise Exception("userBindings can't be set unless rcvObjects is set and a console is provided")
-
- def __repr__(self):
- return "QMF Console Session Manager (brokers: %d)" % len(self.brokers)
-
- def addBroker(self, target="localhost", timeout=None, mechanisms=None):
- """ Connect to a Qpid broker. Returns an object of type Broker. """
- url = BrokerURL(target)
- broker = Broker(self, url.host, url.port, mechanisms, url.authName, url.authPass,
- ssl = url.scheme == URL.AMQPS, connTimeout=timeout)
-
- self.brokers.append(broker)
- if not self.manageConnections:
- self.getObjects(broker=broker, _class="agent")
- return broker
-
- def delBroker(self, broker):
- """ Disconnect from a broker. The 'broker' argument is the object
- returned from the addBroker call """
- if self.console:
- for agent in broker.getAgents():
- self.console.delAgent(agent)
- broker._shutdown()
- self.brokers.remove(broker)
- del broker
-
- def getPackages(self):
- """ Get the list of known QMF packages """
- for broker in self.brokers:
- broker._waitForStable()
- list = []
- for package in self.packages:
- list.append(package)
- return list
-
- def getClasses(self, packageName):
- """ Get the list of known classes within a QMF package """
- for broker in self.brokers:
- broker._waitForStable()
- list = []
- if packageName in self.packages:
- for pkey in self.packages[packageName]:
- list.append(self.packages[packageName][pkey].getKey())
- return list
-
- def getSchema(self, classKey):
- """ Get the schema for a QMF class """
- for broker in self.brokers:
- broker._waitForStable()
- pname = classKey.getPackageName()
- pkey = classKey.getPackageKey()
- if pname in self.packages:
- if pkey in self.packages[pname]:
- return self.packages[pname][pkey]
-
- def bindPackage(self, packageName):
- """ Request object updates for all table classes within a package. """
- if not self.userBindings or not self.rcvObjects:
- raise Exception("userBindings option not set for Session")
- key = "console.obj.*.*.%s.#" % packageName
- self.bindingKeyList.append(key)
- for broker in self.brokers:
- if broker.isConnected():
- broker.amqpSession.exchange_bind(exchange="qpid.management", queue=broker.topicName,
- binding_key=key)
-
- def bindClass(self, pname, cname):
- """ Request object updates for a particular table class by package and class name. """
- if not self.userBindings or not self.rcvObjects:
- raise Exception("userBindings option not set for Session")
- key = "console.obj.*.*.%s.%s.#" % (pname, cname)
- self.bindingKeyList.append(key)
- for broker in self.brokers:
- if broker.isConnected():
- broker.amqpSession.exchange_bind(exchange="qpid.management", queue=broker.topicName,
- binding_key=key)
-
- def bindClassKey(self, classKey):
- """ Request object updates for a particular table class by class key. """
- pname = classKey.getPackageName()
- cname = classKey.getClassName()
- self.bindClass(pname, cname)
-
- def getAgents(self, broker=None):
- """ Get a list of currently known agents """
- brokerList = []
- if broker == None:
- for b in self.brokers:
- brokerList.append(b)
- else:
- brokerList.append(broker)
-
- for b in brokerList:
- b._waitForStable()
- agentList = []
- for b in brokerList:
- for a in b.getAgents():
- agentList.append(a)
- return agentList
-
- def makeObject(self, classKey, broker=None, **kwargs):
- """ Create a new, unmanaged object of the schema indicated by classKey """
- schema = self.getSchema(classKey)
- if schema == None:
- raise Exception("Schema not found for classKey")
- return Object(self, broker, schema, None, True, True, False, kwargs)
-
- def getObjects(self, **kwargs):
- """ Get a list of objects from QMF agents.
- All arguments are passed by name(keyword).
-
- The class for queried objects may be specified in one of the following ways:
-
- _schema = <schema> - supply a schema object returned from getSchema.
- _key = <key> - supply a classKey from the list returned by getClasses.
- _class = <name> - supply a class name as a string. If the class name exists
- in multiple packages, a _package argument may also be supplied.
- _objectId = <id> - get the object referenced by the object-id
-
- If objects should be obtained from only one agent, use the following argument.
- Otherwise, the query will go to all agents.
-
- _agent = <agent> - supply an agent from the list returned by getAgents.
-
- If the get query is to be restricted to one broker (as opposed to all connected brokers),
- add the following argument:
-
- _broker = <broker> - supply a broker as returned by addBroker.
-
- The default timeout for this synchronous operation is 60 seconds. To change the timeout,
- use the following argument:
-
- _timeout = <time in seconds>
-
- If additional arguments are supplied, they are used as property selectors. For example,
- if the argument name="test" is supplied, only objects whose "name" property is "test"
- will be returned in the result.
- """
- if "_broker" in kwargs:
- brokerList = []
- brokerList.append(kwargs["_broker"])
- else:
- brokerList = self.brokers
- for broker in brokerList:
- broker._waitForStable()
- if broker.isConnected():
- if "_package" not in kwargs or "_class" not in kwargs or \
- kwargs["_package"] != "org.apache.qpid.broker" or \
- kwargs["_class"] != "agent":
- self.getObjects(_package = "org.apache.qpid.broker", _class = "agent",
- _agent = broker.getAgent(1,0))
-
- agentList = []
- if "_agent" in kwargs:
- agent = kwargs["_agent"]
- if agent.broker not in brokerList:
- raise Exception("Supplied agent is not accessible through the supplied broker")
- if agent.broker.isConnected():
- agentList.append(agent)
- else:
- if "_objectId" in kwargs:
- oid = kwargs["_objectId"]
- for broker in brokerList:
- for agent in broker.getAgents():
- if agent.getBrokerBank() == oid.getBrokerBank() and agent.getAgentBank() == oid.getAgentBank():
- agentList.append(agent)
- else:
- for broker in brokerList:
- for agent in broker.getAgents():
- if agent.broker.isConnected():
- agentList.append(agent)
-
- if len(agentList) == 0:
- return []
-
- pname = None
- cname = None
- hash = None
- classKey = None
- if "_schema" in kwargs: classKey = kwargs["_schema"].getKey()
- elif "_key" in kwargs: classKey = kwargs["_key"]
- elif "_class" in kwargs:
- cname = kwargs["_class"]
- if "_package" in kwargs:
- pname = kwargs["_package"]
- if cname == None and classKey == None and "_objectId" not in kwargs:
- raise Exception("No class supplied, use '_schema', '_key', '_class', or '_objectId' argument")
-
- map = {}
- self.getSelect = []
- if "_objectId" in kwargs:
- map["_objectid"] = kwargs["_objectId"].__repr__()
- else:
- if cname == None:
- cname = classKey.getClassName()
- pname = classKey.getPackageName()
- hash = classKey.getHash()
- map["_class"] = cname
- if pname != None: map["_package"] = pname
- if hash != None: map["_hash"] = hash
- for item in kwargs:
- if item[0] != '_':
- self.getSelect.append((item, kwargs[item]))
-
- self.getResult = []
- for agent in agentList:
- broker = agent.broker
- sendCodec = Codec()
- try:
- self.cv.acquire()
- seq = self.seqMgr._reserve(self._CONTEXT_MULTIGET)
- self.syncSequenceList.append(seq)
- finally:
- self.cv.release()
- broker._setHeader(sendCodec, 'G', seq)
- sendCodec.write_map(map)
- smsg = broker._message(sendCodec.encoded, "agent.%d.%d" % (agent.brokerBank, agent.agentBank))
- broker._send(smsg)
-
- starttime = time()
- timeout = False
- if "_timeout" in kwargs:
- waitTime = kwargs["_timeout"]
- else:
- waitTime = self.DEFAULT_GET_WAIT_TIME
- try:
- self.cv.acquire()
- while len(self.syncSequenceList) > 0 and self.error == None:
- self.cv.wait(waitTime)
- if time() - starttime > waitTime:
- for pendingSeq in self.syncSequenceList:
- self.seqMgr._release(pendingSeq)
- self.syncSequenceList = []
- timeout = True
- finally:
- self.cv.release()
-
- if self.error:
- errorText = self.error
- self.error = None
- raise Exception(errorText)
-
- if len(self.getResult) == 0 and timeout:
- raise RuntimeError("No agent responded within timeout period")
- return self.getResult
-
- def setEventFilter(self, **kwargs):
- """ """
- pass
-
- def _bindingKeys(self):
- keyList = []
- keyList.append("schema.#")
- if self.rcvObjects and self.rcvEvents and self.rcvHeartbeats and not self.userBindings:
- keyList.append("console.#")
- else:
- if self.rcvObjects and not self.userBindings:
- keyList.append("console.obj.#")
- else:
- keyList.append("console.obj.*.*.org.apache.qpid.broker.agent")
- if self.rcvEvents:
- keyList.append("console.event.#")
- if self.rcvHeartbeats:
- keyList.append("console.heartbeat.#")
- return keyList
-
- def _handleBrokerConnect(self, broker):
- if self.console:
- for agent in broker.getAgents():
- self.console.newAgent(agent)
- self.console.brokerConnected(broker)
-
- def _handleBrokerDisconnect(self, broker):
- if self.console:
- for agent in broker.getAgents():
- self.console.delAgent(agent)
- self.console.brokerDisconnected(broker)
-
- def _handleBrokerResp(self, broker, codec, seq):
- broker.brokerId = codec.read_uuid()
- if self.console != None:
- self.console.brokerInfo(broker)
-
- # Send a package request
- # (effectively inc and dec outstanding by not doing anything)
- sendCodec = Codec()
- seq = self.seqMgr._reserve(self._CONTEXT_STARTUP)
- broker._setHeader(sendCodec, 'P', seq)
- smsg = broker._message(sendCodec.encoded)
- broker._send(smsg)
-
- def _handlePackageInd(self, broker, codec, seq):
- pname = str(codec.read_str8())
- notify = False
- try:
- self.cv.acquire()
- if pname not in self.packages:
- self.packages[pname] = {}
- notify = True
- finally:
- self.cv.release()
- if notify and self.console != None:
- self.console.newPackage(pname)
-
- # Send a class request
- broker._incOutstanding()
- sendCodec = Codec()
- seq = self.seqMgr._reserve(self._CONTEXT_STARTUP)
- broker._setHeader(sendCodec, 'Q', seq)
- sendCodec.write_str8(pname)
- smsg = broker._message(sendCodec.encoded)
- broker._send(smsg)
-
- def _handleCommandComplete(self, broker, codec, seq):
- code = codec.read_uint32()
- text = codec.read_str8()
- context = self.seqMgr._release(seq)
- if context == self._CONTEXT_STARTUP:
- broker._decOutstanding()
- elif context == self._CONTEXT_SYNC and seq == broker.syncSequence:
- try:
- broker.cv.acquire()
- broker.syncInFlight = False
- broker.cv.notify()
- finally:
- broker.cv.release()
- elif context == self._CONTEXT_MULTIGET and seq in self.syncSequenceList:
- try:
- self.cv.acquire()
- self.syncSequenceList.remove(seq)
- if len(self.syncSequenceList) == 0:
- self.cv.notify()
- finally:
- self.cv.release()
-
- def _handleClassInd(self, broker, codec, seq):
- kind = codec.read_uint8()
- classKey = ClassKey(codec)
- unknown = False
-
- try:
- self.cv.acquire()
- if classKey.getPackageName() in self.packages:
- if classKey.getPackageKey() not in self.packages[classKey.getPackageName()]:
- unknown = True
- finally:
- self.cv.release()
-
- if unknown:
- # Send a schema request for the unknown class
- broker._incOutstanding()
- sendCodec = Codec()
- seq = self.seqMgr._reserve(self._CONTEXT_STARTUP)
- broker._setHeader(sendCodec, 'S', seq)
- classKey.encode(sendCodec)
- smsg = broker._message(sendCodec.encoded)
- broker._send(smsg)
-
- def _handleMethodResp(self, broker, codec, seq):
- code = codec.read_uint32()
- text = codec.read_str16()
- outArgs = {}
- pair = self.seqMgr._release(seq)
- if pair == None:
- return
- method, synchronous = pair
- if code == 0:
- for arg in method.arguments:
- if arg.dir.find("O") != -1:
- outArgs[arg.name] = self._decodeValue(codec, arg.type, broker)
- result = MethodResult(code, text, outArgs)
- if synchronous:
- try:
- broker.cv.acquire()
- broker.syncResult = result
- broker.syncInFlight = False
- broker.cv.notify()
- finally:
- broker.cv.release()
- else:
- if self.console:
- self.console.methodResponse(broker, seq, result)
-
- def _handleHeartbeatInd(self, broker, codec, seq, msg):
- brokerBank = 1
- agentBank = 0
- dp = msg.get("delivery_properties")
- if dp:
- key = dp["routing_key"]
- keyElements = key.split(".")
- if len(keyElements) == 4:
- brokerBank = int(keyElements[2])
- agentBank = int(keyElements[3])
-
- agent = broker.getAgent(brokerBank, agentBank)
- timestamp = codec.read_uint64()
- if self.console != None and agent != None:
- self.console.heartbeat(agent, timestamp)
-
- def _handleEventInd(self, broker, codec, seq):
- if self.console != None:
- event = Event(self, broker, codec)
- self.console.event(broker, event)
-
- def _handleSchemaResp(self, broker, codec, seq):
- kind = codec.read_uint8()
- classKey = ClassKey(codec)
- _class = SchemaClass(kind, classKey, codec, self)
- try:
- self.cv.acquire()
- self.packages[classKey.getPackageName()][classKey.getPackageKey()] = _class
- finally:
- self.cv.release()
-
- self.seqMgr._release(seq)
- broker._decOutstanding()
- if self.console != None:
- self.console.newClass(kind, classKey)
-
- def _handleContentInd(self, broker, codec, seq, prop=False, stat=False):
- classKey = ClassKey(codec)
- try:
- self.cv.acquire()
- pname = classKey.getPackageName()
- if pname not in self.packages:
- return
- pkey = classKey.getPackageKey()
- if pkey not in self.packages[pname]:
- return
- schema = self.packages[pname][pkey]
- finally:
- self.cv.release()
-
- object = Object(self, broker, schema, codec, prop, stat)
- if pname == "org.apache.qpid.broker" and classKey.getClassName() == "agent" and prop:
- broker._updateAgent(object)
-
- try:
- self.cv.acquire()
- if seq in self.syncSequenceList:
- if object.getTimestamps()[2] == 0 and self._selectMatch(object):
- self.getResult.append(object)
- return
- finally:
- self.cv.release()
-
- if self.console and self.rcvObjects:
- if prop:
- self.console.objectProps(broker, object)
- if stat:
- self.console.objectStats(broker, object)
-
- def _handleError(self, error):
- try:
- self.cv.acquire()
- if len(self.syncSequenceList) > 0:
- self.error = error
- self.syncSequenceList = []
- self.cv.notify()
- finally:
- self.cv.release()
-
- def _selectMatch(self, object):
- """ Check the object against self.getSelect to check for a match """
- for key, value in self.getSelect:
- for prop, propval in object.getProperties():
- if key == prop.name and value != propval:
- return False
- return True
-
- def _decodeValue(self, codec, typecode, broker=None):
- """ Decode, from the codec, a value based on its typecode. """
- if typecode == 1: data = codec.read_uint8() # U8
- elif typecode == 2: data = codec.read_uint16() # U16
- elif typecode == 3: data = codec.read_uint32() # U32
- elif typecode == 4: data = codec.read_uint64() # U64
- elif typecode == 6: data = codec.read_str8() # SSTR
- elif typecode == 7: data = codec.read_str16() # LSTR
- elif typecode == 8: data = codec.read_int64() # ABSTIME
- elif typecode == 9: data = codec.read_uint64() # DELTATIME
- elif typecode == 10: data = ObjectId(codec) # REF
- elif typecode == 11: data = codec.read_uint8() != 0 # BOOL
- elif typecode == 12: data = codec.read_float() # FLOAT
- elif typecode == 13: data = codec.read_double() # DOUBLE
- elif typecode == 14: data = codec.read_uuid() # UUID
- elif typecode == 16: data = codec.read_int8() # S8
- elif typecode == 17: data = codec.read_int16() # S16
- elif typecode == 18: data = codec.read_int32() # S32
- elif typecode == 19: data = codec.read_int64() # S63
- elif typecode == 15: data = codec.read_map() # FTABLE
- elif typecode == 20: # OBJECT
- # Peek at the type, and if it is still 20 pull it decode. If
- # Not, call back into self.
- inner_type_code = codec.read_uint8()
- if inner_type_code == 20:
- classKey = ClassKey(codec)
- try:
- self.cv.acquire()
- pname = classKey.getPackageName()
- if pname not in self.packages:
- return None
- pkey = classKey.getPackageKey()
- if pkey not in self.packages[pname]:
- return None
- schema = self.packages[pname][pkey]
- finally:
- self.cv.release()
- data = Object(self, broker, schema, codec, True, True, False)
- else:
- data = self._decodeValue(codec, inner_type_code, broker)
- elif typecode == 21: # List
- #taken from codec10.read_list
- sc = Codec(codec.read_vbin32())
- count = sc.read_uint32()
- data = []
- while count > 0:
- type = sc.read_uint8()
- data.append(self._decodeValue(sc,type,broker))
- count -= 1
- elif typecode == 22: #Array
- #taken from codec10.read_array
- sc = Codec(codec.read_vbin32())
- count = sc.read_uint32()
- type = sc.read_uint8()
- data = []
- while count > 0:
- data.append(self._decodeValue(sc,type,broker))
- count -= 1
- else:
- raise ValueError("Invalid type code: %d" % typecode)
- return data
-
- def _encodeValue(self, codec, value, typecode):
- """ Encode, into the codec, a value based on its typecode. """
- if typecode == 1: codec.write_uint8 (int(value)) # U8
- elif typecode == 2: codec.write_uint16 (int(value)) # U16
- elif typecode == 3: codec.write_uint32 (long(value)) # U32
- elif typecode == 4: codec.write_uint64 (long(value)) # U64
- elif typecode == 6: codec.write_str8 (value) # SSTR
- elif typecode == 7: codec.write_str16 (value) # LSTR
- elif typecode == 8: codec.write_int64 (long(value)) # ABSTIME
- elif typecode == 9: codec.write_uint64 (long(value)) # DELTATIME
- elif typecode == 10: value.encode (codec) # REF
- elif typecode == 11: codec.write_uint8 (int(value)) # BOOL
- elif typecode == 12: codec.write_float (float(value)) # FLOAT
- elif typecode == 13: codec.write_double (float(value)) # DOUBLE
- elif typecode == 14: codec.write_uuid (value.bytes) # UUID
- elif typecode == 16: codec.write_int8 (int(value)) # S8
- elif typecode == 17: codec.write_int16 (int(value)) # S16
- elif typecode == 18: codec.write_int32 (int(value)) # S32
- elif typecode == 19: codec.write_int64 (int(value)) # S64
- elif typecode == 20: value._encodeUnmanaged(codec) # OBJECT
- elif typecode == 15: codec.write_map (value) # FTABLE
- elif typecode == 21: # List
- sc = Codec()
- self._encodeValue(sc, len(value), 3)
- for o in value:
- ltype=self.encoding(o)
- self._encodeValue(sc,ltype,1)
- self._encodeValue(sc, o, ltype)
- codec.write_vbin32(sc.encoded)
- elif typecode == 22: # Array
- sc = Codec()
- self._encodeValue(sc, len(value), 3)
- if len(value) > 0:
- ltype = self.encoding(value[0])
- self._encodeValue(sc,ltype,1)
- for o in value:
- self._encodeValue(sc, o, ltype)
- codec.write_vbin32(sc.encoded)
- else:
- raise ValueError ("Invalid type code: %d" % typecode)
-
- def encoding(self, value):
- return self._encoding(value.__class__)
-
- def _encoding(self, klass):
- if Session.ENCODINGS.has_key(klass):
- return self.ENCODINGS[klass]
- for base in klass.__bases__:
- result = self._encoding(base, obj)
- if result != None:
- return result
-
- def _displayValue(self, value, typecode):
- """ """
- if typecode == 1: return unicode(value)
- elif typecode == 2: return unicode(value)
- elif typecode == 3: return unicode(value)
- elif typecode == 4: return unicode(value)
- elif typecode == 6: return value
- elif typecode == 7: return value
- elif typecode == 8: return unicode(strftime("%c", gmtime(value / 1000000000)))
- elif typecode == 9: return unicode(value)
- elif typecode == 10: return unicode(value.__repr__())
- elif typecode == 11:
- if value: return u"T"
- else: return u"F"
- elif typecode == 12: return unicode(value)
- elif typecode == 13: return unicode(value)
- elif typecode == 14: return unicode(value.__repr__())
- elif typecode == 15: return unicode(value.__repr__())
- elif typecode == 16: return unicode(value)
- elif typecode == 17: return unicode(value)
- elif typecode == 18: return unicode(value)
- elif typecode == 19: return unicode(value)
- elif typecode == 20: return unicode(value.__repr__())
- elif typecode == 21: return unicode(value.__repr__())
- elif typecode == 22: return unicode(value.__repr__())
- else:
- raise ValueError ("Invalid type code: %d" % typecode)
-
- def _defaultValue(self, stype, broker=None, kwargs={}):
- """ """
- typecode = stype.type
- if typecode == 1: return 0
- elif typecode == 2: return 0
- elif typecode == 3: return 0
- elif typecode == 4: return 0
- elif typecode == 6: return ""
- elif typecode == 7: return ""
- elif typecode == 8: return 0
- elif typecode == 9: return 0
- elif typecode == 10: return ObjectId(None)
- elif typecode == 11: return False
- elif typecode == 12: return 0.0
- elif typecode == 13: return 0.0
- elif typecode == 14: return UUID([0 for i in range(16)])
- elif typecode == 15: return {}
- elif typecode == 16: return 0
- elif typecode == 17: return 0
- elif typecode == 18: return 0
- elif typecode == 19: return 0
- elif typecode == 21: return []
- elif typecode == 22: return []
- elif typecode == 20:
- try:
- if "classKeys" in kwargs:
- keyList = kwargs["classKeys"]
- else:
- keyList = None
- classKey = self._bestClassKey(stype.refPackage, stype.refClass, keyList)
- if classKey:
- return self.makeObject(classKey, broker, kwargs)
- except:
- pass
- return None
- else:
- raise ValueError ("Invalid type code: %d" % typecode)
-
- def _bestClassKey(self, pname, cname, preferredList):
- """ """
- if pname == None or cname == None:
- if len(preferredList) == 0:
- return None
- return preferredList[0]
- for p in preferredList:
- if p.getPackageName() == pname and p.getClassName() == cname:
- return p
- clist = self.getClasses(pname)
- for c in clist:
- if c.getClassName() == cname:
- return c
- return None
-
- def _sendMethodRequest(self, broker, schemaKey, objectId, name, argList):
- """ This function can be used to send a method request to an object given only the
- broker, schemaKey, and objectId. This is an uncommon usage pattern as methods are
- normally invoked on the object itself.
- """
- schema = self.getSchema(schemaKey)
- for method in schema.getMethods():
- if name == method.name:
- aIdx = 0
- sendCodec = Codec()
- seq = self.seqMgr._reserve((method, False))
- broker._setHeader(sendCodec, 'M', seq)
- objectId.encode(sendCodec)
- schemaKey.encode(sendCodec)
- sendCodec.write_str8(name)
-
- count = 0
- for arg in method.arguments:
- if arg.dir.find("I") != -1:
- count += 1
- if count != len(argList):
- raise Exception("Incorrect number of arguments: expected %d, got %d" % (count, len(argList)))
-
- for arg in method.arguments:
- if arg.dir.find("I") != -1:
- self._encodeValue(sendCodec, argList[aIdx], arg.type)
- aIdx += 1
- smsg = broker._message(sendCodec.encoded, "agent.%d.%d" %
- (objectId.getBrokerBank(), objectId.getAgentBank()))
- broker._send(smsg)
- return seq
- return None
-
-class Package:
- """ """
- def __init__(self, name):
- self.name = name
-
-class ClassKey:
- """ A ClassKey uniquely identifies a class from the schema. """
- def __init__(self, constructor):
- if type(constructor) == str:
- # construct from __repr__ string
- try:
- self.pname, cls = constructor.split(":")
- self.cname, hsh = cls.split("(")
- hsh = hsh.strip(")")
- hexValues = hsh.split("-")
- h0 = int(hexValues[0], 16)
- h1 = int(hexValues[1], 16)
- h2 = int(hexValues[2], 16)
- h3 = int(hexValues[3], 16)
- self.hash = struct.pack("!LLLL", h0, h1, h2, h3)
- except:
- raise Exception("Invalid ClassKey format")
- else:
- # construct from codec
- codec = constructor
- self.pname = str(codec.read_str8())
- self.cname = str(codec.read_str8())
- self.hash = codec.read_bin128()
-
- def encode(self, codec):
- codec.write_str8(self.pname)
- codec.write_str8(self.cname)
- codec.write_bin128(self.hash)
-
- def getPackageName(self):
- return self.pname
-
- def getClassName(self):
- return self.cname
-
- def getHash(self):
- return self.hash
-
- def getHashString(self):
- return "%08x-%08x-%08x-%08x" % struct.unpack ("!LLLL", self.hash)
-
- def getPackageKey(self):
- return (self.cname, self.hash)
-
- def __repr__(self):
- return self.pname + ":" + self.cname + "(" + self.getHashString() + ")"
-
-class SchemaClass:
- """ """
- CLASS_KIND_TABLE = 1
- CLASS_KIND_EVENT = 2
-
- def __init__(self, kind, key, codec, session):
- self.kind = kind
- self.classKey = key
- self.properties = []
- self.statistics = []
- self.methods = []
- self.arguments = []
- self.session = session
-
- hasSupertype = 0 #codec.read_uint8()
- if self.kind == self.CLASS_KIND_TABLE:
- propCount = codec.read_uint16()
- statCount = codec.read_uint16()
- methodCount = codec.read_uint16()
- if hasSupertype == 1:
- self.superTypeKey = ClassKey(codec)
- else:
- self.superTypeKey = None ;
- for idx in range(propCount):
- self.properties.append(SchemaProperty(codec))
- for idx in range(statCount):
- self.statistics.append(SchemaStatistic(codec))
- for idx in range(methodCount):
- self.methods.append(SchemaMethod(codec))
-
- elif self.kind == self.CLASS_KIND_EVENT:
- argCount = codec.read_uint16()
- if (hasSupertype):
- self.superTypeKey = ClassKey(codec)
- else:
- self.superTypeKey = None ;
- for idx in range(argCount):
- self.arguments.append(SchemaArgument(codec, methodArg=False))
-
- def __repr__(self):
- if self.kind == self.CLASS_KIND_TABLE:
- kindStr = "Table"
- elif self.kind == self.CLASS_KIND_EVENT:
- kindStr = "Event"
- else:
- kindStr = "Unsupported"
- result = "%s Class: %s " % (kindStr, self.classKey.__repr__())
- return result
-
- def getKey(self):
- """ Return the class-key for this class. """
- return self.classKey
-
- def getProperties(self):
- """ Return the list of properties for the class. """
- if (self.superTypeKey == None):
- return self.properties
- else:
- return self.properties + self.session.getSchema(self.superTypeKey).getProperties()
-
- def getStatistics(self):
- """ Return the list of statistics for the class. """
- if (self.superTypeKey == None):
- return self.statistics
- else:
- return self.statistics + self.session.getSchema(self.superTypeKey).getStatistics()
-
- def getMethods(self):
- """ Return the list of methods for the class. """
- if (self.superTypeKey == None):
- return self.methods
- else:
- return self.methods + self.session.getSchema(self.superTypeKey).getMethods()
-
- def getArguments(self):
- """ Return the list of events for the class. """
- """ Return the list of methods for the class. """
- if (self.superTypeKey == None):
- return self.arguments
- else:
- return self.arguments + self.session.getSchema(self.superTypeKey).getArguments()
-
-class SchemaProperty:
- """ """
- def __init__(self, codec):
- map = codec.read_map()
- self.name = str(map["name"])
- self.type = map["type"]
- self.access = str(map["access"])
- self.index = map["index"] != 0
- self.optional = map["optional"] != 0
- self.refPackage = None
- self.refClass = None
- self.unit = None
- self.min = None
- self.max = None
- self.maxlen = None
- self.desc = None
-
- for key, value in map.items():
- if key == "unit" : self.unit = value
- elif key == "min" : self.min = value
- elif key == "max" : self.max = value
- elif key == "maxlen" : self.maxlen = value
- elif key == "desc" : self.desc = value
- elif key == "refPackage" : self.refPackage = value
- elif key == "refClass" : self.refClass = value
-
- def __repr__(self):
- return self.name
-
-class SchemaStatistic:
- """ """
- def __init__(self, codec):
- map = codec.read_map()
- self.name = str(map["name"])
- self.type = map["type"]
- self.unit = None
- self.desc = None
-
- for key, value in map.items():
- if key == "unit" : self.unit = value
- elif key == "desc" : self.desc = value
-
- def __repr__(self):
- return self.name
-
-class SchemaMethod:
- """ """
- def __init__(self, codec):
- map = codec.read_map()
- self.name = str(map["name"])
- argCount = map["argCount"]
- if "desc" in map:
- self.desc = map["desc"]
- else:
- self.desc = None
- self.arguments = []
-
- for idx in range(argCount):
- self.arguments.append(SchemaArgument(codec, methodArg=True))
-
- def __repr__(self):
- result = self.name + "("
- first = True
- for arg in self.arguments:
- if arg.dir.find("I") != -1:
- if first:
- first = False
- else:
- result += ", "
- result += arg.name
- result += ")"
- return result
-
-class SchemaArgument:
- """ """
- def __init__(self, codec, methodArg):
- map = codec.read_map()
- self.name = str(map["name"])
- self.type = map["type"]
- if methodArg:
- self.dir = str(map["dir"]).upper()
- self.unit = None
- self.min = None
- self.max = None
- self.maxlen = None
- self.desc = None
- self.default = None
- self.refPackage = None
- self.refClass = None
-
- for key, value in map.items():
- if key == "unit" : self.unit = value
- elif key == "min" : self.min = value
- elif key == "max" : self.max = value
- elif key == "maxlen" : self.maxlen = value
- elif key == "desc" : self.desc = value
- elif key == "default" : self.default = value
- elif key == "refPackage" : self.refPackage = value
- elif key == "refClass" : self.refClass = value
-
-class ObjectId:
- """ Object that represents QMF object identifiers """
- def __init__(self, codec, first=0, second=0):
- if codec:
- self.first = codec.read_uint64()
- self.second = codec.read_uint64()
- else:
- self.first = first
- self.second = second
-
- def __cmp__(self, other):
- if other == None or not isinstance(other, ObjectId) :
- return 1
- if self.first < other.first:
- return -1
- if self.first > other.first:
- return 1
- if self.second < other.second:
- return -1
- if self.second > other.second:
- return 1
- return 0
-
- def __repr__(self):
- return "%d-%d-%d-%d-%d" % (self.getFlags(), self.getSequence(),
- self.getBrokerBank(), self.getAgentBank(), self.getObject())
-
- def index(self):
- return (self.first, self.second)
-
- def getFlags(self):
- return (self.first & 0xF000000000000000) >> 60
-
- def getSequence(self):
- return (self.first & 0x0FFF000000000000) >> 48
-
- def getBrokerBank(self):
- return (self.first & 0x0000FFFFF0000000) >> 28
-
- def getAgentBank(self):
- return self.first & 0x000000000FFFFFFF
-
- def getObject(self):
- return self.second
-
- def isDurable(self):
- return self.getSequence() == 0
-
- def encode(self, codec):
- codec.write_uint64(self.first)
- codec.write_uint64(self.second)
-
- def __hash__(self):
- return (self.first, self.second).__hash__()
-
- def __eq__(self, other):
- return (self.first, self.second).__eq__(other)
-
-class MethodResult(object):
- """ """
- def __init__(self, status, text, outArgs):
- """ """
- self.status = status
- self.text = text
- self.outArgs = outArgs
-
- def __getattr__(self, name):
- if name in self.outArgs:
- return self.outArgs[name]
-
- def __repr__(self):
- return "%s (%d) - %s" % (self.text, self.status, self.outArgs)
-
-class ManagedConnection(Thread):
- """ Thread class for managing a connection. """
- DELAY_MIN = 1
- DELAY_MAX = 128
- DELAY_FACTOR = 2
-
- def __init__(self, broker):
- Thread.__init__(self)
- self.broker = broker
- self.cv = Condition()
- self.canceled = False
-
- def stop(self):
- """ Tell this thread to stop running and return. """
- try:
- self.cv.acquire()
- self.canceled = True
- self.cv.notify()
- finally:
- self.cv.release()
-
- def disconnected(self):
- """ Notify the thread that the connection was lost. """
- try:
- self.cv.acquire()
- self.cv.notify()
- finally:
- self.cv.release()
-
- def run(self):
- """ Main body of the running thread. """
- delay = self.DELAY_MIN
- while True:
- try:
- self.broker._tryToConnect()
- try:
- self.cv.acquire()
- while (not self.canceled) and self.broker.connected:
- self.cv.wait()
- if self.canceled:
- return
- delay = self.DELAY_MIN
- finally:
- self.cv.release()
- except socket.error:
- if delay < self.DELAY_MAX:
- delay *= self.DELAY_FACTOR
- except SessionDetached:
- if delay < self.DELAY_MAX:
- delay *= self.DELAY_FACTOR
- except Closed:
- if delay < self.DELAY_MAX:
- delay *= self.DELAY_FACTOR
-
- try:
- self.cv.acquire()
- self.cv.wait(delay)
- if self.canceled:
- return
- finally:
- self.cv.release()
-
-class Broker:
- """ This object represents a connection (or potential connection) to a QMF broker. """
- SYNC_TIME = 60
- nextSeq = 1
-
- def __init__(self, session, host, port, authMechs, authUser, authPass, ssl=False, connTimeout=None):
- self.session = session
- self.host = host
- self.port = port
- self.mechanisms = authMechs
- self.ssl = ssl
- self.connTimeout = connTimeout
- self.authUser = authUser
- self.authPass = authPass
- self.cv = Condition()
- self.error = None
- self.brokerId = None
- self.connected = False
- self.amqpSessionId = "%s.%d.%d" % (platform.uname()[1], os.getpid(), Broker.nextSeq)
- Broker.nextSeq += 1
- if self.session.manageConnections:
- self.thread = ManagedConnection(self)
- self.thread.start()
- else:
- self.thread = None
- self._tryToConnect()
-
- def isConnected(self):
- """ Return True if there is an active connection to the broker. """
- return self.connected
-
- def getError(self):
- """ Return the last error message seen while trying to connect to the broker. """
- return self.error
-
- def getBrokerId(self):
- """ Get broker's unique identifier (UUID) """
- return self.brokerId
-
- def getBrokerBank(self):
- """ Return the broker-bank value. This is the value that the broker assigns to
- objects within its control. This value appears as a field in the ObjectId
- of objects created by agents controlled by this broker. """
- return 1
-
- def getAgent(self, brokerBank, agentBank):
- """ Return the agent object associated with a particular broker and agent bank value."""
- bankKey = (brokerBank, agentBank)
- if bankKey in self.agents:
- return self.agents[bankKey]
- return None
-
- def getSessionId(self):
- """ Get the identifier of the AMQP session to the broker """
- return self.amqpSessionId
-
- def getAgents(self):
- """ Get the list of agents reachable via this broker """
- return self.agents.values()
-
- def getAmqpSession(self):
- """ Get the AMQP session object for this connected broker. """
- return self.amqpSession
-
- def getUrl(self):
- """ """
- return "%s:%d" % (self.host, self.port)
-
- def getFullUrl(self, noAuthIfGuestDefault=True):
- """ """
- ssl = ""
- if self.ssl:
- ssl = "s"
- auth = "%s/%s@" % (self.authUser, self.authPass)
- if self.authUser == "" or \
- (noAuthIfGuestDefault and self.authUser == "guest" and self.authPass == "guest"):
- auth = ""
- return "amqp%s://%s%s:%d" % (ssl, auth, self.host, self.port or 5672)
-
- def __repr__(self):
- if self.connected:
- return "Broker connected at: %s" % self.getUrl()
- else:
- return "Disconnected Broker"
-
- def _tryToConnect(self):
- try:
- self.agents = {}
- self.agents[(1,0)] = Agent(self, 0, "BrokerAgent")
- self.topicBound = False
- self.syncInFlight = False
- self.syncRequest = 0
- self.syncResult = None
- self.reqsOutstanding = 1
-
- sock = connect(self.host, self.port)
- sock.settimeout(5)
- oldTimeout = sock.gettimeout()
- sock.settimeout(self.connTimeout)
- if self.ssl:
- connSock = ssl(sock)
- else:
- connSock = sock
- self.conn = Connection(connSock, username=self.authUser, password=self.authPass,
- mechanism = self.mechanisms, host=self.host, service="qpidd")
- 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.replyName = "reply-%s" % self.amqpSessionId
- self.amqpSession = self.conn.session(self.amqpSessionId)
- self.amqpSession.auto_sync = True
- self.amqpSession.queue_declare(queue=self.replyName, exclusive=True, auto_delete=True)
- self.amqpSession.exchange_bind(exchange="amq.direct",
- queue=self.replyName, binding_key=self.replyName)
- self.amqpSession.message_subscribe(queue=self.replyName, destination="rdest",
- accept_mode=self.amqpSession.accept_mode.none,
- acquire_mode=self.amqpSession.acquire_mode.pre_acquired)
- self.amqpSession.incoming("rdest").listen(self._replyCb, self._exceptionCb)
- self.amqpSession.message_set_flow_mode(destination="rdest", flow_mode=1)
- self.amqpSession.message_flow(destination="rdest", unit=0, value=0xFFFFFFFFL)
- self.amqpSession.message_flow(destination="rdest", unit=1, value=0xFFFFFFFFL)
-
- self.topicName = "topic-%s" % self.amqpSessionId
- self.amqpSession.queue_declare(queue=self.topicName, exclusive=True, auto_delete=True)
- self.amqpSession.message_subscribe(queue=self.topicName, destination="tdest",
- accept_mode=self.amqpSession.accept_mode.none,
- acquire_mode=self.amqpSession.acquire_mode.pre_acquired)
- self.amqpSession.incoming("tdest").listen(self._replyCb)
- self.amqpSession.message_set_flow_mode(destination="tdest", flow_mode=1)
- self.amqpSession.message_flow(destination="tdest", unit=0, value=0xFFFFFFFFL)
- self.amqpSession.message_flow(destination="tdest", unit=1, value=0xFFFFFFFFL)
-
- self.connected = True
- self.session._handleBrokerConnect(self)
-
- codec = Codec()
- self._setHeader(codec, 'B')
- msg = self._message(codec.encoded)
- self._send(msg)
-
- except socket.error, e:
- self.error = "Socket Error %s - %s" % (e.__class__.__name__, e)
- raise
- except Closed, e:
- self.error = "Connect Failed %s - %s" % (e.__class__.__name__, e)
- raise
- except ConnectionFailed, e:
- self.error = "Connect Failed %s - %s" % (e.__class__.__name__, e)
- raise
-
- def _updateAgent(self, obj):
- bankKey = (obj.brokerBank, obj.agentBank)
- if obj._deleteTime == 0:
- if bankKey not in self.agents:
- agent = Agent(self, obj.agentBank, obj.label)
- self.agents[bankKey] = agent
- if self.session.console != None:
- self.session.console.newAgent(agent)
- else:
- agent = self.agents.pop(bankKey, None)
- if agent != None and self.session.console != None:
- self.session.console.delAgent(agent)
-
- def _setHeader(self, codec, opcode, seq=0):
- """ Compose the header of a management message. """
- codec.write_uint8(ord('A'))
- codec.write_uint8(ord('M'))
- codec.write_uint8(ord('2'))
- codec.write_uint8(ord(opcode))
- codec.write_uint32(seq)
-
- def _checkHeader(self, codec):
- """ Check the header of a management message and extract the opcode and class. """
- try:
- octet = chr(codec.read_uint8())
- if octet != 'A':
- return None, None
- octet = chr(codec.read_uint8())
- if octet != 'M':
- return None, None
- octet = chr(codec.read_uint8())
- if octet != '2':
- return None, None
- opcode = chr(codec.read_uint8())
- seq = codec.read_uint32()
- return opcode, seq
- except:
- return None, None
-
- def _message (self, body, routing_key="broker", ttl=None):
- dp = self.amqpSession.delivery_properties()
- dp.routing_key = routing_key
- if ttl:
- dp.ttl = ttl
- mp = self.amqpSession.message_properties()
- mp.content_type = "x-application/qmf"
- mp.user_id = self.authUser
- mp.reply_to = self.amqpSession.reply_to("amq.direct", self.replyName)
- return Message(dp, mp, body)
-
- def _send(self, msg, dest="qpid.management"):
- self.amqpSession.message_transfer(destination=dest, message=msg)
-
- def _shutdown(self):
- if self.thread:
- self.thread.stop()
- self.thread.join()
- if self.connected:
- self.amqpSession.incoming("rdest").stop()
- if self.session.console != None:
- self.amqpSession.incoming("tdest").stop()
- self.amqpSession.close()
- self.conn.close()
- self.connected = False
-
- def _waitForStable(self):
- try:
- self.cv.acquire()
- if not self.connected:
- return
- if self.reqsOutstanding == 0:
- return
- self.syncInFlight = True
- starttime = time()
- while self.reqsOutstanding != 0:
- self.cv.wait(self.SYNC_TIME)
- if time() - starttime > self.SYNC_TIME:
- raise RuntimeError("Timed out waiting for broker to synchronize")
- finally:
- self.cv.release()
-
- def _incOutstanding(self):
- try:
- self.cv.acquire()
- self.reqsOutstanding += 1
- finally:
- self.cv.release()
-
- def _decOutstanding(self):
- try:
- self.cv.acquire()
- self.reqsOutstanding -= 1
- if self.reqsOutstanding == 0 and not self.topicBound:
- self.topicBound = True
- for key in self.session.bindingKeyList:
- self.amqpSession.exchange_bind(exchange="qpid.management",
- queue=self.topicName, binding_key=key)
- if self.reqsOutstanding == 0 and self.syncInFlight:
- self.syncInFlight = False
- self.cv.notify()
- finally:
- self.cv.release()
-
- def _replyCb(self, msg):
- codec = Codec(msg.body)
- while True:
- opcode, seq = self._checkHeader(codec)
- if opcode == None: return
- if opcode == 'b': self.session._handleBrokerResp (self, codec, seq)
- elif opcode == 'p': self.session._handlePackageInd (self, codec, seq)
- elif opcode == 'z': self.session._handleCommandComplete (self, codec, seq)
- elif opcode == 'q': self.session._handleClassInd (self, codec, seq)
- elif opcode == 'm': self.session._handleMethodResp (self, codec, seq)
- elif opcode == 'h': self.session._handleHeartbeatInd (self, codec, seq, msg)
- elif opcode == 'e': self.session._handleEventInd (self, codec, seq)
- elif opcode == 's': self.session._handleSchemaResp (self, codec, seq)
- elif opcode == 'c': self.session._handleContentInd (self, codec, seq, prop=True)
- elif opcode == 'i': self.session._handleContentInd (self, codec, seq, stat=True)
- elif opcode == 'g': self.session._handleContentInd (self, codec, seq, prop=True, stat=True)
- self.session.receiver._completed.add(msg.id)
- self.session.channel.session_completed(self.session.receiver._completed)
-
- def _exceptionCb(self, data):
- self.connected = False
- self.error = data
- try:
- self.cv.acquire()
- if self.syncInFlight:
- self.cv.notify()
- finally:
- self.cv.release()
- self.session._handleError(self.error)
- self.session._handleBrokerDisconnect(self)
- if self.thread:
- self.thread.disconnected()
-
-class Agent:
- """ """
- def __init__(self, broker, agentBank, label):
- self.broker = broker
- self.brokerBank = broker.getBrokerBank()
- self.agentBank = agentBank
- self.label = label
-
- def __repr__(self):
- return "Agent at bank %d.%d (%s)" % (self.brokerBank, self.agentBank, self.label)
-
- def getBroker(self):
- return self.broker
-
- def getBrokerBank(self):
- return self.brokerBank
-
- def getAgentBank(self):
- return self.agentBank
-
-class Event:
- """ """
- def __init__(self, session, broker, codec):
- self.session = session
- self.broker = broker
- self.classKey = ClassKey(codec)
- self.timestamp = codec.read_int64()
- self.severity = codec.read_uint8()
- self.schema = None
- pname = self.classKey.getPackageName()
- pkey = self.classKey.getPackageKey()
- if pname in session.packages:
- if pkey in session.packages[pname]:
- self.schema = session.packages[pname][pkey]
- self.arguments = {}
- for arg in self.schema.arguments:
- self.arguments[arg.name] = session._decodeValue(codec, arg.type, broker)
-
- def __repr__(self):
- if self.schema == None:
- return "<uninterpretable>"
- out = strftime("%c", gmtime(self.timestamp / 1000000000))
- out += " " + self._sevName() + " " + self.classKey.getPackageName() + ":" + self.classKey.getClassName()
- out += " broker=" + self.broker.getUrl()
- for arg in self.schema.arguments:
- disp = self.session._displayValue(self.arguments[arg.name], arg.type).encode("utf8")
- if " " in disp:
- disp = "\"" + disp + "\""
- out += " " + arg.name + "=" + disp
- return out
-
- def _sevName(self):
- if self.severity == 0 : return "EMER "
- if self.severity == 1 : return "ALERT"
- if self.severity == 2 : return "CRIT "
- if self.severity == 3 : return "ERROR"
- if self.severity == 4 : return "WARN "
- if self.severity == 5 : return "NOTIC"
- if self.severity == 6 : return "INFO "
- if self.severity == 7 : return "DEBUG"
- return "INV-%d" % self.severity
-
- def getClassKey(self):
- return self.classKey
-
- def getArguments(self):
- return self.arguments
-
- def getTimestamp(self):
- return self.timestamp
-
- def getName(self):
- return self.name
-
- def getSchema(self):
- return self.schema
-
-class SequenceManager:
- """ Manage sequence numbers for asynchronous method calls """
- def __init__(self):
- self.lock = Lock()
- self.sequence = 0
- self.pending = {}
-
- def _reserve(self, data):
- """ Reserve a unique sequence number """
- try:
- self.lock.acquire()
- result = self.sequence
- self.sequence = self.sequence + 1
- self.pending[result] = data
- finally:
- self.lock.release()
- return result
-
- def _release(self, seq):
- """ Release a reserved sequence number """
- data = None
- try:
- self.lock.acquire()
- if seq in self.pending:
- data = self.pending[seq]
- del self.pending[seq]
- finally:
- self.lock.release()
- return data
-
-
-class DebugConsole(Console):
- """ """
- def brokerConnected(self, broker):
- print "brokerConnected:", broker
-
- def brokerDisconnected(self, broker):
- print "brokerDisconnected:", broker
-
- def newPackage(self, name):
- print "newPackage:", name
-
- def newClass(self, kind, classKey):
- print "newClass:", kind, classKey
-
- def newAgent(self, agent):
- print "newAgent:", agent
-
- def delAgent(self, agent):
- print "delAgent:", agent
-
- def objectProps(self, broker, record):
- print "objectProps:", record
-
- def objectStats(self, broker, record):
- print "objectStats:", record
-
- def event(self, broker, event):
- print "event:", event
-
- def heartbeat(self, agent, timestamp):
- print "heartbeat:", agent
-
- def brokerInfo(self, broker):
- print "brokerInfo:", broker
-
diff --git a/python/qmf2/__init__.py b/python/qmf2/__init__.py
deleted file mode 100644
index 31d5a2ef58..0000000000
--- a/python/qmf2/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# 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.
-#
diff --git a/python/qmf2/agent.py b/python/qmf2/agent.py
deleted file mode 100644
index a6b3c39ad1..0000000000
--- a/python/qmf2/agent.py
+++ /dev/null
@@ -1,961 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import sys
-import logging
-import datetime
-import time
-import Queue
-from threading import Thread, Lock, currentThread, Event
-from qpid.messaging import Connection, Message, Empty, SendError
-from uuid import uuid4
-from common import (make_subject, parse_subject, OpCode, QmfQuery,
- SchemaObjectClass, MsgKey, QmfData, QmfAddress,
- SchemaClass, SchemaClassId, WorkItem, SchemaMethod,
- timedelta_to_secs)
-
-# global flag that indicates which thread (if any) is
-# running the agent notifier callback
-_callback_thread=None
-
- ##==============================================================================
- ## METHOD CALL
- ##==============================================================================
-
-class _MethodCallHandle(object):
- """
- Private class used to hold context when handing off a method call to the
- application. Given to the app in a WorkItem, provided to the agent when
- method_response() is invoked.
- """
- def __init__(self, correlation_id, reply_to, meth_name, _oid=None,
- _schema_id=None):
- self.correlation_id = correlation_id
- self.reply_to = reply_to
- self.meth_name = meth_name
- self.oid = _oid
- self.schema_id = _schema_id
-
-class MethodCallParams(object):
- """
- """
- def __init__(self, name, _oid=None, _schema_id=None, _in_args=None,
- _user_id=None):
- self._meth_name = name
- self._oid = _oid
- self._schema_id = _schema_id
- self._in_args = _in_args
- self._user_id = _user_id
-
- def get_name(self):
- return self._meth_name
-
- def get_object_id(self):
- return self._oid
-
- def get_schema_id(self):
- return self._schema_id
-
- def get_args(self):
- return self._in_args
-
- def get_user_id(self):
- return self._user_id
-
-
-
- ##==============================================================================
- ## AGENT
- ##==============================================================================
-
-class Agent(Thread):
- def __init__(self, name, _domain=None, _notifier=None, _heartbeat_interval=30,
- _max_msg_size=0, _capacity=10):
- Thread.__init__(self)
- self._running = False
- self._ready = Event()
-
- self.name = str(name)
- self._domain = _domain
- self._address = QmfAddress.direct(self.name, self._domain)
- self._notifier = _notifier
- self._heartbeat_interval = _heartbeat_interval
- # @todo: currently, max # of objects in a single reply message, would
- # be better if it were max bytesize of per-msg content...
- self._max_msg_size = _max_msg_size
- self._capacity = _capacity
-
- self._conn = None
- self._session = None
- self._direct_receiver = None
- self._topic_receiver = None
- self._direct_sender = None
- self._topic_sender = None
-
- self._lock = Lock()
- self._packages = {}
- self._schema_timestamp = long(0)
- self._schema = {}
- # _described_data holds QmfData objects that are associated with schema
- # it is index by schema_id, object_id
- self._described_data = {}
- # _undescribed_data holds unstructured QmfData objects - these objects
- # have no schema. it is indexed by object_id only.
- self._undescribed_data = {}
- self._work_q = Queue.Queue()
- self._work_q_put = False
-
-
- def destroy(self, timeout=None):
- """
- Must be called before the Agent is deleted.
- Frees up all resources and shuts down all background threads.
-
- @type timeout: float
- @param timeout: maximum time in seconds to wait for all background threads to terminate. Default: forever.
- """
- logging.debug("Destroying Agent %s" % self.name)
- if self._conn:
- self.remove_connection(timeout)
- logging.debug("Agent Destroyed")
-
-
- def get_name(self):
- return self.name
-
- def set_connection(self, conn):
- self._conn = conn
- self._session = self._conn.session()
-
- # for messages directly addressed to me
- self._direct_receiver = self._session.receiver(str(self._address) +
- ";{create:always,"
- " node-properties:"
- " {type:topic,"
- " x-properties:"
- " {type:direct}}}",
- capacity=self._capacity)
- logging.debug("my direct addr=%s" % self._direct_receiver.source)
-
- # for sending directly addressed messages.
- self._direct_sender = self._session.sender(str(self._address.get_node()) +
- ";{create:always,"
- " node-properties:"
- " {type:topic,"
- " x-properties:"
- " {type:direct}}}")
- logging.debug("my default direct send addr=%s" % self._direct_sender.target)
-
- # for receiving "broadcast" messages from consoles
- default_addr = QmfAddress.topic(QmfAddress.SUBJECT_CONSOLE_IND + ".#",
- self._domain)
- self._topic_receiver = self._session.receiver(str(default_addr) +
- ";{create:always,"
- " node-properties:"
- " {type:topic}}",
- capacity=self._capacity)
- logging.debug("console.ind addr=%s" % self._topic_receiver.source)
-
- # for sending to topic subscribers
- ind_addr = QmfAddress.topic(QmfAddress.SUBJECT_AGENT_IND,
- self._domain)
- self._topic_sender = self._session.sender(str(ind_addr) +
- ";{create:always,"
- " node-properties:"
- " {type:topic}}")
- logging.debug("agent.ind addr=%s" % self._topic_sender.target)
-
- self._running = True
- self.start()
- self._ready.wait(10)
- if not self._ready.isSet():
- raise Exception("Agent managment thread failed to start.")
-
- def remove_connection(self, timeout=None):
- # tell connection thread to shutdown
- self._running = False
- if self.isAlive():
- # kick my thread to wake it up
- try:
- msg = Message(properties={"method":"request",
- "qmf.subject":make_subject(OpCode.noop)},
- subject=self.name,
- content={"noop":"noop"})
-
- # TRACE
- #logging.error("!!! sending wakeup to myself: %s" % msg)
- self._direct_sender.send( msg, sync=True )
- except SendError, e:
- logging.error(str(e))
- logging.debug("waiting for agent receiver thread to exit")
- self.join(timeout)
- if self.isAlive():
- logging.error( "Agent thread '%s' is hung..." % self.name)
- self._direct_receiver.close()
- self._direct_receiver = None
- self._direct_sender.close()
- self._direct_sender = None
- self._topic_receiver.close()
- self._topic_receiver = None
- self._topic_sender.close()
- self._topic_sender = None
- self._session.close()
- self._session = None
- self._conn = None
- logging.debug("agent connection removal complete")
-
- def register_object_class(self, schema):
- """
- Register an instance of a SchemaClass with this agent
- """
- # @todo: need to update subscriptions
- # @todo: need to mark schema as "non-const"
- if not isinstance(schema, SchemaClass):
- raise TypeError("SchemaClass instance expected")
-
- classId = schema.get_class_id()
- pname = classId.get_package_name()
- cname = classId.get_class_name()
- hstr = classId.get_hash_string()
- if not hstr:
- raise Exception("Schema hash is not set.")
-
- self._lock.acquire()
- try:
- if pname not in self._packages:
- self._packages[pname] = [cname]
- else:
- if cname not in self._packages[pname]:
- self._packages[pname].append(cname)
- self._schema[classId] = schema
- self._schema_timestamp = long(time.time() * 1000)
- finally:
- self._lock.release()
-
- def register_event_class(self, schema):
- return self.register_object_class(schema)
-
- def raise_event(self, qmfEvent):
- """
- TBD
- """
- if not self._topic_sender:
- raise Exception("No connection available")
-
- # @todo: should we validate against the schema?
- _map = {"_name": self.get_name(),
- "_event": qmfEvent.map_encode()}
- msg = Message(subject=QmfAddress.SUBJECT_AGENT_EVENT + "." +
- qmfEvent.get_severity() + "." + self.name,
- properties={"method":"response",
- "qmf.subject":make_subject(OpCode.event_ind)},
- content={MsgKey.event:_map})
- # TRACE
- # logging.error("!!! Agent %s sending Event (%s)" %
- # (self.name, str(msg)))
- self._topic_sender.send(msg)
-
- def add_object(self, data):
- """
- Register an instance of a QmfAgentData object.
- """
- # @todo: need to update subscriptions
- # @todo: need to mark schema as "non-const"
- if not isinstance(data, QmfAgentData):
- raise TypeError("QmfAgentData instance expected")
-
- oid = data.get_object_id()
- if not oid:
- raise TypeError("No identifier assigned to QmfAgentData!")
-
- sid = data.get_schema_class_id()
-
- self._lock.acquire()
- try:
- if sid:
- if sid not in self._described_data:
- self._described_data[sid] = {oid: data}
- else:
- self._described_data[sid][oid] = data
- else:
- self._undescribed_data[oid] = data
- finally:
- self._lock.release()
-
- def get_object(self, oid, schema_id):
- data = None
- self._lock.acquire()
- try:
- if schema_id:
- data = self._described_data.get(schema_id)
- if data:
- data = data.get(oid)
- else:
- data = self._undescribed_data.get(oid)
- finally:
- self._lock.release()
- return data
-
-
- def method_response(self, handle, _out_args=None, _error=None):
- """
- """
- if not isinstance(handle, _MethodCallHandle):
- raise TypeError("Invalid handle passed to method_response!")
-
- _map = {SchemaMethod.KEY_NAME:handle.meth_name}
- if handle.oid is not None:
- _map[QmfData.KEY_OBJECT_ID] = handle.oid
- if handle.schema_id is not None:
- _map[QmfData.KEY_SCHEMA_ID] = handle.schema_id.map_encode()
- if _out_args is not None:
- _map[SchemaMethod.KEY_ARGUMENTS] = _out_args.copy()
- if _error is not None:
- if not isinstance(_error, QmfData):
- raise TypeError("Invalid type for error - must be QmfData")
- _map[SchemaMethod.KEY_ERROR] = _error.map_encode()
-
- msg = Message( properties={"method":"response",
- "qmf.subject":make_subject(OpCode.response)},
- content={MsgKey.method:_map})
- msg.correlation_id = handle.correlation_id
-
- self._send_reply(msg, handle.reply_to)
-
- def get_workitem_count(self):
- """
- Returns the count of pending WorkItems that can be retrieved.
- """
- return self._work_q.qsize()
-
- def get_next_workitem(self, timeout=None):
- """
- Obtains the next pending work item, or None if none available.
- """
- try:
- wi = self._work_q.get(True, timeout)
- except Queue.Empty:
- return None
- return wi
-
- def release_workitem(self, wi):
- """
- Releases a WorkItem instance obtained by getNextWorkItem(). Called when
- the application has finished processing the WorkItem.
- """
- pass
-
-
- def run(self):
- global _callback_thread
- next_heartbeat = datetime.datetime.utcnow()
- batch_limit = 10 # a guess
-
- self._ready.set()
-
- while self._running:
-
- now = datetime.datetime.utcnow()
- # print("now=%s next_heartbeat=%s" % (now, next_heartbeat))
- if now >= next_heartbeat:
- ind = self._makeAgentIndMsg()
- ind.subject = QmfAddress.SUBJECT_AGENT_HEARTBEAT
- # TRACE
- #logging.error("!!! Agent %s sending Heartbeat (%s)" %
- # (self.name, str(ind)))
- self._topic_sender.send(ind)
- logging.debug("Agent Indication Sent")
- next_heartbeat = now + datetime.timedelta(seconds = self._heartbeat_interval)
-
- timeout = timedelta_to_secs(next_heartbeat - now)
- # print("now=%s next_heartbeat=%s timeout=%s" % (now, next_heartbeat, timeout))
- try:
- self._session.next_receiver(timeout=timeout)
- except Empty:
- continue
-
- for i in range(batch_limit):
- try:
- msg = self._topic_receiver.fetch(timeout=0)
- except Empty:
- break
- # TRACE
- # logging.error("!!! Agent %s: msg on %s [%s]" %
- # (self.name, self._topic_receiver.source, msg))
- self._dispatch(msg, _direct=False)
-
- for i in range(batch_limit):
- try:
- msg = self._direct_receiver.fetch(timeout=0)
- except Empty:
- break
- # TRACE
- # logging.error("!!! Agent %s: msg on %s [%s]" %
- # (self.name, self._direct_receiver.source, msg))
- self._dispatch(msg, _direct=True)
-
- if self._work_q_put and self._notifier:
- # new stuff on work queue, kick the the application...
- self._work_q_put = False
- _callback_thread = currentThread()
- logging.info("Calling agent notifier.indication")
- self._notifier.indication()
- _callback_thread = None
-
- #
- # Private:
- #
-
- def _makeAgentIndMsg(self):
- """
- Create an agent indication message identifying this agent
- """
- _map = {"_name": self.get_name(),
- "_schema_timestamp": self._schema_timestamp}
- return Message(properties={"method":"response",
- "qmf.subject":make_subject(OpCode.agent_ind)},
- content={MsgKey.agent_info: _map})
-
- def _send_reply(self, msg, reply_to):
- """
- Send a reply message to the given reply_to address
- """
- if not isinstance(reply_to, QmfAddress):
- try:
- reply_to = QmfAddress.from_string(str(reply_to))
- except ValueError:
- logging.error("Invalid reply-to address '%s'" % reply_to)
-
- msg.subject = reply_to.get_subject()
-
- try:
- if reply_to.is_direct():
- # TRACE
- #logging.error("!!! Agent %s direct REPLY-To:%s (%s)" %
- # (self.name, str(reply_to), str(msg)))
- self._direct_sender.send(msg)
- else:
- # TRACE
- # logging.error("!!! Agent %s topic REPLY-To:%s (%s)" %
- # (self.name, str(reply_to), str(msg)))
- self._topic_sender.send(msg)
- logging.debug("reply msg sent to [%s]" % str(reply_to))
- except SendError, e:
- logging.error("Failed to send reply msg '%s' (%s)" % (msg, str(e)))
-
- def _send_query_response(self, subject, msgkey, cid, reply_to, objects):
- """
- Send a response to a query, breaking the result into multiple
- messages based on the agent's _max_msg_size config parameter
- """
-
- total = len(objects)
- if self._max_msg_size:
- max_count = self._max_msg_size
- else:
- max_count = total
-
- start = 0
- end = min(total, max_count)
- while end <= total:
- m = Message(properties={"qmf.subject":subject,
- "method":"response"},
- correlation_id = cid,
- content={msgkey:objects[start:end]})
- self._send_reply(m, reply_to)
- if end == total:
- break;
- start = end
- end = min(total, end + max_count)
-
- # response terminator - last message has empty object array
- if total:
- m = Message(properties={"qmf.subject":subject,
- "method":"response"},
- correlation_id = cid,
- content={msgkey: []} )
- self._send_reply(m, reply_to)
-
- def _dispatch(self, msg, _direct=False):
- """
- Process a message from a console.
-
- @param _direct: True if msg directly addressed to this agent.
- """
- logging.debug( "Message received from Console! [%s]" % msg )
- try:
- version,opcode = parse_subject(msg.properties.get("qmf.subject"))
- except:
- logging.warning("Ignoring unrecognized message '%s'" % msg.subject)
- return
-
- cmap = {}; props={}
- if msg.content_type == "amqp/map":
- cmap = msg.content
- if msg.properties:
- props = msg.properties
-
- if opcode == OpCode.agent_locate:
- self._handleAgentLocateMsg( msg, cmap, props, version, _direct )
- elif opcode == OpCode.get_query:
- self._handleQueryMsg( msg, cmap, props, version, _direct )
- elif opcode == OpCode.method_req:
- self._handleMethodReqMsg(msg, cmap, props, version, _direct)
- elif opcode == OpCode.cancel_subscription:
- logging.warning("!!! CANCEL_SUB TBD !!!")
- elif opcode == OpCode.create_subscription:
- logging.warning("!!! CREATE_SUB TBD !!!")
- elif opcode == OpCode.renew_subscription:
- logging.warning("!!! RENEW_SUB TBD !!!")
- elif opcode == OpCode.schema_query:
- logging.warning("!!! SCHEMA_QUERY TBD !!!")
- elif opcode == OpCode.noop:
- logging.debug("No-op msg received.")
- else:
- logging.warning("Ignoring message with unrecognized 'opcode' value: '%s'"
- % opcode)
-
- def _handleAgentLocateMsg( self, msg, cmap, props, version, direct ):
- """
- Process a received agent-locate message
- """
- logging.debug("_handleAgentLocateMsg")
-
- reply = True
- if "method" in props and props["method"] == "request":
- query = cmap.get(MsgKey.query)
- if query is not None:
- # fake a QmfData containing my identifier for the query compare
- tmpData = QmfData.create({QmfQuery.KEY_AGENT_NAME:
- self.get_name()},
- _object_id="my-name")
- reply = QmfQuery.from_map(query).evaluate(tmpData)
-
- if reply:
- m = self._makeAgentIndMsg()
- m.correlation_id = msg.correlation_id
- self._send_reply(m, msg.reply_to)
- else:
- logging.debug("agent-locate msg not mine - no reply sent")
-
-
- def _handleQueryMsg(self, msg, cmap, props, version, _direct ):
- """
- Handle received query message
- """
- logging.debug("_handleQueryMsg")
-
- if "method" in props and props["method"] == "request":
- qmap = cmap.get(MsgKey.query)
- if qmap:
- query = QmfQuery.from_map(qmap)
- target = query.get_target()
- if target == QmfQuery.TARGET_PACKAGES:
- self._queryPackages( msg, query )
- elif target == QmfQuery.TARGET_SCHEMA_ID:
- self._querySchema( msg, query, _idOnly=True )
- elif target == QmfQuery.TARGET_SCHEMA:
- self._querySchema( msg, query)
- elif target == QmfQuery.TARGET_AGENT:
- logging.warning("!!! @todo: Query TARGET=AGENT TBD !!!")
- elif target == QmfQuery.TARGET_OBJECT_ID:
- self._queryData(msg, query, _idOnly=True)
- elif target == QmfQuery.TARGET_OBJECT:
- self._queryData(msg, query)
- else:
- logging.warning("Unrecognized query target: '%s'" % str(target))
-
-
-
- def _handleMethodReqMsg(self, msg, cmap, props, version, _direct):
- """
- Process received Method Request
- """
- if "method" in props and props["method"] == "request":
- mname = cmap.get(SchemaMethod.KEY_NAME)
- if not mname:
- logging.warning("Invalid method call from '%s': no name"
- % msg.reply_to)
- return
-
- in_args = cmap.get(SchemaMethod.KEY_ARGUMENTS)
- oid = cmap.get(QmfData.KEY_OBJECT_ID)
- schema_id = cmap.get(QmfData.KEY_SCHEMA_ID)
- if schema_id:
- schema_id = SchemaClassId.from_map(schema_id)
- handle = _MethodCallHandle(msg.correlation_id,
- msg.reply_to,
- mname,
- oid, schema_id)
- param = MethodCallParams( mname, oid, schema_id, in_args,
- msg.user_id)
-
- # @todo: validate the method against the schema:
- # if self._schema:
- # # validate
- # _in_args = _in_args.copy()
- # ms = self._schema.get_method(name)
- # if ms is None:
- # raise ValueError("Method '%s' is undefined." % name)
-
- # for aname,prop in ms.get_arguments().iteritems():
- # if aname not in _in_args:
- # if prop.get_default():
- # _in_args[aname] = prop.get_default()
- # elif not prop.is_optional():
- # raise ValueError("Method '%s' requires argument '%s'"
- # % (name, aname))
- # for aname in _in_args.iterkeys():
- # prop = ms.get_argument(aname)
- # if prop is None:
- # raise ValueError("Method '%s' does not define argument"
- # " '%s'" % (name, aname))
- # if "I" not in prop.get_direction():
- # raise ValueError("Method '%s' argument '%s' is not an"
- # " input." % (name, aname))
-
- # # @todo check if value is correct (type, range, etc)
-
- self._work_q.put(WorkItem(WorkItem.METHOD_CALL, handle, param))
- self._work_q_put = True
-
- def _queryPackages(self, msg, query):
- """
- Run a query against the list of known packages
- """
- pnames = []
- self._lock.acquire()
- try:
- for name in self._packages.iterkeys():
- qmfData = QmfData.create({SchemaClassId.KEY_PACKAGE:name},
- _object_id="_package")
- if query.evaluate(qmfData):
- pnames.append(name)
- finally:
- self._lock.release()
-
- self._send_query_response(make_subject(OpCode.data_ind),
- MsgKey.package_info,
- msg.correlation_id,
- msg.reply_to,
- pnames)
-
- def _querySchema( self, msg, query, _idOnly=False ):
- """
- """
- schemas = []
- # if querying for a specific schema, do a direct lookup
- if query.get_selector() == QmfQuery.ID:
- found = None
- self._lock.acquire()
- try:
- found = self._schema.get(query.get_id())
- finally:
- self._lock.release()
- if found:
- if _idOnly:
- schemas.append(query.get_id().map_encode())
- else:
- schemas.append(found.map_encode())
- else: # otherwise, evaluate all schema
- self._lock.acquire()
- try:
- for sid,val in self._schema.iteritems():
- if query.evaluate(val):
- if _idOnly:
- schemas.append(sid.map_encode())
- else:
- schemas.append(val.map_encode())
- finally:
- self._lock.release()
-
- if _idOnly:
- msgkey = MsgKey.schema_id
- else:
- msgkey = MsgKey.schema
-
- self._send_query_response(make_subject(OpCode.data_ind),
- msgkey,
- msg.correlation_id,
- msg.reply_to,
- schemas)
-
-
- def _queryData( self, msg, query, _idOnly=False ):
- """
- """
- data_objs = []
- # extract optional schema_id from target params
- sid = None
- t_params = query.get_target_param()
- if t_params:
- sid = t_params.get(QmfData.KEY_SCHEMA_ID)
- # if querying for a specific object, do a direct lookup
- if query.get_selector() == QmfQuery.ID:
- oid = query.get_id()
- found = None
- self._lock.acquire()
- try:
- if sid and not sid.get_hash_string():
- # wildcard schema_id match, check each schema
- for name,db in self._described_data.iteritems():
- if (name.get_class_name() == sid.get_class_name()
- and name.get_package_name() == sid.get_package_name()):
- found = db.get(oid)
- if found:
- if _idOnly:
- data_objs.append(oid)
- else:
- data_objs.append(found.map_encode())
- else:
- if sid:
- db = self._described_data.get(sid)
- if db:
- found = db.get(oid)
- else:
- found = self._undescribed_data.get(oid)
- if found:
- if _idOnly:
- data_objs.append(oid)
- else:
- data_objs.append(found.map_encode())
- finally:
- self._lock.release()
- else: # otherwise, evaluate all data
- self._lock.acquire()
- try:
- if sid and not sid.get_hash_string():
- # wildcard schema_id match, check each schema
- for name,db in self._described_data.iteritems():
- if (name.get_class_name() == sid.get_class_name()
- and name.get_package_name() == sid.get_package_name()):
- for oid,data in db.iteritems():
- if query.evaluate(data):
- if _idOnly:
- data_objs.append(oid)
- else:
- data_objs.append(data.map_encode())
- else:
- if sid:
- db = self._described_data.get(sid)
- else:
- db = self._undescribed_data
-
- if db:
- for oid,data in db.iteritems():
- if query.evaluate(data):
- if _idOnly:
- data_objs.append(oid)
- else:
- data_objs.append(data.map_encode())
- finally:
- self._lock.release()
-
- if _idOnly:
- msgkey = MsgKey.object_id
- else:
- msgkey = MsgKey.data_obj
-
- self._send_query_response(make_subject(OpCode.data_ind),
- msgkey,
- msg.correlation_id,
- msg.reply_to,
- data_objs)
-
-
-
- ##==============================================================================
- ## DATA MODEL
- ##==============================================================================
-
-
-class QmfAgentData(QmfData):
- """
- A managed data object that is owned by an agent.
- """
-
- def __init__(self, agent, _values={}, _subtypes={}, _tag=None,
- _object_id=None, _schema=None):
- schema_id = None
- if _schema:
- schema_id = _schema.get_class_id()
-
- if _object_id is None:
- if not isinstance(_schema, SchemaObjectClass):
- raise Exception("An object_id must be provided if the object"
- "doesn't have an associated schema.")
- ids = _schema.get_id_names()
- if not ids:
- raise Exception("Object must have an Id or a schema that"
- " provides an Id")
- _object_id = u""
- for key in ids:
- value = _values.get(key)
- if value is None:
- raise Exception("Object must have a value for key"
- " attribute '%s'" % str(key))
- try:
- _object_id += unicode(value)
- except:
- raise Exception("Cannot create object_id from key"
- " value '%s'" % str(value))
-
- # timestamp in millisec since epoch UTC
- ctime = long(time.time() * 1000)
- super(QmfAgentData, self).__init__(_values=_values, _subtypes=_subtypes,
- _tag=_tag, _ctime=ctime,
- _utime=ctime, _object_id=_object_id,
- _schema_id=schema_id, _const=False)
- self._agent = agent
- self._validated = False
-
- def destroy(self):
- self._dtime = long(time.time() * 1000)
- # @todo: publish change
-
- def is_deleted(self):
- return self._dtime == 0
-
- def set_value(self, _name, _value, _subType=None):
- super(QmfAgentData, self).set_value(_name, _value, _subType)
- # @todo: publish change
-
- def inc_value(self, name, delta=1):
- """ add the delta to the property """
- # @todo: need to take write-lock
- val = self.get_value(name)
- try:
- val += delta
- except:
- raise
- self.set_value(name, val)
-
- def dec_value(self, name, delta=1):
- """ subtract the delta from the property """
- # @todo: need to take write-lock
- logging.error(" TBD!!!")
-
- def validate(self):
- """
- Compares this object's data against the associated schema. Throws an
- exception if the data does not conform to the schema.
- """
- props = self._schema.get_properties()
- for name,val in props.iteritems():
- # @todo validate: type compatible with amqp_type?
- # @todo validate: primary keys have values
- if name not in self._values:
- if val._isOptional:
- # ok not to be present, put in dummy value
- # to simplify access
- self._values[name] = None
- else:
- raise Exception("Required property '%s' not present." % name)
- self._validated = True
-
-
-
-################################################################################
-################################################################################
-################################################################################
-################################################################################
-
-if __name__ == '__main__':
- # static test cases - no message passing, just exercise API
- from common import (AgentName, SchemaProperty, qmfTypes, SchemaEventClass)
-
- logging.getLogger().setLevel(logging.INFO)
-
- logging.info( "Create an Agent" )
- _agent_name = AgentName("redhat.com", "agent", "tross")
- _agent = Agent(str(_agent_name))
-
- logging.info( "Get agent name: '%s'" % _agent.get_name())
-
- logging.info( "Create SchemaObjectClass" )
-
- _schema = SchemaObjectClass(SchemaClassId("MyPackage", "MyClass"),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"])
- # add properties
- _schema.add_property("index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property("index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property("query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property("method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- # These two properties can be set via the method call
- _schema.add_property("set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property("set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # add method
- _meth = SchemaMethod(_desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- print("Schema Map='%s'" % str(_schema.map_encode()))
-
- _agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- logging.info( "Create QmfAgentData" )
-
- _obj = QmfAgentData( _agent, _schema=_schema )
- _obj.set_value("index1", 100)
- _obj.set_value("index2", "a name" )
- _obj.set_value("set_string", "UNSET")
- _obj.set_value("set_int", 0)
- _obj.set_value("query_count", 0)
- _obj.set_value("method_call_count", 0)
-
- print("Obj1 Map='%s'" % str(_obj.map_encode()))
-
- _agent.add_object( _obj )
-
- _obj = QmfAgentData( _agent,
- _values={"index1":99,
- "index2": "another name",
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0},
- _schema=_schema)
-
- print("Obj2 Map='%s'" % str(_obj.map_encode()))
-
- _agent.add_object(_obj)
-
- ##############
-
-
-
- logging.info( "Create SchemaEventClass" )
-
- _event = SchemaEventClass(SchemaClassId("MyPackage", "MyEvent",
- stype=SchemaClassId.TYPE_EVENT),
- _desc="A test data schema",
- _props={"edata_1": SchemaProperty(qmfTypes.TYPE_UINT32)})
- _event.add_property("edata_2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- print("Event Map='%s'" % str(_event.map_encode()))
-
- _agent.register_event_class(_event)
diff --git a/python/qmf2/common.py b/python/qmf2/common.py
deleted file mode 100644
index 8107b86666..0000000000
--- a/python/qmf2/common.py
+++ /dev/null
@@ -1,1943 +0,0 @@
-# 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 time
-from logging import getLogger
-from threading import Lock
-from threading import Condition
-try:
- import hashlib
- _md5Obj = hashlib.md5
-except ImportError:
- import md5
- _md5Obj = md5.new
-
-log = getLogger("qmf")
-log_query = getLogger("qmf.query")
-
-
-##
-## Constants
-##
-
-AMQP_QMF_SUBJECT = "qmf"
-AMQP_QMF_VERSION = 4
-AMQP_QMF_SUBJECT_FMT = "%s%d.%s"
-
-class MsgKey(object):
- agent_info = "agent_info"
- query = "query"
- package_info = "package_info"
- schema_id = "schema_id"
- schema = "schema"
- object_id="object_id"
- data_obj="object"
- method="method"
- event="event"
-
-
-class OpCode(object):
- noop = "noop"
-
- # codes sent by a console and processed by the agent
- agent_locate = "agent-locate"
- cancel_subscription = "cancel-subscription"
- create_subscription = "create-subscription"
- get_query = "get-query"
- method_req = "method"
- renew_subscription = "renew-subscription"
- schema_query = "schema-query" # @todo: deprecate
-
- # codes sent by the agent to a console
- agent_ind = "agent"
- data_ind = "data"
- event_ind = "event"
- managed_object = "managed-object"
- object_ind = "object"
- response = "response"
- schema_ind="schema" # @todo: deprecate
-
-
-
-
-def make_subject(_code):
- """
- Create a message subject field value.
- """
- return AMQP_QMF_SUBJECT_FMT % (AMQP_QMF_SUBJECT, AMQP_QMF_VERSION, _code)
-
-
-def parse_subject(_sub):
- """
- Deconstruct a subject field, return version,opcode values
- """
- if _sub[:3] != "qmf":
- raise Exception("Non-QMF message received")
-
- return _sub[3:].split('.', 1)
-
-def timedelta_to_secs(td):
- """
- Convert a time delta to a time interval in seconds (float)
- """
- return td.days * 86400 + td.seconds + td.microseconds/1000000.0
-
-
-##==============================================================================
-## Async Event Model
-##==============================================================================
-
-
-class Notifier(object):
- """
- Virtual base class that defines a call back which alerts the application that
- a QMF Console notification is pending.
- """
- def indication(self):
- """
- Called when one or more items are ready for the application to process.
- This method may be called by an internal QMF library thread. Its purpose is to
- indicate that the application should process pending work items.
- """
- raise Exception("The indication method must be overridden by the application!")
-
-
-
-class WorkItem(object):
- """
- Describes an event that has arrived for the application to process. The
- Notifier is invoked when one or more of these WorkItems become available
- for processing.
- """
- # Enumeration of the types of WorkItems produced on the Console
- AGENT_ADDED=1
- AGENT_DELETED=2
- NEW_PACKAGE=3
- NEW_CLASS=4
- OBJECT_UPDATE=5
- EVENT_RECEIVED=7
- AGENT_HEARTBEAT=8
- QUERY_COMPLETE=9
- METHOD_RESPONSE=10
- # Enumeration of the types of WorkItems produced on the Agent
- METHOD_CALL=1000
- QUERY=1001
- SUBSCRIBE=1002
- UNSUBSCRIBE=1003
-
- def __init__(self, kind, handle, _params=None):
- """
- Used by the Console to create a work item.
-
- @type kind: int
- @param kind: work item type
- """
- self._kind = kind
- self._handle = handle
- self._params = _params
-
- def get_type(self):
- return self._kind
-
- def get_handle(self):
- return self._handle
-
- def get_params(self):
- return self._params
-
-
-
-##==============================================================================
-## Addressing
-##==============================================================================
-
-class QmfAddress(object):
- """
- Address format: "qmf.<domain>.[topic|direct]/<subject>"
- TBD
- """
-
- TYPE_DIRECT = "direct"
- TYPE_TOPIC = "topic"
-
- ADDRESS_FMT = "qmf.%s.%s/%s"
- DEFAULT_DOMAIN = "default"
-
- # Directly-addressed messages:
- # agent's direct address: "qmf.<domain>.direct/<agent-name>
- # console's direct address: "qmf.<domain>.direct/<console-name>
-
- # Well-known Topic Addresses:
- # "qmf.<domain>.topic/<subject>
- # Where <subject> has the following format:
- # "console.ind#" - indications sent from consoles
- # "agent.ind#" - indications sent from agents
- #
- # The following "well known" subjects are defined:
- #
- # console.ind.locate[.<agent-name>] - agent discovery request
- # agent.ind.heartbeat[.<agent-name>"] - agent heartbeats
- # agent.ind.event[.<severity>.<agent-name>] - events
- # agent.ind.schema[TBD] - schema updates
- #
- SUBJECT_AGENT_IND="agent.ind"
- SUBJECT_AGENT_HEARTBEAT = "agent.ind.heartbeat"
- SUBJECT_AGENT_EVENT="agent.ind.event"
- SUBJECT_AGENT_SCHEMA="agent.ind.schema"
-
- SUBJECT_CONSOLE_IND="console.ind"
- SUBJECT_CONSOLE_LOCATE_AGENT="console.ind.locate"
-
-
-
- def __init__(self, subject, domain, type_):
- if '/' in domain or '.' in domain:
- raise Exception("domain string must not contain '/' or '.'"
- " characters.")
-
- self._subject = subject
- self._domain = domain
- self._type = type_
-
- def _direct(cls, subject, _domain=None):
- if _domain is None:
- _domain = QmfAddress.DEFAULT_DOMAIN
- return cls(subject, _domain, type_=QmfAddress.TYPE_DIRECT)
- direct = classmethod(_direct)
-
- def _topic(cls, subject, _domain=None):
- if _domain is None:
- _domain = QmfAddress.DEFAULT_DOMAIN
- return cls(subject, _domain, type_=QmfAddress.TYPE_TOPIC)
- topic = classmethod(_topic)
-
- def __from_string(cls, address):
- node,subject = address.split('/',1)
- qmf,domain,type_ = node.split('.',2)
-
- if qmf != "qmf" or (type_ != QmfAddress.TYPE_DIRECT and
- type_ != QmfAddress.TYPE_TOPIC):
- raise ValueError("invalid QmfAddress format: %s" % address)
-
- return cls(subject, domain, type_)
- from_string = classmethod(__from_string)
-
- def get_address(self):
- """
- Return the QMF address as a string, suitable for use with the AMQP
- messaging API.
- """
- return str(self)
-
- def get_node(self):
- """
- Return the 'node' portion of the address.
- """
- return self.get_address().split('/',1)[0]
-
- def get_subject(self):
- """
- Return the 'subject' portion of the address.
- """
- return self.get_address().split('/',1)[1]
-
- def get_domain(self):
- return self._domain
-
- def is_direct(self):
- return self._type == self.TYPE_DIRECT
-
- def __repr__(self):
- return QmfAddress.ADDRESS_FMT % (self._domain, self._type, self._subject)
-
-
-
-
-class AgentName(object):
- """
- Uniquely identifies a management agent within the management domain.
- """
- _separator = ":"
-
- def __init__(self, vendor, product, name, _str=None):
- """
- Note: this object must be immutable, as it is used to index into a dictionary
- """
- if _str is not None:
- # construct from string representation
- if _str.count(AgentName._separator) < 2:
- raise TypeError("AgentName string format must be 'vendor.product.name'")
- self._vendor, self._product, self._name = _str.split(AgentName._separator)
- else:
- self._vendor = vendor
- self._product = product
- self._name = name
-
-
- def _from_str(cls, str_):
- return cls(None, None, None, str_=str_)
- from_str = classmethod(_from_str)
-
- def vendor(self):
- return self._vendor
-
- def product(self):
- return self._product
-
- def name(self):
- return self._name
-
- def __cmp__(self, other):
- if not isinstance(other, AgentName) :
- raise TypeError("Invalid types for compare")
- # return 1
- me = str(self)
- them = str(other)
-
- if me < them:
- return -1
- if me > them:
- return 1
- return 0
-
- def __hash__(self):
- return (self._vendor, self._product, self._name).__hash__()
-
- def __repr__(self):
- return self._vendor + AgentName._separator + \
- self._product + AgentName._separator + \
- self._name
-
-
-
-##==============================================================================
-## DATA MODEL
-##==============================================================================
-
-
-class _mapEncoder(object):
- """
- virtual base class for all objects that support being converted to a map
- """
-
- def map_encode(self):
- raise Exception("The map_encode method my be overridden.")
-
-
-class QmfData(_mapEncoder):
- """
- Base class representing management data.
-
- Map format:
- map["_values"] = map of unordered "name"=<value> pairs (optional)
- map["_subtype"] = map of unordered "name"="subtype string" pairs (optional)
- map["_tag"] = application-specific tag for this instance (optional)
- """
- KEY_VALUES = "_values"
- KEY_SUBTYPES = "_subtypes"
- KEY_TAG="_tag"
- KEY_OBJECT_ID = "_object_id"
- KEY_SCHEMA_ID = "_schema_id"
- KEY_UPDATE_TS = "_update_ts"
- KEY_CREATE_TS = "_create_ts"
- KEY_DELETE_TS = "_delete_ts"
-
- def __init__(self,
- _values={}, _subtypes={}, _tag=None,
- _object_id=None, _schema_id=None,
- _ctime = 0, _utime = 0, _dtime = 0,
- _map=None, _const=False):
- """
- @type _values: dict
- @param _values: dictionary of initial name=value pairs for object's
- named data.
- @type _subtypes: dict
- @param _subtype: dictionary of subtype strings for each of the object's
- named data.
- @type _desc: string
- @param _desc: Human-readable description of this data object.
- @type _const: boolean
- @param _const: if true, this object cannot be modified
- """
- if _map is not None:
- # construct from map
- _tag = _map.get(self.KEY_TAG, _tag)
- _values = _map.get(self.KEY_VALUES, _values)
- _subtypes = _map.get(self.KEY_SUBTYPES, _subtypes)
- _object_id = _map.get(self.KEY_OBJECT_ID, _object_id)
- sid = _map.get(self.KEY_SCHEMA_ID)
- if sid:
- _schema_id = SchemaClassId.from_map(sid)
- _ctime = long(_map.get(self.KEY_CREATE_TS, _ctime))
- _utime = long(_map.get(self.KEY_UPDATE_TS, _utime))
- _dtime = long(_map.get(self.KEY_DELETE_TS, _dtime))
-
- if _object_id is None:
- raise Exception("An object_id must be provided.")
-
- self._values = _values.copy()
- self._subtypes = _subtypes.copy()
- self._tag = _tag
- self._ctime = _ctime
- self._utime = _utime
- self._dtime = _dtime
- self._const = _const
- self._schema_id = _schema_id
- self._object_id = str(_object_id)
-
-
- def __create(cls, values, _subtypes={}, _tag=None, _object_id=None,
- _schema_id=None, _const=False):
- # timestamp in millisec since epoch UTC
- ctime = long(time.time() * 1000)
- return cls(_values=values, _subtypes=_subtypes, _tag=_tag,
- _ctime=ctime, _utime=ctime,
- _object_id=_object_id, _schema_id=_schema_id, _const=_const)
- create = classmethod(__create)
-
- def __from_map(cls, map_, _const=False):
- return cls(_map=map_, _const=_const)
- from_map = classmethod(__from_map)
-
- def is_managed(self):
- return self._object_id is not None
-
- def is_described(self):
- return self._schema_id is not None
-
- def get_tag(self):
- return self._tag
-
- def get_value(self, name):
- """
- Will throw an AttributeError exception if the named value does not exist.
- """
- # meta-properties first:
- if name == SchemaClassId.KEY_PACKAGE:
- if self._schema_id:
- return self._schema_id.get_package_name()
- return None
- if name == SchemaClassId.KEY_CLASS:
- if self._schema_id:
- return self._schema_id.get_class_name()
- return None
- if name == SchemaClassId.KEY_TYPE:
- if self._schema_id:
- return self._schema_id.get_type()
- return None
- if name == SchemaClassId.KEY_HASH:
- if self._schema_id:
- return self._schema_id.get_hash_string()
- return None
- if name == self.KEY_SCHEMA_ID:
- return self._schema_id
- if name == self.KEY_OBJECT_ID:
- return self._object_id
- if name == self.KEY_TAG:
- return self._tag
- if name == self.KEY_UPDATE_TS:
- return self._utime
- if name == self.KEY_CREATE_TS:
- return self._ctime
- if name == self.KEY_DELETE_TS:
- return self._dtime
-
- try:
- return self._values[name]
- except KeyError:
- raise AttributeError("no value named '%s' in this object" % name)
-
- def has_value(self, name):
-
- if name in [SchemaClassId.KEY_PACKAGE, SchemaClassId.KEY_CLASS,
- SchemaClassId.KEY_TYPE, SchemaClassId.KEY_HASH,
- self.KEY_SCHEMA_ID]:
- return self._schema_id is not None
- if name in [self.KEY_UPDATE_TS, self.KEY_CREATE_TS,
- self.KEY_DELETE_TS]:
- return True
- if name == self.KEY_OBJECT_ID:
- return self._object_id is not None
- if name == self.KEY_TAG:
- return self._tag is not None
-
- return name in self._values
-
- def set_value(self, _name, _value, _subType=None):
- if self._const:
- raise Exception("cannot modify constant data object")
- self._values[_name] = _value
- if _subType:
- self._subtypes[_name] = _subType
- return _value
-
- def get_subtype(self, _name):
- return self._subtypes.get(_name)
-
- def get_schema_class_id(self):
- """
- @rtype: class SchemaClassId
- @returns: the identifier of the Schema that describes the structure of the data.
- """
- return self._schema_id
-
- def get_object_id(self):
- """
- Get the instance's identification string.
- @rtype: str
- @returns: the identification string, or None if not assigned and id.
- """
- return self._object_id
-
- def map_encode(self):
- _map = {}
- if self._tag:
- _map[self.KEY_TAG] = self._tag
-
- # data in the _values map may require recursive map_encode()
- vmap = {}
- for name,val in self._values.iteritems():
- if isinstance(val, _mapEncoder):
- vmap[name] = val.map_encode()
- else:
- # otherwise, just toss in the native type...
- vmap[name] = val
-
- _map[self.KEY_VALUES] = vmap
- # subtypes are never complex, so safe to just copy
- _map[self.KEY_SUBTYPES] = self._subtypes.copy()
- if self._object_id:
- _map[self.KEY_OBJECT_ID] = self._object_id
- if self._schema_id:
- _map[self.KEY_SCHEMA_ID] = self._schema_id.map_encode()
- return _map
-
- def __repr__(self):
- return "QmfData=<<" + str(self.map_encode()) + ">>"
-
-
- def __setattr__(self, _name, _value):
- # ignore private data members
- if _name[0] == '_':
- return super(QmfData, self).__setattr__(_name, _value)
- if _name in self._values:
- return self.set_value(_name, _value)
- return super(QmfData, self).__setattr__(_name, _value)
-
- def __getattr__(self, _name):
- if _name != "_values" and _name in self._values:
- return self._values[_name]
- raise AttributeError("no value named '%s' in this object" % _name)
-
- def __getitem__(self, _name):
- return self.__getattr__(_name)
-
- def __setitem__(self, _name, _value):
- return self.__setattr__(_name, _value)
-
-
-
-class QmfEvent(QmfData):
- """
- A QMF Event is a type of described data that is not managed. Events are
- notifications that are sent by Agents. An event notifies a Console of a
- change in some aspect of the system under managment.
- """
- KEY_TIMESTAMP = "_timestamp"
- KEY_SEVERITY = "_severity"
-
- SEV_EMERG = "emerg"
- SEV_ALERT = "alert"
- SEV_CRIT = "crit"
- SEV_ERR = "err"
- SEV_WARNING = "warning"
- SEV_NOTICE = "notice"
- SEV_INFO = "info"
- SEV_DEBUG = "debug"
-
- def __init__(self, _timestamp=None, _sev=SEV_NOTICE, _values={},
- _subtypes={}, _tag=None,
- _map=None,
- _schema_id=None, _const=True):
- """
- @type _map: dict
- @param _map: if not None, construct instance from map representation.
- @type _timestamp: int
- @param _timestamp: moment in time when event occurred, expressed
- as milliseconds since Midnight, Jan 1, 1970 UTC.
- @type _agentId: class AgentId
- @param _agentId: Identifies agent issuing this event.
- @type _schema: class Schema
- @param _schema:
- @type _schemaId: class SchemaClassId (event)
- @param _schemaId: identi
- """
-
- if _map is not None:
- # construct from map
- super(QmfEvent, self).__init__(_map=_map, _const=_const,
- _object_id="_event")
- _timestamp = _map.get(self.KEY_TIMESTAMP, _timestamp)
- _sev = _map.get(self.KEY_SEVERITY, _sev)
- else:
- super(QmfEvent, self).__init__(_object_id="_event",
- _values=_values,
- _subtypes=_subtypes, _tag=_tag,
- _schema_id=_schema_id,
- _const=_const)
- if _timestamp is None:
- raise TypeError("QmfEvent: a valid timestamp is required.")
-
- try:
- self._timestamp = long(_timestamp)
- except:
- raise TypeError("QmfEvent: a numeric timestamp is required.")
-
- self._severity = _sev
-
- def _create(cls, timestamp, severity, values,
- _subtypes={}, _tag=None, _schema_id=None, _const=False):
- return cls(_timestamp=timestamp, _sev=severity, _values=values,
- _subtypes=_subtypes, _tag=_tag, _schema_id=_schema_id, _const=_const)
- create = classmethod(_create)
-
- def _from_map(cls, map_, _const=False):
- return cls(_map=map_, _const=_const)
- from_map = classmethod(_from_map)
-
- def get_timestamp(self):
- return self._timestamp
-
- def get_severity(self):
- return self._severity
-
- def map_encode(self):
- _map = super(QmfEvent, self).map_encode()
- _map[self.KEY_TIMESTAMP] = self._timestamp
- _map[self.KEY_SEVERITY] = self._severity
- return _map
-
-
-
-
-
-#==============================================================================
-#==============================================================================
-#==============================================================================
-
-
-
-
-class Arguments(object):
- def __init__(self, map):
- pass
-# self.map = map
-# self._by_hash = {}
-# key_count = self.map.keyCount()
-# a = 0
-# while a < key_count:
-# self._by_hash[self.map.key(a)] = self.by_key(self.map.key(a))
-# a += 1
-
-
-# def __getitem__(self, key):
-# return self._by_hash[key]
-
-
-# def __setitem__(self, key, value):
-# self._by_hash[key] = value
-# self.set(key, value)
-
-
-# def __iter__(self):
-# return self._by_hash.__iter__
-
-
-# def __getattr__(self, name):
-# if name in self._by_hash:
-# return self._by_hash[name]
-# return super.__getattr__(self, name)
-
-
-# def __setattr__(self, name, value):
-# #
-# # ignore local data members
-# #
-# if (name[0] == '_' or
-# name == 'map'):
-# return super.__setattr__(self, name, value)
-
-# if name in self._by_hash:
-# self._by_hash[name] = value
-# return self.set(name, value)
-
-# return super.__setattr__(self, name, value)
-
-
-# def by_key(self, key):
-# val = self.map.byKey(key)
-# vType = val.getType()
-# if vType == TYPE_UINT8: return val.asUint()
-# elif vType == TYPE_UINT16: return val.asUint()
-# elif vType == TYPE_UINT32: return val.asUint()
-# elif vType == TYPE_UINT64: return val.asUint64()
-# elif vType == TYPE_SSTR: return val.asString()
-# elif vType == TYPE_LSTR: return val.asString()
-# elif vType == TYPE_ABSTIME: return val.asInt64()
-# elif vType == TYPE_DELTATIME: return val.asUint64()
-# elif vType == TYPE_REF: return ObjectId(val.asObjectId())
-# elif vType == TYPE_BOOL: return val.asBool()
-# elif vType == TYPE_FLOAT: return val.asFloat()
-# elif vType == TYPE_DOUBLE: return val.asDouble()
-# elif vType == TYPE_UUID: return val.asUuid()
-# elif vType == TYPE_INT8: return val.asInt()
-# elif vType == TYPE_INT16: return val.asInt()
-# elif vType == TYPE_INT32: return val.asInt()
-# elif vType == TYPE_INT64: return val.asInt64()
-# else:
-# # when TYPE_MAP
-# # when TYPE_OBJECT
-# # when TYPE_LIST
-# # when TYPE_ARRAY
-# logging.error( "Unsupported Type for Get? '%s'" % str(val.getType()))
-# return None
-
-
-# def set(self, key, value):
-# val = self.map.byKey(key)
-# vType = val.getType()
-# if vType == TYPE_UINT8: return val.setUint(value)
-# elif vType == TYPE_UINT16: return val.setUint(value)
-# elif vType == TYPE_UINT32: return val.setUint(value)
-# elif vType == TYPE_UINT64: return val.setUint64(value)
-# elif vType == TYPE_SSTR:
-# if value:
-# return val.setString(value)
-# else:
-# return val.setString('')
-# elif vType == TYPE_LSTR:
-# if value:
-# return val.setString(value)
-# else:
-# return val.setString('')
-# elif vType == TYPE_ABSTIME: return val.setInt64(value)
-# elif vType == TYPE_DELTATIME: return val.setUint64(value)
-# elif vType == TYPE_REF: return val.setObjectId(value.impl)
-# elif vType == TYPE_BOOL: return val.setBool(value)
-# elif vType == TYPE_FLOAT: return val.setFloat(value)
-# elif vType == TYPE_DOUBLE: return val.setDouble(value)
-# elif vType == TYPE_UUID: return val.setUuid(value)
-# elif vType == TYPE_INT8: return val.setInt(value)
-# elif vType == TYPE_INT16: return val.setInt(value)
-# elif vType == TYPE_INT32: return val.setInt(value)
-# elif vType == TYPE_INT64: return val.setInt64(value)
-# else:
-# # when TYPE_MAP
-# # when TYPE_OBJECT
-# # when TYPE_LIST
-# # when TYPE_ARRAY
-# logging.error("Unsupported Type for Set? '%s'" % str(val.getType()))
-# return None
-
-
-
-#class MethodResponse(object):
-# def __init__(self, impl):
-# pass
-# self.impl = qmfengine.MethodResponse(impl)
-
-
-# def status(self):
-# return self.impl.getStatus()
-
-
-# def exception(self):
-# return self.impl.getException()
-
-
-# def text(self):
-# return exception().asString()
-
-
-# def args(self):
-# return Arguments(self.impl.getArgs())
-
-
-# def __getattr__(self, name):
-# myArgs = self.args()
-# return myArgs.__getattr__(name)
-
-
-# def __setattr__(self, name, value):
-# if name == 'impl':
-# return super.__setattr__(self, name, value)
-
-# myArgs = self.args()
-# return myArgs.__setattr__(name, value)
-
-
-
-# ##==============================================================================
-# ## QUERY
-# ##==============================================================================
-
-
-
-# def _doQuery(predicate, params ):
-# """
-# Given the predicate from a query, and a map of named parameters, apply the predicate
-# to the parameters, and return True or False.
-# """
-# if type(predicate) != list or len(predicate) < 1:
-# return False
-
-# elif opr == Query._LOGIC_AND:
-# logging.debug("_doQuery() AND: [%s]" % predicate )
-# rc = False
-# for exp in predicate[1:]:
-# rc = _doQuery( exp, params )
-# if not rc:
-# break
-# return rc
-
-# elif opr == Query._LOGIC_OR:
-# logging.debug("_doQuery() OR: [%s]" % predicate )
-# rc = False
-# for exp in predicate[1:]:
-# rc = _doQuery( exp, params )
-# if rc:
-# break
-# return rc
-
-# elif opr == Query._LOGIC_NOT:
-# logging.debug("_doQuery() NOT: [%s]" % predicate )
-# if len(predicate) != 2:
-# logging.warning("Malformed query not-expression received: '%s'" % predicate)
-# return False
-# return not _doQuery( predicate[1:], params )
-
-
-
-# else:
-# logging.warning("Unknown query operator received: '%s'" % opr)
-# return False
-
-
-
-class QmfQuery(_mapEncoder):
-
- KEY_TARGET="what"
- KEY_PREDICATE="where"
- KEY_ID="id"
-
- ### Query Types
- ID=1
- PREDICATE=2
-
- #### Query Targets ####
- TARGET_PACKAGES="schema_package"
- # (returns just package names)
- # allowed predicate key(s):
- #
- # SchemaClassId.KEY_PACKAGE
-
- TARGET_SCHEMA_ID="schema_id"
- TARGET_SCHEMA="schema"
- # allowed id: value:
- # SchemaClassId
- #
- # allowed predicate key(s):
- # SchemaClassId.KEY_PACKAGE
- # SchemaClassId.KEY_CLASS
- # SchemaClassId.KEY_TYPE
- # SchemaClassId.KEY_HASH
- # SchemaClass.KEY_SCHEMA_ID
- # name of property (exist test only)
- # name of method (exist test only)
-
- TARGET_AGENT="agent"
- # allowed id: value:
- # string name of agent
- # allowed predicate keys(s):
- #
- KEY_AGENT_NAME="_name"
-
- TARGET_OBJECT_ID="object_id"
- TARGET_OBJECT="object"
- # If object is described by a schema, the value of the target map must
- # include a "_schema_id": {map encoded schema id} value.
- #
- # allowed id: value:
- # object_id string
- #
- # allowed predicate keys(s):
- #
- # QmfData.KEY_OBJECT_ID
- # QmfData.KEY_UPDATE_TS
- # QmfData.KEY_CREATE_TS
- # QmfData.KEY_DELETE_TS
- # <name of data value>
-
- # supported predicate operators
-
- # evaluation operators
- QUOTE="quote"
- UNQUOTE="unquote"
- # boolean operators
- EQ="eq"
- NE="ne"
- LT="lt"
- LE="le"
- GT="gt"
- GE="ge"
- RE_MATCH="re_match"
- EXISTS="exists"
- TRUE="true"
- FALSE="false"
- # logic operators
- AND="and"
- OR="or"
- NOT="not"
-
- _valid_targets = [TARGET_PACKAGES, TARGET_OBJECT_ID, TARGET_SCHEMA, TARGET_SCHEMA_ID,
- TARGET_OBJECT, TARGET_AGENT]
- _valid_bool_ops = [EQ, NE, LT, GT, LE, GE, EXISTS, RE_MATCH, TRUE, FALSE]
- _valid_logic_ops = [AND, OR, NOT]
- _valid_eval_ops = [QUOTE, UNQUOTE]
-
- def __init__(self, _target=None, _target_params=None, _predicate=None,
- _id=None, _map=None):
- """
- """
- if _map is not None:
- target_map = _map.get(self.KEY_TARGET)
- if not target_map:
- raise TypeError("QmfQuery requires a target map")
-
- _target = None
- for key in target_map.iterkeys():
- if key in self._valid_targets:
- _target = key
- break
- if _target is None:
- raise TypeError("Invalid QmfQuery target: '%s'" %
- str(target_map))
-
- # convert target params from map format
- _target_params = target_map.get(_target)
- if _target_params:
- if not isinstance(_target_params, type({})):
- raise TypeError("target params must be a map: '%s'" %
- str(_target_params))
- t_params = {}
- for name,value in _target_params.iteritems():
- if name == QmfData.KEY_SCHEMA_ID:
- t_params[name] = SchemaClassId.from_map(value)
- else:
- t_params[name] = value
- _target_params = t_params
-
- _id = _map.get(self.KEY_ID)
- if _id is not None:
- # Convert identifier to native type if necessary
- if _target == self.TARGET_SCHEMA:
- _id = SchemaClassId.from_map(_id)
- else:
- _predicate = _map.get(self.KEY_PREDICATE, _predicate)
-
- self._target = _target
- if not self._target:
- raise TypeError("QmfQuery requires a target value")
- self._target_params = _target_params
- self._predicate = _predicate
- self._id = _id
-
- # constructors
- def _create_wildcard(cls, target, _target_params=None):
- return cls(_target=target, _target_params=_target_params)
- create_wildcard = classmethod(_create_wildcard)
-
- def _create_wildcard_object_id(cls, schema_id):
- """
- Create a wildcard to match all object_ids for a given schema.
- """
- if not isinstance(schema_id, SchemaClassId):
- raise TypeError("class SchemaClassId expected")
- params = {QmfData.KEY_SCHEMA_ID: schema_id}
- return cls(_target=QmfQuery.TARGET_OBJECT_ID,
- _target_params=params)
- create_wildcard_object_id = classmethod(_create_wildcard_object_id)
-
- def _create_wildcard_object(cls, schema_id):
- """
- Create a wildcard to match all objects for a given schema.
- """
- if not isinstance(schema_id, SchemaClassId):
- raise TypeError("class SchemaClassId expected")
- params = {QmfData.KEY_SCHEMA_ID: schema_id}
- return cls(_target=QmfQuery.TARGET_OBJECT,
- _target_params=params)
- create_wildcard_object = classmethod(_create_wildcard_object)
-
- def _create_predicate(cls, target, predicate, _target_params=None):
- return cls(_target=target, _target_params=_target_params,
- _predicate=predicate)
- create_predicate = classmethod(_create_predicate)
-
- def _create_id(cls, target, ident, _target_params=None):
- return cls(_target=target, _target_params=_target_params, _id=ident)
- create_id = classmethod(_create_id)
-
- def _create_id_object(cls, object_id, _schema_id=None):
- """
- Create a ID Query for an object (schema optional).
- """
- if _schema_id is not None:
- if not isinstance(_schema_id, SchemaClassId):
- raise TypeError("class SchemaClassId expected")
- params = {QmfData.KEY_SCHEMA_ID: _schema_id}
- else:
- params = None
- return cls(_target=QmfQuery.TARGET_OBJECT,
- _id=object_id,
- _target_params=params)
- create_id_object = classmethod(_create_id_object)
-
- def _create_id_object_id(cls, object_id, _schema_id=None):
- """
- Create a ID Query for object_ids (schema optional).
- """
- if _schema_id is not None:
- if not isinstance(_schema_id, SchemaClassId):
- raise TypeError("class SchemaClassId expected")
- params = {QmfData.KEY_SCHEMA_ID: _schema_id}
- else:
- params = None
- return cls(_target=QmfQuery.TARGET_OBJECT_ID,
- _id=object_id,
- _target_params=params)
- create_id_object_id = classmethod(_create_id_object_id)
-
- def _from_map(cls, map_):
- return cls(_map=map_)
- from_map = classmethod(_from_map)
- # end constructors
-
- def get_target(self):
- return self._target
-
- def get_target_param(self):
- return self._target_params
-
- def get_selector(self):
- if self._id:
- return QmfQuery.ID
- else:
- return QmfQuery.PREDICATE
-
- def get_id(self):
- return self._id
-
- def get_predicate(self):
- """
- """
- return self._predicate
-
- def evaluate(self, qmfData):
- """
- """
- if self._id:
- if self._target == self.TARGET_SCHEMA:
- return (qmfData.has_value(qmfData.KEY_SCHEMA_ID) and
- qmfData.get_value(qmfData.KEY_SCHEMA_ID) == self._id)
- elif self._target == self.TARGET_OBJECT:
- return (qmfData.has_value(qmfData.KEY_OBJECT_ID) and
- qmfData.get_value(qmfData.KEY_OBJECT_ID) == self._id)
- elif self._target == self.TARGET_AGENT:
- return (qmfData.has_value(self.KEY_AGENT_NAME) and
- qmfData.get_value(self.KEY_AGENT_NAME) == self._id)
-
- raise Exception("Unsupported query target '%s'" % str(self._target))
-
- if self._predicate:
- return self._eval_pred(self._predicate, qmfData)
- # no predicate and no id - always match
- return True
-
- def map_encode(self):
- t_params = {}
- if self._target_params:
- for name,value in self._target_params.iteritems():
- if isinstance(value, _mapEncoder):
- t_params[name] = value.map_encode()
- else:
- t_params[name] = value
- if t_params:
- _map = {self.KEY_TARGET: {self._target: t_params}}
- else:
- _map = {self.KEY_TARGET: {self._target: None}}
-
- if self._id is not None:
- if isinstance(self._id, _mapEncoder):
- _map[self.KEY_ID] = self._id.map_encode()
- else:
- _map[self.KEY_ID] = self._id
- elif self._predicate is not None:
- _map[self.KEY_PREDICATE] = self._predicate
- return _map
-
- def _eval_pred(self, pred, qmfData):
- """
- Evaluate the predicate expression against a QmfData object.
- """
- if not isinstance(qmfData, QmfData):
- raise TypeError("Query expects to evaluate QmfData types.")
-
- if not isinstance(pred, type([])):
- log_query.warning("Invalid type for predicate expression: '%s'" % str(pred))
- return False
-
- # empty predicate - match all???
- if len(pred) == 0:
- return True
-
- oper = pred[0]
- if oper == QmfQuery.TRUE:
- log_query.debug("query evaluate TRUE")
- return True
-
- if oper == QmfQuery.FALSE:
- log_query.debug("query evaluate FALSE")
- return False
-
- if oper == QmfQuery.AND:
- log_query.debug("query evaluate AND: '%s'" % str(pred))
- for exp in pred[1:]:
- if not self._eval_pred(exp, qmfData):
- log_query.debug("---> False")
- return False
- log_query.debug("---> True")
- return True
-
- if oper == QmfQuery.OR:
- log_query.debug("query evaluate OR: [%s]" % str(pred))
- for exp in pred[1:]:
- if self._eval_pred(exp, qmfData):
- log_query.debug("---> True")
- return True
- log_query.debug("---> False")
- return False
-
- if oper == QmfQuery.NOT:
- log_query.debug("query evaluate NOT: [%s]" % str(pred))
- for exp in pred[1:]:
- if self._eval_pred(exp, qmfData):
- log_query.debug("---> False")
- return False
- log_query.debug("---> True")
- return True
-
- if oper == QmfQuery.EXISTS:
- if len(pred) != 2:
- log_query.warning("Malformed query: 'exists' operator"
- " - bad arguments '%s'" % str(pred))
- return False
- ### Q: Should we assume "quote", or should it be explicit?
- ### "foo" or ["quote" "foo"]
- ### my guess is "explicit"
- log_query.debug("query evaluate EXISTS: [%s]" % str(pred))
- try:
- arg = self._fetch_pred_arg(pred[1], qmfData)
- except AttributeError:
- log_query.debug("query parameter not found: '%s'" % str(pred))
- return False
- v = qmfData.has_value(arg)
- log_query.debug("---> %s" % str(v))
- return v
-
- # binary operators
- if oper in [QmfQuery.EQ, QmfQuery.NE, QmfQuery.LT,
- QmfQuery.LE, QmfQuery.GT, QmfQuery.GE,
- QmfQuery.RE_MATCH]:
- if len(pred) != 3:
- log_query.warning("Malformed query: '%s' operator"
- " - requires 2 arguments '%s'" %
- (oper, str(pred)))
- return False
- # @todo: support regular expression match
- log_query.debug("query evaluate binary op: [%s]" % str(pred))
- try:
- arg1 = self._fetch_pred_arg(pred[1], qmfData)
- arg2 = self._fetch_pred_arg(pred[2], qmfData)
- except AttributeError:
- log_query.debug("query parameter not found: '%s'" % str(pred))
- return False
- log_query.debug("query evaluate %s: %s, %s" % (oper, str(arg1), str(arg2)))
- v = False
- try:
- if oper == QmfQuery.EQ: v = arg1 == arg2
- elif oper == QmfQuery.NE: v = arg1 != arg2
- elif oper == QmfQuery.LT: v = arg1 < arg2
- elif oper == QmfQuery.LE: v = arg1 <= arg2
- elif oper == QmfQuery.GT: v = arg1 > arg2
- elif oper == QmfQuery.GE: v = arg1 >= arg2
- except TypeError:
- log_query.warning("query comparison failed: '%s'" % str(pred))
- log_query.debug("---> %s" % str(v))
- return v
-
- log_query.warning("Unrecognized query operator: [%s]" % str(pred[0]))
- return False
-
- def _fetch_pred_arg(self, arg, qmfData):
- """
- Determine the value of a predicate argument by evaluating quoted
- arguments.
- """
- if isinstance(arg, basestring):
- return qmfData.get_value(arg)
- if isinstance(arg, type([])) and len(arg) == 2:
- if arg[0] == QmfQuery.QUOTE:
- return arg[1]
- if arg[0] == QmfQuery.UNQUOTE:
- return qmfData.get_value(arg[1])
- return arg
-
- def __repr__(self):
- return "QmfQuery=<<" + str(self.map_encode()) + ">>"
-
-
-
-
-
-##==============================================================================
-## SCHEMA
-##==============================================================================
-
-
-# Argument typecodes, access, and direction qualifiers
-
-class qmfTypes(object):
- TYPE_UINT8 = 1
- TYPE_UINT16 = 2
- TYPE_UINT32 = 3
- TYPE_UINT64 = 4
-
- TYPE_SSTR = 6
- TYPE_LSTR = 7
-
- TYPE_ABSTIME = 8
- TYPE_DELTATIME = 9
-
- TYPE_REF = 10
-
- TYPE_BOOL = 11
-
- TYPE_FLOAT = 12
- TYPE_DOUBLE = 13
-
- TYPE_UUID = 14
-
- TYPE_MAP = 15
-
- TYPE_INT8 = 16
- TYPE_INT16 = 17
- TYPE_INT32 = 18
- TYPE_INT64 = 19
-
- TYPE_OBJECT = 20
-
- TYPE_LIST = 21
-
- TYPE_ARRAY = 22
-
-# New subtypes:
-# integer (for time, duration, signed/unsigned)
-# double (float)
-# bool
-# string
-# map (ref, qmfdata)
-# list
-# uuid
-
-
-class qmfAccess(object):
- READ_CREATE = 1
- READ_WRITE = 2
- READ_ONLY = 3
-
-
-class qmfDirection(object):
- DIR_IN = 1
- DIR_OUT = 2
- DIR_IN_OUT = 3
-
-
-
-def _to_bool( param ):
- """
- Helper routine to convert human-readable representations of
- boolean values to python bool types.
- """
- _false_strings = ["off", "no", "false", "0", "none"]
- _true_strings = ["on", "yes", "true", "1"]
- if type(param) == str:
- lparam = param.lower()
- if lparam in _false_strings:
- return False
- if lparam in _true_strings:
- return True
- raise TypeError("unrecognized boolean string: '%s'" % param )
- else:
- return bool(param)
-
-
-
-class SchemaClassId(_mapEncoder):
- """
- Unique identifier for an instance of a SchemaClass.
-
- Map format:
- map["package_name"] = str, name of associated package
- map["class_name"] = str, name of associated class
- map["type"] = str, "data"|"event", default: "data"
- optional:
- map["hash_str"] = str, hash value in standard format or None
- if hash is unknown.
- """
- KEY_PACKAGE="_package_name"
- KEY_CLASS="_class_name"
- KEY_TYPE="_type"
- KEY_HASH="_hash_str"
-
- TYPE_DATA = "_data"
- TYPE_EVENT = "_event"
-
- _valid_types=[TYPE_DATA, TYPE_EVENT]
- _schemaHashStrFormat = "%08x-%08x-%08x-%08x"
- _schemaHashStrDefault = "00000000-00000000-00000000-00000000"
-
- def __init__(self, pname=None, cname=None, stype=TYPE_DATA, hstr=None,
- _map=None):
- """
- @type pname: str
- @param pname: the name of the class's package
- @type cname: str
- @param cname: name of the class
- @type stype: str
- @param stype: schema type [data | event]
- @type hstr: str
- @param hstr: the hash value in '%08x-%08x-%08x-%08x' format
- """
- if _map is not None:
- # construct from map
- pname = _map.get(self.KEY_PACKAGE, pname)
- cname = _map.get(self.KEY_CLASS, cname)
- stype = _map.get(self.KEY_TYPE, stype)
- hstr = _map.get(self.KEY_HASH, hstr)
-
- self._pname = pname
- self._cname = cname
- if stype not in SchemaClassId._valid_types:
- raise TypeError("Invalid SchemaClassId type: '%s'" % stype)
- self._type = stype
- self._hstr = hstr
- if self._hstr:
- try:
- # sanity check the format of the hash string
- hexValues = hstr.split("-")
- h0 = int(hexValues[0], 16)
- h1 = int(hexValues[1], 16)
- h2 = int(hexValues[2], 16)
- h3 = int(hexValues[3], 16)
- except:
- raise Exception("Invalid SchemaClassId format: bad hash string: '%s':"
- % hstr)
- # constructor
- def _create(cls, pname, cname, stype=TYPE_DATA, hstr=None):
- return cls(pname=pname, cname=cname, stype=stype, hstr=hstr)
- create = classmethod(_create)
-
- # map constructor
- def _from_map(cls, map_):
- return cls(_map=map_)
- from_map = classmethod(_from_map)
-
- def get_package_name(self):
- """
- Access the package name in the SchemaClassId.
-
- @rtype: str
- """
- return self._pname
-
-
- def get_class_name(self):
- """
- Access the class name in the SchemaClassId
-
- @rtype: str
- """
- return self._cname
-
-
- def get_hash_string(self):
- """
- Access the schema's hash as a string value
-
- @rtype: str
- """
- return self._hstr
-
-
- def get_type(self):
- """
- Returns the type code associated with this Schema
-
- @rtype: str
- """
- return self._type
-
- def map_encode(self):
- _map = {}
- _map[self.KEY_PACKAGE] = self._pname
- _map[self.KEY_CLASS] = self._cname
- _map[self.KEY_TYPE] = self._type
- if self._hstr: _map[self.KEY_HASH] = self._hstr
- return _map
-
- def __repr__(self):
- hstr = self.get_hash_string()
- if not hstr:
- hstr = SchemaClassId._schemaHashStrDefault
- return self._pname + ":" + self._cname + ":" + self._type + "(" + hstr + ")"
-
-
- def __cmp__(self, other):
- if isinstance(other, dict):
- other = SchemaClassId.from_map(other)
- if not isinstance(other, SchemaClassId):
- raise TypeError("Invalid types for compare")
- # return 1
- me = str(self)
- them = str(other)
- if me < them:
- return -1
- if me > them:
- return 1
- return 0
-
-
- def __hash__(self):
- return (self._pname, self._cname, self._hstr).__hash__()
-
-
-
-class SchemaProperty(_mapEncoder):
- """
- Describes the structure of a Property data object.
- Map format:
- map["amqp_type"] = int, AMQP type code indicating property's data type
-
- optional:
- map["access"] = str, access allowed to this property, default "RO"
- map["index"] = bool, True if this property is an index value, default False
- map["optional"] = bool, True if this property is optional, default False
- map["unit"] = str, describes units used
- map["min"] = int, minimum allowed value
- map["max"] = int, maximun allowed value
- map["maxlen"] = int, if string type, this is the maximum length in bytes
- required to represent the longest instance of this string.
- map["desc"] = str, human-readable description of this argument
- map["reference"] = str, ???
- map["parent_ref"] = bool, true if this property references an object in
- which this object is in a child-parent relationship. Default False
- """
- __hash__ = None
- _access_strings = ["RO","RW","RC"]
- _dir_strings = ["I", "O", "IO"]
- def __init__(self, _type_code=None, _map=None, kwargs={}):
- if _map is not None:
- # construct from map
- _type_code = _map.get("amqp_type", _type_code)
- kwargs = _map
- if not _type_code:
- raise TypeError("SchemaProperty: amqp_type is a mandatory"
- " parameter")
-
- self._type = _type_code
- self._access = "RO"
- self._isIndex = False
- self._isOptional = False
- self._unit = None
- self._min = None
- self._max = None
- self._maxlen = None
- self._desc = None
- self._reference = None
- self._isParentRef = False
- self._dir = None
- self._default = None
-
- for key, value in kwargs.items():
- if key == "access":
- value = str(value).upper()
- if value not in self._access_strings:
- raise TypeError("invalid value for access parameter: '%s':" % value )
- self._access = value
- elif key == "index" : self._isIndex = _to_bool(value)
- elif key == "optional": self._isOptional = _to_bool(value)
- elif key == "unit" : self._unit = value
- elif key == "min" : self._min = value
- elif key == "max" : self._max = value
- elif key == "maxlen" : self._maxlen = value
- elif key == "desc" : self._desc = value
- elif key == "reference" : self._reference = value
- elif key == "parent_ref" : self._isParentRef = _to_bool(value)
- elif key == "dir":
- value = str(value).upper()
- if value not in self._dir_strings:
- raise TypeError("invalid value for direction parameter: '%s'" % value)
- self._dir = value
- elif key == "default" : self._default = value
-
- # constructor
- def _create(cls, type_code, kwargs={}):
- return cls(_type_code=type_code, kwargs=kwargs)
- create = classmethod(_create)
-
- # map constructor
- def _from_map(cls, map_):
- return cls(_map=map_)
- from_map = classmethod(_from_map)
-
- def get_type(self): return self._type
-
- def get_access(self): return self._access
-
- def is_optional(self): return self._isOptional
-
- def is_index(self): return self._isIndex
-
- def get_unit(self): return self._unit
-
- def get_min(self): return self._min
-
- def get_max(self): return self._max
-
- def get_max_len(self): return self._maxlen
-
- def get_desc(self): return self._desc
-
- def get_reference(self): return self._reference
-
- def is_parent_ref(self): return self._isParentRef
-
- def get_direction(self): return self._dir
-
- def get_default(self): return self._default
-
- def map_encode(self):
- """
- Return the map encoding of this schema.
- """
- _map = {}
- _map["amqp_type"] = self._type
- _map["access"] = self._access
- _map["index"] = self._isIndex
- _map["optional"] = self._isOptional
- if self._unit: _map["unit"] = self._unit
- if self._min: _map["min"] = self._min
- if self._max: _map["max"] = self._max
- if self._maxlen: _map["maxlen"] = self._maxlen
- if self._desc: _map["desc"] = self._desc
- if self._reference: _map["reference"] = self._reference
- _map["parent_ref"] = self._isParentRef
- if self._dir: _map["dir"] = self._dir
- if self._default: _map["default"] = self._default
- return _map
-
- def __repr__(self):
- return "SchemaProperty=<<" + str(self.map_encode()) + ">>"
-
- def _update_hash(self, hasher):
- """
- Update the given hash object with a hash computed over this schema.
- """
- hasher.update(str(self._type))
- hasher.update(str(self._isIndex))
- hasher.update(str(self._isOptional))
- if self._access: hasher.update(self._access)
- if self._unit: hasher.update(self._unit)
- if self._desc: hasher.update(self._desc)
- if self._dir: hasher.update(self._dir)
- if self._default: hasher.update(self._default)
-
-
-
-class SchemaMethod(_mapEncoder):
- """
- The SchemaMethod class describes the method's structure, and contains a
- SchemaProperty class for each argument declared by the method.
-
- Map format:
- map["arguments"] = map of "name"=<SchemaProperty> pairs.
- map["desc"] = str, description of the method
- """
- KEY_NAME="_name"
- KEY_ARGUMENTS="_arguments"
- KEY_DESC="_desc"
- KEY_ERROR="_error"
- def __init__(self, _args={}, _desc=None, _map=None):
- """
- Construct a SchemaMethod.
-
- @type args: map of "name"=<SchemaProperty> objects
- @param args: describes the arguments accepted by the method
- @type _desc: str
- @param _desc: Human-readable description of the schema
- """
- if _map is not None:
- _desc = _map.get(self.KEY_DESC)
- margs = _map.get(self.KEY_ARGUMENTS)
- if margs:
- # margs are in map format - covert to SchemaProperty
- tmp_args = {}
- for name,val in margs.iteritems():
- tmp_args[name] = SchemaProperty.from_map(val)
- _args=tmp_args
-
- self._arguments = _args.copy()
- self._desc = _desc
-
- # map constructor
- def _from_map(cls, map_):
- return cls(_map=map_)
- from_map = classmethod(_from_map)
-
- def get_desc(self): return self._desc
-
- def get_arg_count(self): return len(self._arguments)
-
- def get_arguments(self): return self._arguments.copy()
-
- def get_argument(self, name): return self._arguments.get(name)
-
- def add_argument(self, name, schema):
- """
- Add an argument to the list of arguments passed to this method.
- Used by an agent for dynamically creating method schema.
-
- @type name: string
- @param name: name of new argument
- @type schema: SchemaProperty
- @param schema: SchemaProperty to add to this method
- """
- if not isinstance(schema, SchemaProperty):
- raise TypeError("argument must be a SchemaProperty class")
- # "Input" argument, by default
- if schema._dir is None:
- schema._dir = "I"
- self._arguments[name] = schema
-
- def map_encode(self):
- """
- Return the map encoding of this schema.
- """
- _map = {}
- _args = {}
- for name,val in self._arguments.iteritems():
- _args[name] = val.map_encode()
- _map[self.KEY_ARGUMENTS] = _args
- if self._desc: _map[self.KEY_DESC] = self._desc
- return _map
-
- def __repr__(self):
- result = "SchemaMethod=<<args=("
- first = True
- for name,arg in self._arguments.iteritems():
- if first:
- first = False
- else:
- result += ", "
- result += name
- result += ")>>"
- return result
-
- def _update_hash(self, hasher):
- """
- Update the given hash object with a hash computed over this schema.
- """
- for name,val in self._arguments.iteritems():
- hasher.update(name)
- val._update_hash(hasher)
- if self._desc: hasher.update(self._desc)
-
-
-
-class SchemaClass(QmfData):
- """
- Base class for Data and Event Schema classes.
-
- Map format:
- map(QmfData), plus:
- map["_schema_id"] = map representation of a SchemaClassId instance
- map["_primary_key_names"] = order list of primary key names
- """
- KEY_PRIMARY_KEY_NAMES="_primary_key_names"
- KEY_DESC = "_desc"
-
- SUBTYPE_PROPERTY="qmfProperty"
- SUBTYPE_METHOD="qmfMethod"
-
- def __init__(self, _classId=None, _desc=None, _map=None):
- """
- Schema Class constructor.
-
- @type classId: class SchemaClassId
- @param classId: Identifier for this SchemaClass
- @type _desc: str
- @param _desc: Human-readable description of the schema
- """
- if _map is not None:
- super(SchemaClass, self).__init__(_map=_map)
-
- # decode each value based on its type
- for name,value in self._values.iteritems():
- if self._subtypes.get(name) == self.SUBTYPE_METHOD:
- self._values[name] = SchemaMethod.from_map(value)
- else:
- self._values[name] = SchemaProperty.from_map(value)
- cid = _map.get(self.KEY_SCHEMA_ID)
- if cid:
- _classId = SchemaClassId.from_map(cid)
- self._object_id_names = _map.get(self.KEY_PRIMARY_KEY_NAMES,[])
- _desc = _map.get(self.KEY_DESC)
- else:
- if _classId is None:
- raise Exception("A class identifier must be supplied.")
- super(SchemaClass, self).__init__(_object_id=str(_classId))
- self._object_id_names = []
-
- self._classId = _classId
- self._desc = _desc
-
- def get_class_id(self):
- if not self._classId.get_hash_string():
- self.generate_hash()
- return self._classId
-
- def get_desc(self): return self._desc
-
- def generate_hash(self):
- """
- generate an md5 hash over the body of the schema,
- and return a string representation of the hash
- in format "%08x-%08x-%08x-%08x"
- """
- md5Hash = _md5Obj()
- md5Hash.update(self._classId.get_package_name())
- md5Hash.update(self._classId.get_class_name())
- md5Hash.update(self._classId.get_type())
- for name,x in self._values.iteritems():
- md5Hash.update(name)
- x._update_hash( md5Hash )
- for name,value in self._subtypes.iteritems():
- md5Hash.update(name)
- md5Hash.update(value)
- idx = 0
- for name in self._object_id_names:
- md5Hash.update(str(idx) + name)
- idx += 1
- hstr = md5Hash.hexdigest()[0:8] + "-" +\
- md5Hash.hexdigest()[8:16] + "-" +\
- md5Hash.hexdigest()[16:24] + "-" +\
- md5Hash.hexdigest()[24:32]
- # update classId with new hash value
- self._classId._hstr = hstr
- return hstr
-
-
- def get_property_count(self):
- count = 0
- for value in self._subtypes.itervalues():
- if value == self.SUBTYPE_PROPERTY:
- count += 1
- return count
-
- def get_properties(self):
- props = {}
- for name,value in self._subtypes.iteritems():
- if value == self.SUBTYPE_PROPERTY:
- props[name] = self._values.get(name)
- return props
-
- def get_property(self, name):
- if self._subtypes.get(name) == self.SUBTYPE_PROPERTY:
- return self._values.get(name)
- return None
-
- def add_property(self, name, prop):
- self.set_value(name, prop, self.SUBTYPE_PROPERTY)
- # need to re-generate schema hash
- self._classId._hstr = None
-
- def get_value(self, name):
- # check for meta-properties first
- if name == SchemaClassId.KEY_PACKAGE:
- return self._classId.get_package_name()
- if name == SchemaClassId.KEY_CLASS:
- return self._classId.get_class_name()
- if name == SchemaClassId.KEY_TYPE:
- return self._classId.get_type()
- if name == SchemaClassId.KEY_HASH:
- return self.get_class_id().get_hash_string()
- if name == self.KEY_SCHEMA_ID:
- return self.get_class_id()
- if name == self.KEY_PRIMARY_KEY_NAMES:
- return self._object_id_names[:]
- return super(SchemaClass, self).get_value(name)
-
- def has_value(self, name):
- if name in [SchemaClassId.KEY_PACKAGE, SchemaClassId.KEY_CLASS, SchemaClassId.KEY_TYPE,
- SchemaClassId.KEY_HASH, self.KEY_SCHEMA_ID, self.KEY_PRIMARY_KEY_NAMES]:
- return True
- super(SchemaClass, self).has_value(name)
-
- def map_encode(self):
- """
- Return the map encoding of this schema.
- """
- _map = super(SchemaClass,self).map_encode()
- _map[self.KEY_SCHEMA_ID] = self.get_class_id().map_encode()
- if self._object_id_names:
- _map[self.KEY_PRIMARY_KEY_NAMES] = self._object_id_names[:]
- if self._desc:
- _map[self.KEY_DESC] = self._desc
- return _map
-
- def __repr__(self):
- return str(self.get_class_id())
-
-
-
-class SchemaObjectClass(SchemaClass):
- """
- A schema class that describes a data object. The data object is composed
- of zero or more properties and methods. An instance of the SchemaObjectClass
- can be identified using a key generated by concantenating the values of
- all properties named in the primary key list.
-
- Map format:
- map(SchemaClass)
- """
- def __init__(self, _classId=None, _desc=None,
- _props={}, _methods={}, _object_id_names=[],
- _map=None):
- """
- @type pname: str
- @param pname: name of package this schema belongs to
- @type cname: str
- @param cname: class name for this schema
- @type desc: str
- @param desc: Human-readable description of the schema
- @type _hash: str
- @param _methods: hash computed on the body of this schema, if known
- @type _props: map of 'name':<SchemaProperty> objects
- @param _props: all properties provided by this schema
- @type _pkey: list of strings
- @param _pkey: names of each property to be used for constructing the primary key
- @type _methods: map of 'name':<SchemaMethod> objects
- @param _methods: all methods provided by this schema
- """
- if _map is not None:
- super(SchemaObjectClass,self).__init__(_map=_map)
- else:
- super(SchemaObjectClass, self).__init__(_classId=_classId, _desc=_desc)
- self._object_id_names = _object_id_names
- for name,value in _props.iteritems():
- self.set_value(name, value, self.SUBTYPE_PROPERTY)
- for name,value in _methods.iteritems():
- self.set_value(name, value, self.SUBTYPE_METHOD)
-
- if self._classId.get_type() != SchemaClassId.TYPE_DATA:
- raise TypeError("Invalid ClassId type for data schema: %s" % self._classId)
-
- # map constructor
- def __from_map(cls, map_):
- return cls(_map=map_)
- from_map = classmethod(__from_map)
-
- def get_id_names(self):
- return self._object_id_names[:]
-
- def get_method_count(self):
- count = 0
- for value in self._subtypes.itervalues():
- if value == self.SUBTYPE_METHOD:
- count += 1
- return count
-
- def get_methods(self):
- meths = {}
- for name,value in self._subtypes.iteritems():
- if value == self.SUBTYPE_METHOD:
- meths[name] = self._values.get(name)
- return meths
-
- def get_method(self, name):
- if self._subtypes.get(name) == self.SUBTYPE_METHOD:
- return self._values.get(name)
- return None
-
- def add_method(self, name, method):
- self.set_value(name, method, self.SUBTYPE_METHOD)
- # need to re-generate schema hash
- self._classId._hstr = None
-
-
-
-
-class SchemaEventClass(SchemaClass):
- """
- A schema class that describes an event. The event is composed
- of zero or more properties.
-
- Map format:
- map["schema_id"] = map, SchemaClassId map for this object.
- map["desc"] = string description of this schema
- map["properties"] = map of "name":SchemaProperty values.
- """
- def __init__(self, _classId=None, _desc=None, _props={},
- _map=None):
- if _map is not None:
- super(SchemaEventClass,self).__init__(_map=_map)
- else:
- super(SchemaEventClass, self).__init__(_classId=_classId,
- _desc=_desc)
- for name,value in _props.iteritems():
- self.set_value(name, value, self.SUBTYPE_PROPERTY)
-
- if self._classId.get_type() != SchemaClassId.TYPE_EVENT:
- raise TypeError("Invalid ClassId type for event schema: %s" %
- self._classId)
-
- # map constructor
- def __from_map(cls, map_):
- return cls(_map=map_)
- from_map = classmethod(__from_map)
-
diff --git a/python/qmf2/console.py b/python/qmf2/console.py
deleted file mode 100644
index c13cf70755..0000000000
--- a/python/qmf2/console.py
+++ /dev/null
@@ -1,2295 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-import sys
-import os
-import logging
-import platform
-import time
-import datetime
-import Queue
-from threading import Thread, Event
-from threading import Lock
-from threading import currentThread
-from threading import Condition
-
-from qpid.messaging import Connection, Message, Empty, SendError
-
-from common import (make_subject, parse_subject, OpCode, QmfQuery, Notifier,
- MsgKey, QmfData, QmfAddress, SchemaClass, SchemaClassId,
- SchemaEventClass, SchemaObjectClass, WorkItem,
- SchemaMethod, QmfEvent, timedelta_to_secs)
-
-
-# global flag that indicates which thread (if any) is
-# running the console notifier callback
-_callback_thread=None
-
-
-
-
-##==============================================================================
-## Console Transaction Management
-##
-## At any given time, a console application may have multiple outstanding
-## message transactions with agents. The following objects allow the console
-## to track these outstanding transactions.
-##==============================================================================
-
-
-class _Mailbox(object):
- """
- Virtual base class for all Mailbox-like objects.
- """
- def __init__(self, console):
- self.console = console
- self.cid = 0
- self.console._add_mailbox(self)
-
- def get_address(self):
- return self.cid
-
- def deliver(self, data):
- """
- Invoked by Console Management thread when a message arrives for
- this mailbox.
- """
- raise Exception("_Mailbox deliver() method must be provided")
-
- def destroy(self):
- """
- Release the mailbox. Once called, the mailbox should no longer be
- referenced.
- """
- self.console._remove_mailbox(self.cid)
-
-
-class _SyncMailbox(_Mailbox):
- """
- A simple mailbox that allows a consumer to wait for delivery of data.
- """
- def __init__(self, console):
- """
- Invoked by application thread.
- """
- super(_SyncMailbox, self).__init__(console)
- self._cv = Condition()
- self._data = []
- self._waiting = False
-
- def deliver(self, data):
- """
- Drop data into the mailbox, waking any waiters if necessary.
- Invoked by Console Management thread only.
- """
- self._cv.acquire()
- try:
- self._data.append(data)
- # if was empty, notify waiters
- if len(self._data) == 1:
- self._cv.notify()
- finally:
- self._cv.release()
-
- def fetch(self, timeout=None):
- """
- Get one data item from a mailbox, with timeout.
- Invoked by application thread.
- """
- self._cv.acquire()
- try:
- if len(self._data) == 0:
- self._cv.wait(timeout)
- if len(self._data):
- return self._data.pop(0)
- return None
- finally:
- self._cv.release()
-
-
-class _AsyncMailbox(_Mailbox):
- """
- A Mailbox for asynchronous delivery, with a timeout value.
- """
- def __init__(self, console,
- _timeout=None):
- """
- Invoked by application thread.
- """
- super(_AsyncMailbox, self).__init__(console)
- self.console = console
-
- if _timeout is None:
- _timeout = console._reply_timeout
- self.expiration_date = (datetime.datetime.utcnow() +
- datetime.timedelta(seconds=_timeout))
- console._lock.acquire()
- try:
- console._async_mboxes[self.cid] = self
- finally:
- console._lock.release()
-
- # now that an async mbox has been created, wake the
- # console mgmt thread so it will know about the mbox expiration
- # date (and adjust its idle sleep period correctly)
-
- console._wake_thread()
-
- def deliver(self, msg):
- """
- """
- raise Exception("deliver() method must be provided")
-
- def expire(self):
- raise Exception("expire() method must be provided")
-
-
- def destroy(self):
- self.console._lock.acquire()
- try:
- if self.cid in self.console._async_mboxes:
- del self.console._async_mboxes[self.cid]
- finally:
- self.console._lock.release()
- super(_AsyncMailbox, self).destroy()
-
-
-
-class _QueryMailbox(_AsyncMailbox):
- """
- A mailbox used for asynchronous query requests.
- """
- def __init__(self, console,
- agent_name,
- context,
- target, msgkey,
- _timeout=None):
- """
- Invoked by application thread.
- """
- super(_QueryMailbox, self).__init__(console,
- _timeout)
- self.agent_name = agent_name
- self.target = target
- self.msgkey = msgkey
- self.context = context
- self.result = []
-
- def deliver(self, reply):
- """
- Process query response messages delivered to this mailbox.
- Invoked by Console Management thread only.
- """
- done = False
- objects = reply.content.get(self.msgkey)
- if not objects:
- done = True
- else:
- # convert from map to native types if needed
- if self.target == QmfQuery.TARGET_SCHEMA_ID:
- for sid_map in objects:
- self.result.append(SchemaClassId.from_map(sid_map))
-
- elif self.target == QmfQuery.TARGET_SCHEMA:
- for schema_map in objects:
- # extract schema id, convert based on schema type
- sid_map = schema_map.get(SchemaClass.KEY_SCHEMA_ID)
- if sid_map:
- sid = SchemaClassId.from_map(sid_map)
- if sid:
- if sid.get_type() == SchemaClassId.TYPE_DATA:
- schema = SchemaObjectClass.from_map(schema_map)
- else:
- schema = SchemaEventClass.from_map(schema_map)
- self.console._add_schema(schema) # add to schema cache
- self.result.append(schema)
-
- elif self.target == QmfQuery.TARGET_OBJECT:
- for obj_map in objects:
- # @todo: need the agent name - ideally from the
- # reply message iself.
- agent = self.console.get_agent(self.agent_name)
- if agent:
- obj = QmfConsoleData(map_=obj_map, agent=agent)
- # start fetch of schema if not known
- sid = obj.get_schema_class_id()
- if sid:
- self.console._prefetch_schema(sid, agent)
- self.result.append(obj)
-
-
- else:
- # no conversion needed.
- self.result += objects
-
- if done:
- # create workitem
- # logging.error("QUERY COMPLETE for %s" % str(self.context))
- wi = WorkItem(WorkItem.QUERY_COMPLETE, self.context, self.result)
- self.console._work_q.put(wi)
- self.console._work_q_put = True
-
- self.destroy()
-
-
- def expire(self):
- logging.debug("ASYNC MAILBOX EXPIRED @ %s!!!" %
- datetime.datetime.utcnow())
- # send along whatever (possibly none) has been received so far
- wi = WorkItem(WorkItem.QUERY_COMPLETE, self.context, self.result)
- self.console._work_q.put(wi)
- self.console._work_q_put = True
-
- self.destroy()
-
-
-
-class _SchemaPrefetchMailbox(_AsyncMailbox):
- """
- Handles responses to schema fetches made by the console.
- """
- def __init__(self, console,
- schema_id,
- _timeout=None):
- """
- Invoked by application thread.
- """
- super(_SchemaPrefetchMailbox, self).__init__(console,
- _timeout)
- self.schema_id = schema_id
-
- def deliver(self, reply):
- """
- Process schema response messages.
- """
- done = False
- schemas = reply.content.get(MsgKey.schema)
- if schemas:
- for schema_map in schemas:
- # extract schema id, convert based on schema type
- sid_map = schema_map.get(SchemaClass.KEY_SCHEMA_ID)
- if sid_map:
- sid = SchemaClassId.from_map(sid_map)
- if sid:
- if sid.get_type() == SchemaClassId.TYPE_DATA:
- schema = SchemaObjectClass.from_map(schema_map)
- else:
- schema = SchemaEventClass.from_map(schema_map)
- self.console._add_schema(schema) # add to schema cache
- self.destroy()
-
-
- def expire(self):
- self.destroy()
-
-
-
-class _MethodMailbox(_AsyncMailbox):
- """
- A mailbox used for asynchronous method requests.
- """
- def __init__(self, console,
- context,
- _timeout=None):
- """
- Invoked by application thread.
- """
- super(_MethodMailbox, self).__init__(console,
- _timeout)
- self.context = context
-
- def deliver(self, reply):
- """
- Process method response messages delivered to this mailbox.
- Invoked by Console Management thread only.
- """
-
- _map = reply.content.get(MsgKey.method)
- if not _map:
- logging.error("Invalid method call reply message")
- result = None
- else:
- error=_map.get(SchemaMethod.KEY_ERROR)
- if error:
- error = QmfData.from_map(error)
- result = MethodResult(_error=error)
- else:
- result = MethodResult(_out_args=_map.get(SchemaMethod.KEY_ARGUMENTS))
-
- # create workitem
- wi = WorkItem(WorkItem.METHOD_RESPONSE, self.context, result)
- self.console._work_q.put(wi)
- self.console._work_q_put = True
-
- self.destroy()
-
-
- def expire(self):
- """
- The mailbox expired without receiving a reply.
- Invoked by the Console Management thread only.
- """
- logging.debug("ASYNC MAILBOX EXPIRED @ %s!!!" %
- datetime.datetime.utcnow())
- # send along an empty response
- wi = WorkItem(WorkItem.METHOD_RESPONSE, self.context, None)
- self.console._work_q.put(wi)
- self.console._work_q_put = True
-
- self.destroy()
-
-
-
-##==============================================================================
-## DATA MODEL
-##==============================================================================
-
-
-class QmfConsoleData(QmfData):
- """
- Console's representation of an managed QmfData instance.
- """
- def __init__(self, map_, agent):
- super(QmfConsoleData, self).__init__(_map=map_,
- _const=True)
- self._agent = agent
-
- def get_timestamps(self):
- """
- Returns a list of timestamps describing the lifecycle of
- the object. All timestamps are represented by the AMQP
- timestamp type. [0] = time of last update from Agent,
- [1] = creation timestamp
- [2] = deletion timestamp, or zero if not
- deleted.
- """
- return [self._utime, self._ctime, self._dtime]
-
- def get_create_time(self):
- """
- returns the creation timestamp
- """
- return self._ctime
-
- def get_update_time(self):
- """
- returns the update timestamp
- """
- return self._utime
-
- def get_delete_time(self):
- """
- returns the deletion timestamp, or zero if not yet deleted.
- """
- return self._dtime
-
- def is_deleted(self):
- """
- True if deletion timestamp not zero.
- """
- return self._dtime != long(0)
-
- def refresh(self, _reply_handle=None, _timeout=None):
- """
- request that the Agent update the value of this object's
- contents.
- """
- if _reply_handle is not None:
- logging.error(" ASYNC REFRESH TBD!!!")
- return None
-
- assert self._agent
- assert self._agent._console
-
- if _timeout is None:
- _timeout = self._agent._console._reply_timeout
-
- # create query to agent using this objects ID
- query = QmfQuery.create_id_object(self.get_object_id(),
- self.get_schema_class_id())
- obj_list = self._agent._console.do_query(self._agent, query,
- _timeout=_timeout)
- if obj_list is None or len(obj_list) != 1:
- return None
-
- self._update(obj_list[0])
- return self
-
-
- def invoke_method(self, name, _in_args={}, _reply_handle=None,
- _timeout=None):
- """
- Invoke the named method on this object.
- """
- assert self._agent
- assert self._agent._console
-
- oid = self.get_object_id()
- if oid is None:
- raise ValueError("Cannot invoke methods on unmanaged objects.")
-
- if _timeout is None:
- _timeout = self._agent._console._reply_timeout
-
- if _reply_handle is not None:
- mbox = _MethodMailbox(self._agent._console,
- _reply_handle)
- else:
- mbox = _SyncMailbox(self._agent._console)
- cid = mbox.get_address()
-
- _map = {self.KEY_OBJECT_ID:str(oid),
- SchemaMethod.KEY_NAME:name}
-
- sid = self.get_schema_class_id()
- if sid:
- _map[self.KEY_SCHEMA_ID] = sid.map_encode()
- if _in_args:
- _map[SchemaMethod.KEY_ARGUMENTS] = _in_args
-
- logging.debug("Sending method req to Agent (%s)" % time.time())
- try:
- self._agent._send_method_req(_map, cid)
- except SendError, e:
- logging.error(str(e))
- mbox.destroy()
- return None
-
- if _reply_handle is not None:
- return True
-
- logging.debug("Waiting for response to method req (%s)" % _timeout)
- replyMsg = mbox.fetch(_timeout)
- mbox.destroy()
-
- if not replyMsg:
- logging.debug("Agent method req wait timed-out.")
- return None
-
- _map = replyMsg.content.get(MsgKey.method)
- if not _map:
- logging.error("Invalid method call reply message")
- return None
-
- error=_map.get(SchemaMethod.KEY_ERROR)
- if error:
- return MethodResult(_error=QmfData.from_map(error))
- else:
- return MethodResult(_out_args=_map.get(SchemaMethod.KEY_ARGUMENTS))
-
- def _update(self, newer):
- super(QmfConsoleData,self).__init__(_values=newer._values, _subtypes=newer._subtypes,
- _tag=newer._tag, _object_id=newer._object_id,
- _ctime=newer._ctime, _utime=newer._utime,
- _dtime=newer._dtime,
- _schema_id=newer._schema_id, _const=True)
-
-class QmfLocalData(QmfData):
- """
- Console's representation of an unmanaged QmfData instance. There
- is no remote agent associated with this instance. The Console has
- full control over this instance.
- """
- def __init__(self, values, _subtypes={}, _tag=None, _object_id=None,
- _schema=None):
- # timestamp in millisec since epoch UTC
- ctime = long(time.time() * 1000)
- super(QmfLocalData, self).__init__(_values=values,
- _subtypes=_subtypes, _tag=_tag,
- _object_id=_object_id,
- _schema=_schema, _ctime=ctime,
- _utime=ctime, _const=False)
-
-
-class Agent(object):
- """
- A local representation of a remote agent managed by this console.
- """
- def __init__(self, name, console):
- """
- @type name: string
- @param name: uniquely identifies this agent in the AMQP domain.
- """
-
- if not isinstance(console, Console):
- raise TypeError("parameter must be an instance of class Console")
-
- self._name = name
- self._address = QmfAddress.direct(name, console._domain)
- self._console = console
- self._sender = None
- self._packages = {} # map of {package-name:[list of class-names], } for this agent
- self._subscriptions = [] # list of active standing subscriptions for this agent
- self._announce_timestamp = None # datetime when last announce received
- logging.debug( "Created Agent with address: [%s]" % self._address )
-
-
- def get_name(self):
- return self._name
-
- def is_active(self):
- return self._announce_timestamp != None
-
- def _send_msg(self, msg, correlation_id=None):
- """
- Low-level routine to asynchronously send a message to this agent.
- """
- msg.reply_to = str(self._console._address)
- if correlation_id:
- msg.correlation_id = str(correlation_id)
- # TRACE
- #logging.error("!!! Console %s sending to agent %s (%s)" %
- # (self._console._name, self._name, str(msg)))
- self._sender.send(msg)
- # return handle
-
- def get_packages(self):
- """
- Return a list of the names of all packages known to this agent.
- """
- return self._packages.keys()
-
- def get_classes(self):
- """
- Return a dictionary [key:class] of classes known to this agent.
- """
- return self._packages.copy()
-
- def get_objects(self, query, kwargs={}):
- """
- Return a list of objects that satisfy the given query.
-
- @type query: dict, or common.Query
- @param query: filter for requested objects
- @type kwargs: dict
- @param kwargs: ??? used to build match selector and query ???
- @rtype: list
- @return: list of matching objects, or None.
- """
- pass
-
- def get_object(self, query, kwargs={}):
- """
- Get one object - query is expected to match only one object.
- ??? Recommended: explicit timeout param, default None ???
-
- @type query: dict, or common.Query
- @param query: filter for requested objects
- @type kwargs: dict
- @param kwargs: ??? used to build match selector and query ???
- @rtype: qmfConsole.ObjectProxy
- @return: one matching object, or none
- """
- pass
-
-
- def create_subscription(self, query):
- """
- Factory for creating standing subscriptions based on a given query.
-
- @type query: common.Query object
- @param query: determines the list of objects for which this subscription applies
- @rtype: qmfConsole.Subscription
- @returns: an object representing the standing subscription.
- """
- pass
-
-
- def invoke_method(self, name, _in_args={}, _reply_handle=None,
- _timeout=None):
- """
- Invoke the named method on this agent.
- """
- assert self._console
-
- if _timeout is None:
- _timeout = self._console._reply_timeout
-
- if _reply_handle is not None:
- mbox = _MethodMailbox(self._console,
- _reply_handle)
- else:
- mbox = _SyncMailbox(self._console)
- cid = mbox.get_address()
-
- _map = {SchemaMethod.KEY_NAME:name}
- if _in_args:
- _map[SchemaMethod.KEY_ARGUMENTS] = _in_args.copy()
-
- logging.debug("Sending method req to Agent (%s)" % time.time())
- try:
- self._send_method_req(_map, cid)
- except SendError, e:
- logging.error(str(e))
- mbox.destroy()
- return None
-
- if _reply_handle is not None:
- return True
-
- logging.debug("Waiting for response to method req (%s)" % _timeout)
- replyMsg = mbox.fetch(_timeout)
- mbox.destroy()
-
- if not replyMsg:
- logging.debug("Agent method req wait timed-out.")
- return None
-
- _map = replyMsg.content.get(MsgKey.method)
- if not _map:
- logging.error("Invalid method call reply message")
- return None
-
- return MethodResult(_out_args=_map.get(SchemaMethod.KEY_ARGUMENTS),
- _error=_map.get(SchemaMethod.KEY_ERROR))
-
- def enable_events(self):
- raise Exception("enable_events tbd")
-
- def disable_events(self):
- raise Exception("disable_events tbd")
-
- def destroy(self):
- raise Exception("destroy tbd")
-
- def __repr__(self):
- return str(self._address)
-
- def __str__(self):
- return self.__repr__()
-
- def _send_query(self, query, correlation_id=None):
- """
- """
- msg = Message(properties={"method":"request",
- "qmf.subject":make_subject(OpCode.get_query)},
- content={MsgKey.query: query.map_encode()})
- self._send_msg( msg, correlation_id )
-
-
- def _send_method_req(self, mr_map, correlation_id=None):
- """
- """
- msg = Message(properties={"method":"request",
- "qmf.subject":make_subject(OpCode.method_req)},
- content=mr_map)
- self._send_msg( msg, correlation_id )
-
-
- ##==============================================================================
- ## METHOD CALL
- ##==============================================================================
-
-class MethodResult(object):
- def __init__(self, _out_args=None, _error=None):
- self._error = _error
- self._out_args = _out_args
-
- def succeeded(self):
- return self._error is None
-
- def get_exception(self):
- return self._error
-
- def get_arguments(self):
- return self._out_args
-
- def get_argument(self, name):
- arg = None
- if self._out_args:
- arg = self._out_args.get(name)
- return arg
-
-
- ##==============================================================================
- ## CONSOLE
- ##==============================================================================
-
-
-
-
-
-
-class Console(Thread):
- """
- A Console manages communications to a collection of agents on behalf of an application.
- """
- def __init__(self, name=None, _domain=None, notifier=None,
- reply_timeout = 60,
- # agent_timeout = 120,
- agent_timeout = 60,
- kwargs={}):
- """
- @type name: str
- @param name: identifier for this console. Must be unique.
- @type notifier: qmfConsole.Notifier
- @param notifier: invoked when events arrive for processing.
- @type kwargs: dict
- @param kwargs: ??? Unused
- """
- Thread.__init__(self)
- self._operational = False
- self._ready = Event()
-
- if not name:
- self._name = "qmfc-%s.%d" % (platform.node(), os.getpid())
- else:
- self._name = str(name)
- self._domain = _domain
- self._address = QmfAddress.direct(self._name, self._domain)
- self._notifier = notifier
- self._lock = Lock()
- self._conn = None
- self._session = None
- # dict of "agent-direct-address":class Agent entries
- self._agent_map = {}
- self._direct_recvr = None
- self._announce_recvr = None
- self._locate_sender = None
- self._schema_cache = {}
- self._pending_schema_req = []
- self._agent_discovery_filter = None
- self._reply_timeout = reply_timeout
- self._agent_timeout = agent_timeout
- self._next_agent_expire = None
- self._next_mbox_expire = None
- # for passing WorkItems to the application
- self._work_q = Queue.Queue()
- self._work_q_put = False
- # Correlation ID and mailbox storage
- self._correlation_id = long(time.time()) # pseudo-randomize
- self._post_office = {} # indexed by cid
- self._async_mboxes = {} # indexed by cid, used to expire them
-
- ## Old stuff below???
- #self._broker_list = []
- #self.impl = qmfengine.Console()
- #self._event = qmfengine.ConsoleEvent()
- ##self._cv = Condition()
- ##self._sync_count = 0
- ##self._sync_result = None
- ##self._select = {}
- ##self._cb_cond = Condition()
-
-
-
- def destroy(self, timeout=None):
- """
- Must be called before the Console is deleted.
- Frees up all resources and shuts down all background threads.
-
- @type timeout: float
- @param timeout: maximum time in seconds to wait for all background threads to terminate. Default: forever.
- """
- logging.debug("Destroying Console...")
- if self._conn:
- self.remove_connection(self._conn, timeout)
- logging.debug("Console Destroyed")
-
-
-
- def add_connection(self, conn):
- """
- Add a AMQP connection to the console. The console will setup a session over the
- connection. The console will then broadcast an Agent Locate Indication over
- the session in order to discover present agents.
-
- @type conn: qpid.messaging.Connection
- @param conn: the connection to the AMQP messaging infrastructure.
- """
- if self._conn:
- raise Exception( "Multiple connections per Console not supported." );
- self._conn = conn
- self._session = conn.session(name=self._name)
-
- # for messages directly addressed to me
- self._direct_recvr = self._session.receiver(str(self._address) +
- ";{create:always,"
- " node-properties:"
- " {type:topic,"
- " x-properties:"
- " {type:direct}}}",
- capacity=1)
- logging.debug("my direct addr=%s" % self._direct_recvr.source)
-
- self._direct_sender = self._session.sender(str(self._address.get_node()) +
- ";{create:always,"
- " node-properties:"
- " {type:topic,"
- " x-properties:"
- " {type:direct}}}")
- logging.debug("my direct sender=%s" % self._direct_sender.target)
-
- # for receiving "broadcast" messages from agents
- default_addr = QmfAddress.topic(QmfAddress.SUBJECT_AGENT_IND + ".#",
- self._domain)
- self._topic_recvr = self._session.receiver(str(default_addr) +
- ";{create:always,"
- " node-properties:{type:topic}}",
- capacity=1)
- logging.debug("default topic recv addr=%s" % self._topic_recvr.source)
-
-
- # for sending to topic subscribers
- topic_addr = QmfAddress.topic(QmfAddress.SUBJECT_CONSOLE_IND, self._domain)
- self._topic_sender = self._session.sender(str(topic_addr) +
- ";{create:always,"
- " node-properties:{type:topic}}")
- logging.debug("default topic send addr=%s" % self._topic_sender.target)
-
- #
- # Now that receivers are created, fire off the receive thread...
- #
- self._operational = True
- self.start()
- self._ready.wait(10)
- if not self._ready.isSet():
- raise Exception("Console managment thread failed to start.")
-
-
-
- def remove_connection(self, conn, timeout=None):
- """
- Remove an AMQP connection from the console. Un-does the add_connection() operation,
- and releases any agents and sessions associated with the connection.
-
- @type conn: qpid.messaging.Connection
- @param conn: connection previously added by add_connection()
- """
- if self._conn and conn and conn != self._conn:
- logging.error( "Attempt to delete unknown connection: %s" % str(conn))
-
- # tell connection thread to shutdown
- self._operational = False
- if self.isAlive():
- # kick my thread to wake it up
- self._wake_thread()
- logging.debug("waiting for console receiver thread to exit")
- self.join(timeout)
- if self.isAlive():
- logging.error( "Console thread '%s' is hung..." % self.getName() )
- self._direct_recvr.close()
- self._direct_sender.close()
- self._topic_recvr.close()
- self._topic_sender.close()
- self._session.close()
- self._session = None
- self._conn = None
- logging.debug("console connection removal complete")
-
-
- def get_address(self):
- """
- The AMQP address this Console is listening to.
- """
- return self._address
-
-
- def destroy_agent( self, agent ):
- """
- Undoes create.
- """
- if not isinstance(agent, Agent):
- raise TypeError("agent must be an instance of class Agent")
-
- self._lock.acquire()
- try:
- if agent._name in self._agent_map:
- del self._agent_map[agent._name]
- finally:
- self._lock.release()
-
- def find_agent(self, name, timeout=None ):
- """
- Given the name of a particular agent, return an instance of class Agent
- representing that agent. Return None if the agent does not exist.
- """
-
- self._lock.acquire()
- try:
- agent = self._agent_map.get(name)
- if agent:
- return agent
- finally:
- self._lock.release()
-
- # agent not present yet - ping it with an agent_locate
-
- mbox = _SyncMailbox(self)
- cid = mbox.get_address()
-
- query = QmfQuery.create_id(QmfQuery.TARGET_AGENT, name)
- msg = Message(subject="console.ind.locate." + name,
- properties={"method":"request",
- "qmf.subject":make_subject(OpCode.agent_locate)},
- content={MsgKey.query: query.map_encode()})
- msg.reply_to = str(self._address)
- msg.correlation_id = str(cid)
- logging.debug("Sending Agent Locate (%s)" % time.time())
- # TRACE
- #logging.error("!!! Console %s sending agent locate (%s)" %
- # (self._name, str(msg)))
- try:
- self._topic_sender.send(msg)
- except SendError, e:
- logging.error(str(e))
- mbox.destroy()
- return None
-
- if timeout is None:
- timeout = self._reply_timeout
-
- new_agent = None
- logging.debug("Waiting for response to Agent Locate (%s)" % timeout)
- mbox.fetch(timeout)
- mbox.destroy()
- logging.debug("Agent Locate wait ended (%s)" % time.time())
- self._lock.acquire()
- try:
- new_agent = self._agent_map.get(name)
- finally:
- self._lock.release()
-
- return new_agent
-
-
- def get_agents(self):
- """
- Return the list of known agents.
- """
- self._lock.acquire()
- try:
- agents = self._agent_map.values()
- finally:
- self._lock.release()
- return agents
-
-
- def get_agent(self, name):
- """
- Return the named agent, else None if not currently available.
- """
- self._lock.acquire()
- try:
- agent = self._agent_map.get(name)
- finally:
- self._lock.release()
- return agent
-
-
- def do_query(self, agent, query, _reply_handle=None, _timeout=None ):
- """
- """
- query_keymap={QmfQuery.TARGET_PACKAGES: MsgKey.package_info,
- QmfQuery.TARGET_OBJECT_ID: MsgKey.object_id,
- QmfQuery.TARGET_SCHEMA_ID: MsgKey.schema_id,
- QmfQuery.TARGET_SCHEMA: MsgKey.schema,
- QmfQuery.TARGET_OBJECT: MsgKey.data_obj,
- QmfQuery.TARGET_AGENT: MsgKey.agent_info}
-
- target = query.get_target()
- msgkey = query_keymap.get(target)
- if not msgkey:
- raise Exception("Invalid target for query: %s" % str(query))
-
- if _reply_handle is not None:
- mbox = _QueryMailbox(self,
- agent.get_name(),
- _reply_handle,
- target, msgkey,
- _timeout)
- else:
- mbox = _SyncMailbox(self)
-
- cid = mbox.get_address()
-
- try:
- logging.debug("Sending Query to Agent (%s)" % time.time())
- agent._send_query(query, cid)
- except SendError, e:
- logging.error(str(e))
- mbox.destroy()
- return None
-
- # return now if async reply expected
- if _reply_handle is not None:
- return True
-
- if not _timeout:
- _timeout = self._reply_timeout
-
- logging.debug("Waiting for response to Query (%s)" % _timeout)
- now = datetime.datetime.utcnow()
- expire = now + datetime.timedelta(seconds=_timeout)
-
- response = []
- while (expire > now):
- _timeout = timedelta_to_secs(expire - now)
- reply = mbox.fetch(_timeout)
- if not reply:
- logging.debug("Query wait timed-out.")
- break
-
- objects = reply.content.get(msgkey)
- if not objects:
- # last response is empty
- break
-
- # convert from map to native types if needed
- if target == QmfQuery.TARGET_SCHEMA_ID:
- for sid_map in objects:
- response.append(SchemaClassId.from_map(sid_map))
-
- elif target == QmfQuery.TARGET_SCHEMA:
- for schema_map in objects:
- # extract schema id, convert based on schema type
- sid_map = schema_map.get(SchemaClass.KEY_SCHEMA_ID)
- if sid_map:
- sid = SchemaClassId.from_map(sid_map)
- if sid:
- if sid.get_type() == SchemaClassId.TYPE_DATA:
- schema = SchemaObjectClass.from_map(schema_map)
- else:
- schema = SchemaEventClass.from_map(schema_map)
- self._add_schema(schema) # add to schema cache
- response.append(schema)
-
- elif target == QmfQuery.TARGET_OBJECT:
- for obj_map in objects:
- obj = QmfConsoleData(map_=obj_map, agent=agent)
- # start fetch of schema if not known
- sid = obj.get_schema_class_id()
- if sid:
- self._prefetch_schema(sid, agent)
- response.append(obj)
- else:
- # no conversion needed.
- response += objects
-
- now = datetime.datetime.utcnow()
-
- mbox.destroy()
- return response
-
- def _wake_thread(self):
- """
- Make the console management thread loop wakeup from its next_receiver
- sleep.
- """
- logging.debug("Sending noop to wake up [%s]" % self._address)
- msg = Message(properties={"method":"request",
- "qmf.subject":make_subject(OpCode.noop)},
- subject=self._name,
- content={"noop":"noop"})
- try:
- self._direct_sender.send( msg, sync=True )
- except SendError, e:
- logging.error(str(e))
-
-
- def run(self):
- """
- Console Management Thread main loop.
- Handles inbound messages, agent discovery, async mailbox timeouts.
- """
- global _callback_thread
-
- self._ready.set()
-
- while self._operational:
-
- # qLen = self._work_q.qsize()
-
- while True:
- try:
- msg = self._topic_recvr.fetch(timeout=0)
- except Empty:
- break
- # TRACE:
- # logging.error("!!! Console %s: msg on %s [%s]" %
- # (self._name, self._topic_recvr.source, msg))
- self._dispatch(msg, _direct=False)
-
- while True:
- try:
- msg = self._direct_recvr.fetch(timeout = 0)
- except Empty:
- break
- # TRACE
- #logging.error("!!! Console %s: msg on %s [%s]" %
- # (self._name, self._direct_recvr.source, msg))
- self._dispatch(msg, _direct=True)
-
- self._expire_agents() # check for expired agents
- self._expire_mboxes() # check for expired async mailbox requests
-
- #if qLen == 0 and self._work_q.qsize() and self._notifier:
- if self._work_q_put and self._notifier:
- # new stuff on work queue, kick the the application...
- self._work_q_put = False
- _callback_thread = currentThread()
- logging.info("Calling console notifier.indication")
- self._notifier.indication()
- _callback_thread = None
-
- if self._operational:
- # wait for a message to arrive, or an agent
- # to expire, or a mailbox requrest to time out
- now = datetime.datetime.utcnow()
- next_expire = self._next_agent_expire
- if (self._next_mbox_expire and
- self._next_mbox_expire < next_expire):
- next_expire = self._next_mbox_expire
- if next_expire > now:
- timeout = timedelta_to_secs(next_expire - now)
- try:
- logging.debug("waiting for next rcvr (timeout=%s)..." % timeout)
- xxx = self._session.next_receiver(timeout = timeout)
- except Empty:
- pass
-
-
- logging.debug("Shutting down Console thread")
-
- def get_objects(self,
- _object_id=None,
- _schema_id=None,
- _pname=None, _cname=None,
- _agents=None,
- _timeout=None):
- """
- Retrieve objects by id or schema.
-
- By object_id: must specify schema_id or pname & cname if object defined
- by a schema. Undescribed objects: only object_id needed.
-
- By schema: must specify schema_id or pname & cname - all instances of
- objects defined by that schema are returned.
- """
- if _agents is None:
- # use copy of current agent list
- self._lock.acquire()
- try:
- agent_list = self._agent_map.values()
- finally:
- self._lock.release()
- elif isinstance(_agents, Agent):
- agent_list = [_agents]
- else:
- agent_list = _agents
- # @todo validate this list!
-
- if _timeout is None:
- _timeout = self._reply_timeout
-
- # @todo: fix when async do_query done - query all agents at once, then
- # wait for replies, instead of per-agent querying....
-
- obj_list = []
- expired = datetime.datetime.utcnow() + datetime.timedelta(seconds=_timeout)
- for agent in agent_list:
- if not agent.is_active():
- continue
- now = datetime.datetime.utcnow()
- if now >= expired:
- break
-
- if _pname is None:
- if _object_id:
- query = QmfQuery.create_id_object(_object_id,
- _schema_id)
- else:
- if _schema_id is not None:
- t_params = {QmfData.KEY_SCHEMA_ID: _schema_id}
- else:
- t_params = None
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT,
- t_params)
- timeout = timedelta_to_secs(expired - now)
- reply = self.do_query(agent, query, _timeout=timeout)
- if reply:
- obj_list = obj_list + reply
- else:
- # looking up by package name (and maybe class name), need to
- # find all schema_ids in that package, then lookup object by
- # schema_id
- if _cname is not None:
- pred = [QmfQuery.AND,
- [QmfQuery.EQ,
- SchemaClassId.KEY_PACKAGE,
- [QmfQuery.QUOTE, _pname]],
- [QmfQuery.EQ, SchemaClassId.KEY_CLASS,
- [QmfQuery.QUOTE, _cname]]]
- else:
- pred = [QmfQuery.EQ,
- SchemaClassId.KEY_PACKAGE,
- [QmfQuery.QUOTE, _pname]]
- query = QmfQuery.create_predicate(QmfQuery.TARGET_SCHEMA_ID, pred)
- timeout = timedelta_to_secs(expired - now)
- sid_list = self.do_query(agent, query, _timeout=timeout)
- if sid_list:
- for sid in sid_list:
- now = datetime.datetime.utcnow()
- if now >= expired:
- break
- if _object_id is not None:
- query = QmfQuery.create_id_object(_object_id, sid)
- else:
- t_params = {QmfData.KEY_SCHEMA_ID: sid}
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT, t_params)
- timeout = timedelta_to_secs(expired - now)
- reply = self.do_query(agent, query, _timeout=timeout)
- if reply:
- obj_list = obj_list + reply
- if obj_list:
- return obj_list
- return None
-
-
-
- # called by run() thread ONLY
- #
- def _dispatch(self, msg, _direct=True):
- """
- PRIVATE: Process a message received from an Agent
- """
- logging.debug( "Message received from Agent! [%s]" % msg )
- try:
- version,opcode = parse_subject(msg.properties.get("qmf.subject"))
- # @todo: deal with version mismatch!!!
- except:
- logging.error("Ignoring unrecognized message '%s'" % msg)
- return
-
- cmap = {}; props = {}
- if msg.content_type == "amqp/map":
- cmap = msg.content
- if msg.properties:
- props = msg.properties
-
- if opcode == OpCode.agent_ind:
- self._handle_agent_ind_msg( msg, cmap, version, _direct )
- elif opcode == OpCode.data_ind:
- self._handle_data_ind_msg(msg, cmap, version, _direct)
- elif opcode == OpCode.event_ind:
- self._handle_event_ind_msg(msg, cmap, version, _direct)
- elif opcode == OpCode.managed_object:
- logging.warning("!!! managed_object TBD !!!")
- elif opcode == OpCode.object_ind:
- logging.warning("!!! object_ind TBD !!!")
- elif opcode == OpCode.response:
- self._handle_response_msg(msg, cmap, version, _direct)
- elif opcode == OpCode.schema_ind:
- logging.warning("!!! schema_ind TBD !!!")
- elif opcode == OpCode.noop:
- logging.debug("No-op msg received.")
- else:
- logging.warning("Ignoring message with unrecognized 'opcode' value: '%s'" % opcode)
-
-
- def _handle_agent_ind_msg(self, msg, cmap, version, direct):
- """
- Process a received agent-ind message. This message may be a response to a
- agent-locate, or it can be an unsolicited agent announce.
- """
- logging.debug("_handle_agent_ind_msg '%s' (%s)" % (msg, time.time()))
-
- ai_map = cmap.get(MsgKey.agent_info)
- if not ai_map or not isinstance(ai_map, type({})):
- logging.warning("Bad agent-ind message received: '%s'" % msg)
- return
- name = ai_map.get("_name")
- if not name:
- logging.warning("Bad agent-ind message received: agent name missing"
- " '%s'" % msg)
- return
-
- correlated = False
- if msg.correlation_id:
- mbox = self._get_mailbox(msg.correlation_id)
- correlated = mbox is not None
-
- agent = None
- self._lock.acquire()
- try:
- agent = self._agent_map.get(name)
- if agent:
- # agent already known, just update timestamp
- agent._announce_timestamp = datetime.datetime.utcnow()
- finally:
- self._lock.release()
-
- if not agent:
- # need to create and add a new agent?
- matched = False
- if self._agent_discovery_filter:
- tmp = QmfData.create(values=ai_map, _object_id="agent-filter")
- matched = self._agent_discovery_filter.evaluate(tmp)
-
- if (correlated or matched):
- agent = self._create_agent(name)
- if not agent:
- return # failed to add agent
- agent._announce_timestamp = datetime.datetime.utcnow()
-
- if matched:
- # unsolicited, but newly discovered
- logging.debug("AGENT_ADDED for %s (%s)" % (agent, time.time()))
- wi = WorkItem(WorkItem.AGENT_ADDED, None, {"agent": agent})
- self._work_q.put(wi)
- self._work_q_put = True
-
- if correlated:
- # wake up all waiters
- logging.debug("waking waiters for correlation id %s" % msg.correlation_id)
- mbox.deliver(msg)
-
- def _handle_data_ind_msg(self, msg, cmap, version, direct):
- """
- Process a received data-ind message.
- """
- logging.debug("_handle_data_ind_msg '%s' (%s)" % (msg, time.time()))
-
- mbox = self._get_mailbox(msg.correlation_id)
- if not mbox:
- logging.debug("Data indicate received with unknown correlation_id"
- " msg='%s'" % str(msg))
- return
-
- # wake up all waiters
- logging.debug("waking waiters for correlation id %s" %
- msg.correlation_id)
- mbox.deliver(msg)
-
-
- def _handle_response_msg(self, msg, cmap, version, direct):
- """
- Process a received data-ind message.
- """
- # @todo code replication - clean me.
- logging.debug("_handle_response_msg '%s' (%s)" % (msg, time.time()))
-
- mbox = self._get_mailbox(msg.correlation_id)
- if not mbox:
- logging.debug("Response msg received with unknown correlation_id"
- " msg='%s'" % str(msg))
- return
-
- # wake up all waiters
- logging.debug("waking waiters for correlation id %s" % msg.correlation_id)
- mbox.deliver(msg)
-
- def _handle_event_ind_msg(self, msg, cmap, version, _direct):
- ei_map = cmap.get(MsgKey.event)
- if not ei_map or not isinstance(ei_map, type({})):
- logging.warning("Bad event indication message received: '%s'" % msg)
- return
-
- aname = ei_map.get("_name")
- emap = ei_map.get("_event")
- if not aname:
- logging.debug("No '_name' field in event indication message.")
- return
- if not emap:
- logging.debug("No '_event' field in event indication message.")
- return
-
- agent = None
- self._lock.acquire()
- try:
- agent = self._agent_map.get(aname)
- finally:
- self._lock.release()
- if not agent:
- logging.debug("Agent '%s' not known." % aname)
- return
- try:
- # @todo: schema???
- event = QmfEvent.from_map(emap)
- except TypeError:
- logging.debug("Invalid QmfEvent map received: %s" % str(emap))
- return
-
- # @todo: schema? Need to fetch it, but not from this thread!
- # This thread can not pend on a request.
- logging.debug("Publishing event received from agent %s" % aname)
- wi = WorkItem(WorkItem.EVENT_RECEIVED, None,
- {"agent":agent,
- "event":event})
- self._work_q.put(wi)
- self._work_q_put = True
-
-
- def _expire_mboxes(self):
- """
- Check all async mailboxes for outstanding requests that have expired.
- """
- now = datetime.datetime.utcnow()
- if self._next_mbox_expire and now < self._next_mbox_expire:
- return
- expired_mboxes = []
- self._next_mbox_expire = None
- self._lock.acquire()
- try:
- for mbox in self._async_mboxes.itervalues():
- if now >= mbox.expiration_date:
- expired_mboxes.append(mbox)
- else:
- if (self._next_mbox_expire is None or
- mbox.expiration_date < self._next_mbox_expire):
- self._next_mbox_expire = mbox.expiration_date
-
- for mbox in expired_mboxes:
- del self._async_mboxes[mbox.cid]
- finally:
- self._lock.release()
-
- for mbox in expired_mboxes:
- # note: expire() may deallocate the mbox, so don't touch
- # it further.
- mbox.expire()
-
-
- def _expire_agents(self):
- """
- Check for expired agents and issue notifications when they expire.
- """
- now = datetime.datetime.utcnow()
- if self._next_agent_expire and now < self._next_agent_expire:
- return
- lifetime_delta = datetime.timedelta(seconds = self._agent_timeout)
- next_expire_delta = lifetime_delta
- self._lock.acquire()
- try:
- logging.debug("!!! expiring agents '%s'" % now)
- for agent in self._agent_map.itervalues():
- if agent._announce_timestamp:
- agent_deathtime = agent._announce_timestamp + lifetime_delta
- if agent_deathtime <= now:
- logging.debug("AGENT_DELETED for %s" % agent)
- agent._announce_timestamp = None
- wi = WorkItem(WorkItem.AGENT_DELETED, None,
- {"agent":agent})
- # @todo: remove agent from self._agent_map
- self._work_q.put(wi)
- self._work_q_put = True
- else:
- if (agent_deathtime - now) < next_expire_delta:
- next_expire_delta = agent_deathtime - now
-
- self._next_agent_expire = now + next_expire_delta
- logging.debug("!!! next expire cycle = '%s'" % self._next_agent_expire)
- finally:
- self._lock.release()
-
-
-
- def _create_agent( self, name ):
- """
- Factory to create/retrieve an agent for this console
- """
- logging.debug("creating agent %s" % name)
- self._lock.acquire()
- try:
- agent = self._agent_map.get(name)
- if agent:
- return agent
-
- agent = Agent(name, self)
- try:
- agent._sender = self._session.sender(str(agent._address) +
- ";{create:always,"
- " node-properties:"
- " {type:topic,"
- " x-properties:"
- " {type:direct}}}")
- except:
- logging.warning("Unable to create sender for %s" % name)
- return None
- logging.debug("created agent sender %s" % agent._sender.target)
-
- self._agent_map[name] = agent
- finally:
- self._lock.release()
-
- # new agent - query for its schema database for
- # seeding the schema cache (@todo)
- # query = QmfQuery({QmfQuery.TARGET_SCHEMA_ID:None})
- # agent._sendQuery( query )
-
- return agent
-
-
-
- def enable_agent_discovery(self, _query=None):
- """
- Called to enable the asynchronous Agent Discovery process.
- Once enabled, AGENT_ADD work items can arrive on the WorkQueue.
- """
- # @todo: fix - take predicate only, not entire query!
- if _query is not None:
- if (not isinstance(_query, QmfQuery) or
- _query.get_target() != QmfQuery.TARGET_AGENT):
- raise TypeError("Type QmfQuery with target == TARGET_AGENT expected")
- self._agent_discovery_filter = _query
- else:
- # create a match-all agent query (no predicate)
- self._agent_discovery_filter = QmfQuery.create_wildcard(QmfQuery.TARGET_AGENT)
-
- def disable_agent_discovery(self):
- """
- Called to disable the async Agent Discovery process enabled by
- calling enableAgentDiscovery()
- """
- self._agent_discovery_filter = None
-
-
-
- def get_workitem_count(self):
- """
- Returns the count of pending WorkItems that can be retrieved.
- """
- return self._work_q.qsize()
-
-
-
- def get_next_workitem(self, timeout=None):
- """
- Returns the next pending work item, or None if none available.
- @todo: subclass and return an Empty event instead.
- """
- try:
- wi = self._work_q.get(True, timeout)
- except Queue.Empty:
- return None
- return wi
-
-
- def release_workitem(self, wi):
- """
- Return a WorkItem to the Console when it is no longer needed.
- @todo: call Queue.task_done() - only 2.5+
-
- @type wi: class qmfConsole.WorkItem
- @param wi: work item object to return.
- """
- pass
-
- def _add_schema(self, schema):
- """
- @todo
- """
- if not isinstance(schema, SchemaClass):
- raise TypeError("SchemaClass type expected")
-
- self._lock.acquire()
- try:
- sid = schema.get_class_id()
- if not self._schema_cache.has_key(sid):
- self._schema_cache[sid] = schema
- if sid in self._pending_schema_req:
- self._pending_schema_req.remove(sid)
- finally:
- self._lock.release()
-
- def _prefetch_schema(self, schema_id, agent):
- """
- Send an async request for the schema identified by schema_id if the
- schema is not available in the cache.
- """
- need_fetch = False
- self._lock.acquire()
- try:
- if ((not self._schema_cache.has_key(schema_id)) and
- schema_id not in self._pending_schema_req):
- self._pending_schema_req.append(schema_id)
- need_fetch = True
- finally:
- self._lock.release()
-
- if need_fetch:
- mbox = _SchemaPrefetchMailbox(self, schema_id)
- query = QmfQuery.create_id(QmfQuery.TARGET_SCHEMA, schema_id)
- logging.debug("Sending Schema Query to Agent (%s)" % time.time())
- try:
- agent._send_query(query, mbox.get_address())
- except SendError, e:
- logging.error(str(e))
- mbox.destroy()
- self._lock.acquire()
- try:
- self._pending_schema_req.remove(schema_id)
- finally:
- self._lock.release()
-
-
- def _fetch_schema(self, schema_id, _agent=None, _timeout=None):
- """
- Find the schema identified by schema_id. If not in the cache, ask the
- agent for it.
- """
- if not isinstance(schema_id, SchemaClassId):
- raise TypeError("SchemaClassId type expected")
-
- self._lock.acquire()
- try:
- schema = self._schema_cache.get(schema_id)
- if schema:
- return schema
- finally:
- self._lock.release()
-
- if _agent is None:
- return None
-
- # note: do_query will add the new schema to the cache automatically.
- slist = self.do_query(_agent,
- QmfQuery.create_id(QmfQuery.TARGET_SCHEMA, schema_id),
- _timeout=_timeout)
- if slist:
- return slist[0]
- else:
- return None
-
- def _add_mailbox(self, mbox):
- """
- Add a mailbox to the post office, and assign it a unique address.
- """
- self._lock.acquire()
- try:
- mbox.cid = self._correlation_id
- self._correlation_id += 1
- self._post_office[mbox.cid] = mbox
- finally:
- self._lock.release()
-
- def _get_mailbox(self, mid):
- try:
- mid = long(mid)
- except TypeError:
- logging.error("Invalid mailbox id: %s" % str(mid))
- return None
-
- self._lock.acquire()
- try:
- return self._post_office.get(mid)
- finally:
- self._lock.release()
-
-
- def _remove_mailbox(self, mid):
- """ Remove a mailbox and its address from the post office """
- try:
- mid = long(mid)
- except TypeError:
- logging.error("Invalid mailbox id: %s" % str(mid))
- return None
-
- self._lock.acquire()
- try:
- if mid in self._post_office:
- del self._post_office[mid]
- finally:
- self._lock.release()
-
- def __repr__(self):
- return str(self._address)
-
- # def get_packages(self):
- # plist = []
- # for i in range(self.impl.packageCount()):
- # plist.append(self.impl.getPackageName(i))
- # return plist
-
-
- # def get_classes(self, package, kind=CLASS_OBJECT):
- # clist = []
- # for i in range(self.impl.classCount(package)):
- # key = self.impl.getClass(package, i)
- # class_kind = self.impl.getClassKind(key)
- # if class_kind == kind:
- # if kind == CLASS_OBJECT:
- # clist.append(SchemaObjectClass(None, None, {"impl":self.impl.getObjectClass(key)}))
- # elif kind == CLASS_EVENT:
- # clist.append(SchemaEventClass(None, None, {"impl":self.impl.getEventClass(key)}))
- # return clist
-
-
- # def bind_package(self, package):
- # return self.impl.bindPackage(package)
-
-
- # def bind_class(self, kwargs = {}):
- # if "key" in kwargs:
- # self.impl.bindClass(kwargs["key"])
- # elif "package" in kwargs:
- # package = kwargs["package"]
- # if "class" in kwargs:
- # self.impl.bindClass(package, kwargs["class"])
- # else:
- # self.impl.bindClass(package)
- # else:
- # raise Exception("Argument error: invalid arguments, use 'key' or 'package'[,'class']")
-
-
- # def get_agents(self, broker=None):
- # blist = []
- # if broker:
- # blist.append(broker)
- # else:
- # self._cv.acquire()
- # try:
- # # copy while holding lock
- # blist = self._broker_list[:]
- # finally:
- # self._cv.release()
-
- # agents = []
- # for b in blist:
- # for idx in range(b.impl.agentCount()):
- # agents.append(AgentProxy(b.impl.getAgent(idx), b))
-
- # return agents
-
-
- # def get_objects(self, query, kwargs = {}):
- # timeout = 30
- # agent = None
- # temp_args = kwargs.copy()
- # if type(query) == type({}):
- # temp_args.update(query)
-
- # if "_timeout" in temp_args:
- # timeout = temp_args["_timeout"]
- # temp_args.pop("_timeout")
-
- # if "_agent" in temp_args:
- # agent = temp_args["_agent"]
- # temp_args.pop("_agent")
-
- # if type(query) == type({}):
- # query = Query(temp_args)
-
- # self._select = {}
- # for k in temp_args.iterkeys():
- # if type(k) == str:
- # self._select[k] = temp_args[k]
-
- # self._cv.acquire()
- # try:
- # self._sync_count = 1
- # self._sync_result = []
- # broker = self._broker_list[0]
- # broker.send_query(query.impl, None, agent)
- # self._cv.wait(timeout)
- # if self._sync_count == 1:
- # raise Exception("Timed out: waiting for query response")
- # finally:
- # self._cv.release()
-
- # return self._sync_result
-
-
- # def get_object(self, query, kwargs = {}):
- # '''
- # Return one and only one object or None.
- # '''
- # objs = objects(query, kwargs)
- # if len(objs) == 1:
- # return objs[0]
- # else:
- # return None
-
-
- # def first_object(self, query, kwargs = {}):
- # '''
- # Return the first of potentially many objects.
- # '''
- # objs = objects(query, kwargs)
- # if objs:
- # return objs[0]
- # else:
- # return None
-
-
- # # Check the object against select to check for a match
- # def _select_match(self, object):
- # schema_props = object.properties()
- # for key in self._select.iterkeys():
- # for prop in schema_props:
- # if key == p[0].name() and self._select[key] != p[1]:
- # return False
- # return True
-
-
- # def _get_result(self, list, context):
- # '''
- # Called by Broker proxy to return the result of a query.
- # '''
- # self._cv.acquire()
- # try:
- # for item in list:
- # if self._select_match(item):
- # self._sync_result.append(item)
- # self._sync_count -= 1
- # self._cv.notify()
- # finally:
- # self._cv.release()
-
-
- # def start_sync(self, query): pass
-
-
- # def touch_sync(self, sync): pass
-
-
- # def end_sync(self, sync): pass
-
-
-
-
-# def start_console_events(self):
-# self._cb_cond.acquire()
-# try:
-# self._cb_cond.notify()
-# finally:
-# self._cb_cond.release()
-
-
-# def _do_console_events(self):
-# '''
-# Called by the Console thread to poll for events. Passes the events
-# onto the ConsoleHandler associated with this Console. Is called
-# periodically, but can also be kicked by Console.start_console_events().
-# '''
-# count = 0
-# valid = self.impl.getEvent(self._event)
-# while valid:
-# count += 1
-# try:
-# if self._event.kind == qmfengine.ConsoleEvent.AGENT_ADDED:
-# logging.debug("Console Event AGENT_ADDED received")
-# if self._handler:
-# self._handler.agent_added(AgentProxy(self._event.agent, None))
-# elif self._event.kind == qmfengine.ConsoleEvent.AGENT_DELETED:
-# logging.debug("Console Event AGENT_DELETED received")
-# if self._handler:
-# self._handler.agent_deleted(AgentProxy(self._event.agent, None))
-# elif self._event.kind == qmfengine.ConsoleEvent.NEW_PACKAGE:
-# logging.debug("Console Event NEW_PACKAGE received")
-# if self._handler:
-# self._handler.new_package(self._event.name)
-# elif self._event.kind == qmfengine.ConsoleEvent.NEW_CLASS:
-# logging.debug("Console Event NEW_CLASS received")
-# if self._handler:
-# self._handler.new_class(SchemaClassKey(self._event.classKey))
-# elif self._event.kind == qmfengine.ConsoleEvent.OBJECT_UPDATE:
-# logging.debug("Console Event OBJECT_UPDATE received")
-# if self._handler:
-# self._handler.object_update(ConsoleObject(None, {"impl":self._event.object}),
-# self._event.hasProps, self._event.hasStats)
-# elif self._event.kind == qmfengine.ConsoleEvent.EVENT_RECEIVED:
-# logging.debug("Console Event EVENT_RECEIVED received")
-# elif self._event.kind == qmfengine.ConsoleEvent.AGENT_HEARTBEAT:
-# logging.debug("Console Event AGENT_HEARTBEAT received")
-# if self._handler:
-# self._handler.agent_heartbeat(AgentProxy(self._event.agent, None), self._event.timestamp)
-# elif self._event.kind == qmfengine.ConsoleEvent.METHOD_RESPONSE:
-# logging.debug("Console Event METHOD_RESPONSE received")
-# else:
-# logging.debug("Console thread received unknown event: '%s'" % str(self._event.kind))
-# except e:
-# print "Exception caught in callback thread:", e
-# self.impl.popEvent()
-# valid = self.impl.getEvent(self._event)
-# return count
-
-
-
-
-
-# class Broker(ConnectionHandler):
-# # attr_reader :impl :conn, :console, :broker_bank
-# def __init__(self, console, conn):
-# self.broker_bank = 1
-# self.console = console
-# self.conn = conn
-# self._session = None
-# self._cv = Condition()
-# self._stable = None
-# self._event = qmfengine.BrokerEvent()
-# self._xmtMessage = qmfengine.Message()
-# self.impl = qmfengine.BrokerProxy(self.console.impl)
-# self.console.impl.addConnection(self.impl, self)
-# self.conn.add_conn_handler(self)
-# self._operational = True
-
-
-# def shutdown(self):
-# logging.debug("broker.shutdown() called.")
-# self.console.impl.delConnection(self.impl)
-# self.conn.del_conn_handler(self)
-# if self._session:
-# self.impl.sessionClosed()
-# logging.debug("broker.shutdown() sessionClosed done.")
-# self._session.destroy()
-# logging.debug("broker.shutdown() session destroy done.")
-# self._session = None
-# self._operational = False
-# logging.debug("broker.shutdown() done.")
-
-
-# def wait_for_stable(self, timeout = None):
-# self._cv.acquire()
-# try:
-# if self._stable:
-# return
-# if timeout:
-# self._cv.wait(timeout)
-# if not self._stable:
-# raise Exception("Timed out: waiting for broker connection to become stable")
-# else:
-# while not self._stable:
-# self._cv.wait()
-# finally:
-# self._cv.release()
-
-
-# def send_query(self, query, ctx, agent):
-# agent_impl = None
-# if agent:
-# agent_impl = agent.impl
-# self.impl.sendQuery(query, ctx, agent_impl)
-# self.conn.kick()
-
-
-# def _do_broker_events(self):
-# count = 0
-# valid = self.impl.getEvent(self._event)
-# while valid:
-# count += 1
-# if self._event.kind == qmfengine.BrokerEvent.BROKER_INFO:
-# logging.debug("Broker Event BROKER_INFO received");
-# elif self._event.kind == qmfengine.BrokerEvent.DECLARE_QUEUE:
-# logging.debug("Broker Event DECLARE_QUEUE received");
-# self.conn.impl.declareQueue(self._session.handle, self._event.name)
-# elif self._event.kind == qmfengine.BrokerEvent.DELETE_QUEUE:
-# logging.debug("Broker Event DELETE_QUEUE received");
-# self.conn.impl.deleteQueue(self._session.handle, self._event.name)
-# elif self._event.kind == qmfengine.BrokerEvent.BIND:
-# logging.debug("Broker Event BIND received");
-# self.conn.impl.bind(self._session.handle, self._event.exchange, self._event.name, self._event.bindingKey)
-# elif self._event.kind == qmfengine.BrokerEvent.UNBIND:
-# logging.debug("Broker Event UNBIND received");
-# self.conn.impl.unbind(self._session.handle, self._event.exchange, self._event.name, self._event.bindingKey)
-# elif self._event.kind == qmfengine.BrokerEvent.SETUP_COMPLETE:
-# logging.debug("Broker Event SETUP_COMPLETE received");
-# self.impl.startProtocol()
-# elif self._event.kind == qmfengine.BrokerEvent.STABLE:
-# logging.debug("Broker Event STABLE received");
-# self._cv.acquire()
-# try:
-# self._stable = True
-# self._cv.notify()
-# finally:
-# self._cv.release()
-# elif self._event.kind == qmfengine.BrokerEvent.QUERY_COMPLETE:
-# result = []
-# for idx in range(self._event.queryResponse.getObjectCount()):
-# result.append(ConsoleObject(None, {"impl":self._event.queryResponse.getObject(idx), "broker":self}))
-# self.console._get_result(result, self._event.context)
-# elif self._event.kind == qmfengine.BrokerEvent.METHOD_RESPONSE:
-# obj = self._event.context
-# obj._method_result(MethodResponse(self._event.methodResponse()))
-
-# self.impl.popEvent()
-# valid = self.impl.getEvent(self._event)
-
-# return count
-
-
-# def _do_broker_messages(self):
-# count = 0
-# valid = self.impl.getXmtMessage(self._xmtMessage)
-# while valid:
-# count += 1
-# logging.debug("Broker: sending msg on connection")
-# self.conn.impl.sendMessage(self._session.handle, self._xmtMessage)
-# self.impl.popXmt()
-# valid = self.impl.getXmtMessage(self._xmtMessage)
-
-# return count
-
-
-# def _do_events(self):
-# while True:
-# self.console.start_console_events()
-# bcnt = self._do_broker_events()
-# mcnt = self._do_broker_messages()
-# if bcnt == 0 and mcnt == 0:
-# break;
-
-
-# def conn_event_connected(self):
-# logging.debug("Broker: Connection event CONNECTED")
-# self._session = Session(self.conn, "qmfc-%s.%d" % (socket.gethostname(), os.getpid()), self)
-# self.impl.sessionOpened(self._session.handle)
-# self._do_events()
-
-
-# def conn_event_disconnected(self, error):
-# logging.debug("Broker: Connection event DISCONNECTED")
-# pass
-
-
-# def conn_event_visit(self):
-# self._do_events()
-
-
-# def sess_event_session_closed(self, context, error):
-# logging.debug("Broker: Session event CLOSED")
-# self.impl.sessionClosed()
-
-
-# def sess_event_recv(self, context, message):
-# logging.debug("Broker: Session event MSG_RECV")
-# if not self._operational:
-# logging.warning("Unexpected session event message received by Broker proxy: context='%s'" % str(context))
-# self.impl.handleRcvMessage(message)
-# self._do_events()
-
-
-
-################################################################################
-################################################################################
-################################################################################
-################################################################################
-# TEMPORARY TEST CODE - TO BE DELETED
-################################################################################
-################################################################################
-################################################################################
-################################################################################
-
-if __name__ == '__main__':
- # temp test code
- from common import (qmfTypes, SchemaProperty)
-
- logging.getLogger().setLevel(logging.INFO)
-
- logging.info( "************* Creating Async Console **************" )
-
- class MyNotifier(Notifier):
- def __init__(self, context):
- self._myContext = context
- self.WorkAvailable = False
-
- def indication(self):
- print("Indication received! context=%d" % self._myContext)
- self.WorkAvailable = True
-
- _noteMe = MyNotifier( 666 )
-
- _myConsole = Console(notifier=_noteMe)
-
- _myConsole.enable_agent_discovery()
- logging.info("Waiting...")
-
-
- logging.info( "Destroying console:" )
- _myConsole.destroy( 10 )
-
- logging.info( "******** Messing around with Schema ********" )
-
- _sec = SchemaEventClass( _classId=SchemaClassId("myPackage", "myClass",
- stype=SchemaClassId.TYPE_EVENT),
- _desc="A typical event schema",
- _props={"Argument-1": SchemaProperty(_type_code=qmfTypes.TYPE_UINT8,
- kwargs = {"min":0,
- "max":100,
- "unit":"seconds",
- "desc":"sleep value"}),
- "Argument-2": SchemaProperty(_type_code=qmfTypes.TYPE_LSTR,
- kwargs={"maxlen":100,
- "desc":"a string argument"})})
- print("_sec=%s" % _sec.get_class_id())
- print("_sec.gePropertyCount()=%d" % _sec.get_property_count() )
- print("_sec.getProperty('Argument-1`)=%s" % _sec.get_property('Argument-1') )
- print("_sec.getProperty('Argument-2`)=%s" % _sec.get_property('Argument-2') )
- try:
- print("_sec.getProperty('not-found')=%s" % _sec.get_property('not-found') )
- except:
- pass
- print("_sec.getProperties()='%s'" % _sec.get_properties())
-
- print("Adding another argument")
- _arg3 = SchemaProperty( _type_code=qmfTypes.TYPE_BOOL,
- kwargs={"dir":"IO",
- "desc":"a boolean argument"})
- _sec.add_property('Argument-3', _arg3)
- print("_sec=%s" % _sec.get_class_id())
- print("_sec.getPropertyCount()=%d" % _sec.get_property_count() )
- print("_sec.getProperty('Argument-1')=%s" % _sec.get_property('Argument-1') )
- print("_sec.getProperty('Argument-2')=%s" % _sec.get_property('Argument-2') )
- print("_sec.getProperty('Argument-3')=%s" % _sec.get_property('Argument-3') )
-
- print("_arg3.mapEncode()='%s'" % _arg3.map_encode() )
-
- _secmap = _sec.map_encode()
- print("_sec.mapEncode()='%s'" % _secmap )
-
- _sec2 = SchemaEventClass( _map=_secmap )
-
- print("_sec=%s" % _sec.get_class_id())
- print("_sec2=%s" % _sec2.get_class_id())
-
- _soc = SchemaObjectClass( _map = {"_schema_id": {"_package_name": "myOtherPackage",
- "_class_name": "myOtherClass",
- "_type": "_data"},
- "_desc": "A test data object",
- "_values":
- {"prop1": {"amqp_type": qmfTypes.TYPE_UINT8,
- "access": "RO",
- "index": True,
- "unit": "degrees"},
- "prop2": {"amqp_type": qmfTypes.TYPE_UINT8,
- "access": "RW",
- "index": True,
- "desc": "The Second Property(tm)",
- "unit": "radians"},
- "statistics": { "amqp_type": qmfTypes.TYPE_DELTATIME,
- "unit": "seconds",
- "desc": "time until I retire"},
- "meth1": {"_desc": "A test method",
- "_arguments":
- {"arg1": {"amqp_type": qmfTypes.TYPE_UINT32,
- "desc": "an argument 1",
- "dir": "I"},
- "arg2": {"amqp_type": qmfTypes.TYPE_BOOL,
- "dir": "IO",
- "desc": "some weird boolean"}}},
- "meth2": {"_desc": "A test method",
- "_arguments":
- {"m2arg1": {"amqp_type": qmfTypes.TYPE_UINT32,
- "desc": "an 'nuther argument",
- "dir":
- "I"}}}},
- "_subtypes":
- {"prop1":"qmfProperty",
- "prop2":"qmfProperty",
- "statistics":"qmfProperty",
- "meth1":"qmfMethod",
- "meth2":"qmfMethod"},
- "_primary_key_names": ["prop2", "prop1"]})
-
- print("_soc='%s'" % _soc)
-
- print("_soc.getPrimaryKeyList='%s'" % _soc.get_id_names())
-
- print("_soc.getPropertyCount='%d'" % _soc.get_property_count())
- print("_soc.getProperties='%s'" % _soc.get_properties())
- print("_soc.getProperty('prop2')='%s'" % _soc.get_property('prop2'))
-
- print("_soc.getMethodCount='%d'" % _soc.get_method_count())
- print("_soc.getMethods='%s'" % _soc.get_methods())
- print("_soc.getMethod('meth2')='%s'" % _soc.get_method('meth2'))
-
- _socmap = _soc.map_encode()
- print("_socmap='%s'" % _socmap)
- _soc2 = SchemaObjectClass( _map=_socmap )
- print("_soc='%s'" % _soc)
- print("_soc2='%s'" % _soc2)
-
- if _soc2.get_class_id() == _soc.get_class_id():
- print("soc and soc2 are the same schema")
-
-
- logging.info( "******** Messing around with ObjectIds ********" )
-
-
- qd = QmfData( _values={"prop1":1, "prop2":True, "prop3": {"a":"map"}, "prop4": "astring"} )
- print("qd='%s':" % qd)
-
- print("prop1=%d prop2=%s prop3=%s prop4=%s" % (qd.prop1, qd.prop2, qd.prop3, qd.prop4))
-
- print("qd map='%s'" % qd.map_encode())
- print("qd getProperty('prop4')='%s'" % qd.get_value("prop4"))
- qd.set_value("prop4", 4, "A test property called 4")
- print("qd setProperty('prop4', 4)='%s'" % qd.get_value("prop4"))
- qd.prop4 = 9
- print("qd.prop4 = 9 ='%s'" % qd.prop4)
- qd["prop4"] = 11
- print("qd[prop4] = 11 ='%s'" % qd["prop4"])
-
- print("qd.mapEncode()='%s'" % qd.map_encode())
- _qd2 = QmfData( _map = qd.map_encode() )
- print("_qd2.mapEncode()='%s'" % _qd2.map_encode())
-
- _qmfDesc1 = QmfConsoleData( {"_values" : {"prop1": 1, "statistics": 666,
- "prop2": 0}},
- agent="some agent name?",
- _schema = _soc)
-
- print("_qmfDesc1 map='%s'" % _qmfDesc1.map_encode())
-
- _qmfDesc1._set_schema( _soc )
-
- print("_qmfDesc1 prop2 = '%s'" % _qmfDesc1.get_value("prop2"))
- print("_qmfDesc1 primarykey = '%s'" % _qmfDesc1.get_object_id())
- print("_qmfDesc1 classid = '%s'" % _qmfDesc1.get_schema_class_id())
-
-
- _qmfDescMap = _qmfDesc1.map_encode()
- print("_qmfDescMap='%s'" % _qmfDescMap)
-
- _qmfDesc2 = QmfData( _map=_qmfDescMap, _schema=_soc )
-
- print("_qmfDesc2 map='%s'" % _qmfDesc2.map_encode())
- print("_qmfDesc2 prop2 = '%s'" % _qmfDesc2.get_value("prop2"))
- print("_qmfDesc2 primary key = '%s'" % _qmfDesc2.get_object_id())
-
-
- logging.info( "******** Messing around with QmfEvents ********" )
-
-
- _qmfevent1 = QmfEvent( _timestamp = 1111,
- _schema = _sec,
- _values = {"Argument-1": 77,
- "Argument-3": True,
- "Argument-2": "a string"})
- print("_qmfevent1.mapEncode()='%s'" % _qmfevent1.map_encode())
- print("_qmfevent1.getTimestamp()='%s'" % _qmfevent1.get_timestamp())
-
- _qmfevent1Map = _qmfevent1.map_encode()
-
- _qmfevent2 = QmfEvent(_map=_qmfevent1Map, _schema=_sec)
- print("_qmfevent2.mapEncode()='%s'" % _qmfevent2.map_encode())
-
-
- logging.info( "******** Messing around with Queries ********" )
-
- _q1 = QmfQuery.create_predicate(QmfQuery.TARGET_AGENT,
- [QmfQuery.AND,
- [QmfQuery.EQ, "vendor", [QmfQuery.QUOTE, "AVendor"]],
- [QmfQuery.EQ, [QmfQuery.QUOTE, "SomeProduct"], "product"],
- [QmfQuery.EQ, [QmfQuery.UNQUOTE, "name"], [QmfQuery.QUOTE, "Thingy"]],
- [QmfQuery.OR,
- [QmfQuery.LE, "temperature", -10],
- [QmfQuery.FALSE],
- [QmfQuery.EXISTS, "namey"]]])
-
- print("_q1.mapEncode() = [%s]" % _q1.map_encode())
diff --git a/python/qmf2/tests/__init__.py b/python/qmf2/tests/__init__.py
deleted file mode 100644
index 186f09349e..0000000000
--- a/python/qmf2/tests/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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 agent_discovery
-import basic_query
-import basic_method
-import obj_gets
-import events
-import multi_response
-import async_query
-import async_method
diff --git a/python/qmf2/tests/agent_discovery.py b/python/qmf2/tests/agent_discovery.py
deleted file mode 100644
index 59b65221e0..0000000000
--- a/python/qmf2/tests/agent_discovery.py
+++ /dev/null
@@ -1,484 +0,0 @@
-# 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 unittest
-import logging
-import time
-from threading import Thread, Event
-
-import qpid.messaging
-import qmf2.common
-import qmf2.console
-import qmf2.agent
-
-
-class _testNotifier(qmf2.common.Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.timeout = 3
- self.broker_url = broker_url
- self.notifier = _testNotifier()
- self.agent = qmf2.agent.Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
- # No database needed for this test
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # Connect the agent to the broker,
- # broker_url = "user/passwd@hostname:port"
- conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- conn.connect()
- self.agent.set_connection(conn)
- self.ready.set()
-
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- logging.error("UNEXPECTED AGENT WORKITEM RECEIVED=%s" % wi.get_type())
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- # done, cleanup agent
- self.agent.remove_connection(self.timeout)
- self.agent.destroy(self.timeout)
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent indication interval
- self.agent_heartbeat = 1
- self.agent1 = _agentApp("agent1", self.broker, self.agent_heartbeat)
- self.agent1.start_app()
- self.agent2 = _agentApp("agent2", self.broker, self.agent_heartbeat)
- self.agent2.start_app()
-
- def tearDown(self):
- if self.agent1:
- self.agent1.stop_app()
- self.agent1 = None
- if self.agent2:
- self.agent2.stop_app()
- self.agent2 = None
-
- def test_discover_all(self):
- """
- create console
- enable agent discovery
- wait
- expect agent add for agent1 and agent2
- """
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
- self.console.enable_agent_discovery()
-
- agent1_found = agent2_found = False
- wi = self.console.get_next_workitem(timeout=3)
- while wi and not (agent1_found and agent2_found):
- if wi.get_type() == wi.AGENT_ADDED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_found = True
- elif agent.get_name() == "agent2":
- agent2_found = True
- else:
- self.fail("Unexpected agent name received: %s" %
- agent.get_name())
- if agent1_found and agent2_found:
- break;
-
- wi = self.console.get_next_workitem(timeout=3)
-
- self.assertTrue(agent1_found and agent2_found, "All agents not discovered")
-
- self.console.destroy(10)
-
-
- def test_discover_one(self):
- """
- create console
- enable agent discovery, filter for agent1 only
- wait until timeout
- expect agent add for agent1 only
- """
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- query = qmf2.common.QmfQuery.create_predicate(
- qmf2.common.QmfQuery.TARGET_AGENT,
- [qmf2.common.QmfQuery.EQ, qmf2.common.QmfQuery.KEY_AGENT_NAME,
- [qmf2.common.QmfQuery.QUOTE, "agent1"]])
- self.console.enable_agent_discovery(query)
-
- agent1_found = agent2_found = False
- wi = self.console.get_next_workitem(timeout=3)
- while wi:
- if wi.get_type() == wi.AGENT_ADDED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_found = True
- elif agent.get_name() == "agent2":
- agent2_found = True
- else:
- self.fail("Unexpected agent name received: %s" %
- agent.get_name())
-
- wi = self.console.get_next_workitem(timeout=2)
-
- self.assertTrue(agent1_found and not agent2_found, "Unexpected agent discovered")
-
- self.console.destroy(10)
-
-
- def test_heartbeat(self):
- """
- create console with 2 sec agent timeout
- enable agent discovery, find all agents
- stop agent1, expect timeout notification
- stop agent2, expect timeout notification
- """
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=2)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
- self.console.enable_agent_discovery()
-
- agent1_found = agent2_found = False
- wi = self.console.get_next_workitem(timeout=4)
- while wi and not (agent1_found and agent2_found):
- if wi.get_type() == wi.AGENT_ADDED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_found = True
- elif agent.get_name() == "agent2":
- agent2_found = True
- else:
- self.fail("Unexpected agent name received: %s" %
- agent.get_name())
- if agent1_found and agent2_found:
- break;
-
- wi = self.console.get_next_workitem(timeout=4)
-
- self.assertTrue(agent1_found and agent2_found, "All agents not discovered")
-
- # now kill agent1 and wait for expiration
-
- agent1 = self.agent1
- self.agent1 = None
- agent1.stop_app()
-
- wi = self.console.get_next_workitem(timeout=4)
- while wi is not None:
- if wi.get_type() == wi.AGENT_DELETED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_found = False
- else:
- self.fail("Unexpected agent_deleted received: %s" %
- agent.get_name())
- if not agent1_found:
- break;
-
- wi = self.console.get_next_workitem(timeout=4)
-
- self.assertFalse(agent1_found, "agent1 did not delete!")
-
- # now kill agent2 and wait for expiration
-
- agent2 = self.agent2
- self.agent2 = None
- agent2.stop_app()
-
- wi = self.console.get_next_workitem(timeout=4)
- while wi is not None:
- if wi.get_type() == wi.AGENT_DELETED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent2":
- agent2_found = False
- else:
- self.fail("Unexpected agent_deleted received: %s" %
- agent.get_name())
- if not agent2_found:
- break;
-
- wi = self.console.get_next_workitem(timeout=4)
-
- self.assertFalse(agent2_found, "agent2 did not delete!")
-
- self.console.destroy(10)
-
-
- def test_find_agent(self):
- """
- create console
- do not enable agent discovery
- find agent1, expect success
- find agent-none, expect failure
- find agent2, expect success
- """
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- agent1 = self.console.find_agent("agent1", timeout=3)
- self.assertTrue(agent1 and agent1.get_name() == "agent1")
-
- no_agent = self.console.find_agent("agent-none", timeout=3)
- self.assertTrue(no_agent == None)
-
- agent2 = self.console.find_agent("agent2", timeout=3)
- self.assertTrue(agent2 and agent2.get_name() == "agent2")
-
- self.console.remove_connection(self.conn, 10)
- self.console.destroy(10)
-
-
- def test_heartbeat_x2(self):
- """
- create 2 consoles with 2 sec agent timeout
- enable agent discovery, find all agents
- stop agent1, expect timeout notification on both consoles
- stop agent2, expect timeout notification on both consoles
- """
- console_count = 2
- self.consoles = []
- for i in range(console_count):
- console = qmf2.console.Console("test-console-" + str(i),
- notifier=_testNotifier(),
- agent_timeout=2)
- conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- conn.connect()
- console.add_connection(conn)
- console.enable_agent_discovery()
- self.consoles.append(console)
-
- # now wait for all consoles to discover all agents,
- # agents send a heartbeat once a second
- for console in self.consoles:
- agent1_found = agent2_found = False
- wi = console.get_next_workitem(timeout=2)
- while wi and not (agent1_found and agent2_found):
- if wi.get_type() == wi.AGENT_ADDED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_found = True
- elif agent.get_name() == "agent2":
- agent2_found = True
- else:
- self.fail("Unexpected agent name received: %s" %
- agent.get_name())
- if agent1_found and agent2_found:
- break;
- wi = console.get_next_workitem(timeout=2)
-
- self.assertTrue(agent1_found and agent2_found, "All agents not discovered")
-
- # now kill agent1 and wait for expiration
-
- agent1 = self.agent1
- self.agent1 = None
- agent1.stop_app()
-
- for console in self.consoles:
- agent1_found = True
- wi = console.get_next_workitem(timeout=4)
- while wi is not None:
- if wi.get_type() == wi.AGENT_DELETED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_found = False
- break
- else:
- self.fail("Unexpected agent_deleted received: %s" %
- agent.get_name())
-
- wi = console.get_next_workitem(timeout=4)
-
- self.assertFalse(agent1_found, "agent1 did not delete!")
-
- # now kill agent2 and wait for expiration
-
- agent2 = self.agent2
- self.agent2 = None
- agent2.stop_app()
-
- for console in self.consoles:
- agent2_found = True
- wi = console.get_next_workitem(timeout=4)
- while wi is not None:
- if wi.get_type() == wi.AGENT_DELETED:
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent2":
- agent2_found = False
- break
- else:
- self.fail("Unexpected agent_deleted received: %s" %
- agent.get_name())
-
- wi = console.get_next_workitem(timeout=4)
-
- self.assertFalse(agent2_found, "agent2 did not delete!")
-
-
- for console in self.consoles:
- console.destroy(10)
-
-
- def test_find_agent_x2(self):
- """
- create 2 consoles, do not enable agent discovery
- console-1: find agent1, expect success
- console-2: find agent2, expect success
- Verify console-1 does -not- know agent2
- Verify console-2 does -not- know agent1
- """
- console_count = 2
- self.consoles = []
- for i in range(console_count):
- console = qmf2.console.Console("test-console-" + str(i),
- notifier=_testNotifier(),
- agent_timeout=2)
- conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- conn.connect()
- console.add_connection(conn)
- self.consoles.append(console)
-
- agent1 = self.consoles[0].find_agent("agent1", timeout=3)
- self.assertTrue(agent1 and agent1.get_name() == "agent1")
-
- agent2 = self.consoles[1].find_agent("agent2", timeout=3)
- self.assertTrue(agent2 and agent2.get_name() == "agent2")
-
- # wait long enough for agent heartbeats to be sent...
-
- time.sleep(self.agent_heartbeat * 2)
-
- agents = self.consoles[0].get_agents()
- self.assertTrue(len(agents) == 1 and agents[0].get_name() == "agent1")
- agent1 = self.consoles[0].get_agent("agent1")
- self.assertTrue(agent1 and agent1.get_name() == "agent1")
-
-
- agents = self.consoles[1].get_agents()
- self.assertTrue(len(agents) == 1 and agents[0].get_name() == "agent2")
- agent2 = self.consoles[1].get_agent("agent2")
- self.assertTrue(agent2 and agent2.get_name() == "agent2")
-
- # verify no new agents were learned
-
- for console in self.consoles:
- console.destroy(10)
-
diff --git a/python/qmf2/tests/agent_test.py b/python/qmf2/tests/agent_test.py
deleted file mode 100644
index 14d8ada197..0000000000
--- a/python/qmf2/tests/agent_test.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# 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 logging
-import time
-import unittest
-from threading import Semaphore
-
-
-from qpid.messaging import *
-from qmf2.common import (qmfTypes, SchemaProperty, SchemaObjectClass, QmfData,
- QmfEvent, SchemaMethod, Notifier, SchemaClassId,
- WorkItem)
-from qmf2.agent import (Agent, QmfAgentData)
-
-
-
-class ExampleNotifier(Notifier):
- def __init__(self):
- self._sema4 = Semaphore(0) # locked
-
- def indication(self):
- self._sema4.release()
-
- def waitForWork(self):
- print("Waiting for event...")
- self._sema4.acquire()
- print("...event present")
-
-
-
-
-class QmfTest(unittest.TestCase):
- def test_begin(self):
- print("!!! being test")
-
- def test_end(self):
- print("!!! end test")
-
-
-#
-# An example agent application
-#
-
-
-if __name__ == '__main__':
- _notifier = ExampleNotifier()
- _agent = Agent( "qmf.testAgent", _notifier=_notifier )
-
- # Dynamically construct a class schema
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("MyPackage", "MyClass"),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"] )
- # add properties
- _schema.add_property( "index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property( "query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # These two properties can be set via the method call
- _schema.add_property( "set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
-
- # add method
- _meth = SchemaMethod( _desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- _agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- _obj1 = QmfAgentData( _agent, _schema=_schema )
- _obj1.set_value("index1", 100)
- _obj1.set_value("index2", "a name" )
- _obj1.set_value("set_string", "UNSET")
- _obj1.set_value("set_int", 0)
- _obj1.set_value("query_count", 0)
- _obj1.set_value("method_call_count", 0)
- _agent.add_object( _obj1 )
-
- _agent.add_object( QmfAgentData( _agent, _schema=_schema,
- _values={"index1":99,
- "index2": "another name",
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
- # add an "unstructured" object to the Agent
- _obj2 = QmfAgentData(_agent, _object_id="01545")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 2)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _agent.add_object(_obj2)
-
-
- ## Now connect to the broker
-
- _c = Connection("localhost")
- _c.connect()
- _agent.setConnection(_c)
-
- _error_data = QmfData.create({"code": -1, "description": "You made a boo-boo."})
-
- _done = False
- while not _done:
- # try:
- _notifier.waitForWork()
-
- _wi = _agent.get_next_workitem(timeout=0)
- while _wi:
-
- if _wi.get_type() == WorkItem.METHOD_CALL:
- mc = _wi.get_params()
-
- if mc.get_name() == "set_meth":
- print("!!! Calling 'set_meth' on Object_id = %s" % mc.get_object_id())
- print("!!! args='%s'" % str(mc.get_args()))
- print("!!! userid=%s" % str(mc.get_user_id()))
- print("!!! handle=%s" % _wi.get_handle())
- _agent.method_response(_wi.get_handle(),
- {"rc1": 100, "rc2": "Success"})
- else:
- print("!!! Unknown Method name = %s" % mc.get_name())
- _agent.method_response(_wi.get_handle(), _error=_error_data)
- else:
- print("TBD: work item %d:%s" % (_wi.get_type(), str(_wi.get_params())))
-
- _agent.release_workitem(_wi)
- _wi = _agent.get_next_workitem(timeout=0)
- # except:
- # print( "shutting down...")
- # _done = True
-
- print( "Removing connection... TBD!!!" )
- #_myConsole.remove_connection( _c, 10 )
-
- print( "Destroying agent... TBD!!!" )
- #_myConsole.destroy( 10 )
-
- print( "******** agent test done ********" )
-
-
-
diff --git a/python/qmf2/tests/async_method.py b/python/qmf2/tests/async_method.py
deleted file mode 100644
index 556b62756f..0000000000
--- a/python/qmf2/tests/async_method.py
+++ /dev/null
@@ -1,362 +0,0 @@
-# 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 unittest
-import logging
-from threading import Thread, Event
-
-import qpid.messaging
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData, WorkItem)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent, MethodCallParams)
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.notifier = _testNotifier()
- self.broker_url = broker_url
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
-
- # Dynamically construct a management database
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("MyPackage", "MyClass"),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"] )
- # add properties
- _schema.add_property( "index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property( "query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # These two properties can be set via the method call
- _schema.add_property( "set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # add method
- _meth = SchemaMethod( _desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- # the input value of cookie is returned in the response
- _meth.add_argument( "cookie", SchemaProperty(qmfTypes.TYPE_LSTR,
- kwargs={"dir":"IO"}))
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- self.agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- _obj1 = QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":100, "index2":"a name"})
- _obj1.set_value("set_string", "UNSET")
- _obj1.set_value("set_int", 0)
- _obj1.set_value("query_count", 0)
- _obj1.set_value("method_call_count", 0)
- self.agent.add_object( _obj1 )
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":99,
- "index2": "another name",
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
- # add an "unstructured" object to the Agent
- _obj2 = QmfAgentData(self.agent, _object_id="01545")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 2)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- self.agent.add_object(_obj2)
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- self.conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- self.conn.connect()
- self.agent.set_connection(self.conn)
- self.ready.set()
-
- # Agent application main processing loop
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- if wi.get_type() == WorkItem.METHOD_CALL:
- mc = wi.get_params()
- if not isinstance(mc, MethodCallParams):
- raise Exception("Unexpected method call parameters")
-
- if mc.get_name() == "set_meth":
- obj = self.agent.get_object(mc.get_object_id(),
- mc.get_schema_id())
- if obj is None:
- error_info = QmfData.create({"code": -2,
- "description":
- "Bad Object Id."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- else:
- obj.inc_value("method_call_count")
- out_args = {"code" : 0}
- if "cookie" in mc.get_args():
- out_args["cookie"] = mc.get_args()["cookie"]
- if "arg_int" in mc.get_args():
- obj.set_value("set_int", mc.get_args()["arg_int"])
- if "arg_str" in mc.get_args():
- obj.set_value("set_string", mc.get_args()["arg_str"])
- self.agent.method_response(wi.get_handle(),
- out_args)
- elif mc.get_name() == "a_method":
- obj = self.agent.get_object(mc.get_object_id(),
- mc.get_schema_id())
- if obj is None:
- error_info = QmfData.create({"code": -3,
- "description":
- "Unknown object id."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- elif obj.get_object_id() != "01545":
- error_info = QmfData.create( {"code": -4,
- "description":
- "Unexpected id."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- else:
- args = mc.get_args()
- if ("arg1" in args and args["arg1"] == 1 and
- "arg2" in args and args["arg2"] == "Now set!"
- and "arg3" in args and args["arg3"] == 1966):
- out_args = {"code" : 0}
- if "cookie" in mc.get_args():
- out_args["cookie"] = mc.get_args()["cookie"]
- self.agent.method_response(wi.get_handle(),
- out_args)
- else:
- error_info = QmfData.create(
- {"code": -5,
- "description":
- "Bad Args."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- else:
- error_info = QmfData.create( {"code": -1,
- "description":
- "Unknown method call."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(), _error=error_info)
-
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- if self.conn:
- self.agent.remove_connection(10)
- self.agent.destroy(10)
-
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent heartbeat interval
- self.agent_heartbeat = 1
- self.agent1 = _agentApp("agent1", self.broker, self.agent_heartbeat)
- self.agent1.start_app()
- self.agent2 = _agentApp("agent2", self.broker, self.agent_heartbeat)
- self.agent2.start_app()
-
- def tearDown(self):
- if self.agent1:
- self.agent1.stop_app()
- self.agent1 = None
- if self.agent2:
- self.agent2.stop_app()
- self.agent2 = None
-
- def test_described_obj(self):
- # create console
- # find agents
- # synchronous query for all objects in schema
- # method call on each object
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- i_count = 0
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
-
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == 1)
- for sid in sid_list:
- t_params = {QmfData.KEY_SCHEMA_ID: sid}
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT,
- _target_params=t_params)
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 2)
- for obj in obj_list:
- cookie = "cookie-" + str(i_count)
- i_count += 1
- mr = obj.invoke_method( "set_meth",
- {"arg_int": -99,
- "arg_str": "Now set!",
- "cookie": cookie},
- _reply_handle=cookie,
- _timeout=3)
- self.assertTrue(mr)
-
- # done, now wait for async responses
-
- r_count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- r_count += 1
- self.assertTrue(wi.get_type() == WorkItem.METHOD_RESPONSE)
- reply = wi.get_params()
- self.assertTrue(isinstance(reply, qmf2.console.MethodResult))
- self.assertTrue(reply.succeeded())
- self.assertTrue(reply.get_argument("cookie") == wi.get_handle())
-
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(r_count == i_count)
-
- self.console.destroy(10)
-
-
- def test_managed_obj(self):
- # create console
- # find agents
- # synchronous query for a managed object
- # method call on each object
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- i_count = 0
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_id(QmfQuery.TARGET_OBJECT, "01545")
- obj_list = self.console.do_query(agent, query)
-
- self.assertTrue(isinstance(obj_list, type([])))
- self.assertTrue(len(obj_list) == 1)
- obj = obj_list[0]
-
- cookie = "cookie-" + str(i_count)
- i_count += 1
- mr = obj.invoke_method("a_method",
- {"arg1": 1,
- "arg2": "Now set!",
- "arg3": 1966,
- "cookie": cookie},
- _reply_handle=cookie,
- _timeout=3)
- self.assertTrue(mr)
-
- # done, now wait for async responses
-
- r_count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- r_count += 1
- self.assertTrue(wi.get_type() == WorkItem.METHOD_RESPONSE)
- reply = wi.get_params()
- self.assertTrue(isinstance(reply, qmf2.console.MethodResult))
- self.assertTrue(reply.succeeded())
- self.assertTrue(reply.get_argument("cookie") == wi.get_handle())
-
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(r_count == i_count)
-
- self.console.destroy(10)
diff --git a/python/qmf2/tests/async_query.py b/python/qmf2/tests/async_query.py
deleted file mode 100644
index 3a9a767bf0..0000000000
--- a/python/qmf2/tests/async_query.py
+++ /dev/null
@@ -1,462 +0,0 @@
-# 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 unittest
-import logging
-from threading import Thread, Event
-
-import qpid.messaging
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData, WorkItem)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent)
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.notifier = _testNotifier()
- self.broker_url = broker_url
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
-
- # Dynamically construct a management database
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("MyPackage", "MyClass"),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"] )
- # add properties
- _schema.add_property( "index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property( "query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # These two properties can be set via the method call
- _schema.add_property( "set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # add method
- _meth = SchemaMethod( _desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- self.agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- _obj1 = QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":100, "index2":"a name"})
- _obj1.set_value("set_string", "UNSET")
- _obj1.set_value("set_int", 0)
- _obj1.set_value("query_count", 0)
- _obj1.set_value("method_call_count", 0)
- self.agent.add_object( _obj1 )
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":99,
- "index2": "another name",
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":50,
- "index2": "my name",
- "set_string": "SET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
-
- # add an "unstructured" object to the Agent
- _obj2 = QmfAgentData(self.agent, _object_id="01545")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 2)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 50)
- self.agent.add_object(_obj2)
-
- _obj2 = QmfAgentData(self.agent, _object_id="01546")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 3)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 51)
- self.agent.add_object(_obj2)
-
- _obj2 = QmfAgentData(self.agent, _object_id="01544")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 4)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 49)
- self.agent.add_object(_obj2)
-
- _obj2 = QmfAgentData(self.agent, _object_id="01543")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 4)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 48)
- self.agent.add_object(_obj2)
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- self.conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- self.conn.connect()
- self.agent.set_connection(self.conn)
- self.ready.set()
-
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- logging.error("UNEXPECTED AGENT WORKITEM RECEIVED=%s" % wi.get_type())
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- if self.conn:
- self.agent.remove_connection(10)
- self.agent.destroy(10)
-
-
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent indication interval
- self.agent_heartbeat = 1
- self.agent1 = _agentApp("agent1", self.broker, self.agent_heartbeat)
- self.agent1.start_app()
- self.agent2 = _agentApp("agent2", self.broker, self.agent_heartbeat)
- self.agent2.start_app()
-
- def tearDown(self):
- if self.agent1:
- self.agent1.stop_app()
- self.agent1 = None
- if self.agent2:
- self.agent2.stop_app()
- self.agent2 = None
-
- def test_all_schema_ids(self):
- # create console
- # find agents
- # asynchronous query for all schema ids
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # send queries
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
- rc = self.console.do_query(agent, query,
- _reply_handle=aname)
- self.assertTrue(rc)
-
- # done. Now wait for async responses
-
- count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- count += 1
- self.assertTrue(wi.get_type() == WorkItem.QUERY_COMPLETE)
- self.assertTrue(wi.get_handle() == "agent1" or
- wi.get_handle() == "agent2")
- reply = wi.get_params()
- self.assertTrue(len(reply) == 1)
- self.assertTrue(isinstance(reply[0], SchemaClassId))
- self.assertTrue(reply[0].get_package_name() == "MyPackage")
- self.assertTrue(reply[0].get_class_name() == "MyClass")
- self.console.release_workitem(wi)
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(count == 2)
- self.console.destroy(10)
-
-
-
- def test_undescribed_objs(self):
- # create console
- # find agents
- # asynchronous query for all non-schema objects
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # send queries
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT)
- rc = self.console.do_query(agent, query, _reply_handle=aname)
- self.assertTrue(rc)
-
- # done. Now wait for async responses
-
- count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- count += 1
- self.assertTrue(wi.get_type() == WorkItem.QUERY_COMPLETE)
- self.assertTrue(wi.get_handle() == "agent1" or
- wi.get_handle() == "agent2")
- reply = wi.get_params()
- self.assertTrue(len(reply) == 4)
- self.assertTrue(isinstance(reply[0], qmf2.console.QmfConsoleData))
- self.assertFalse(reply[0].is_described()) # no schema
- self.console.release_workitem(wi)
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(count == 2)
- self.console.destroy(10)
-
-
-
- def test_described_objs(self):
- # create console
- # find agents
- # asynchronous query for all schema-based objects
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- #
- t_params = {QmfData.KEY_SCHEMA_ID: SchemaClassId("MyPackage", "MyClass")}
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT, t_params)
- #
- rc = self.console.do_query(agent, query, _reply_handle=aname)
- self.assertTrue(rc)
-
- # done. Now wait for async responses
-
- count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- count += 1
- self.assertTrue(wi.get_type() == WorkItem.QUERY_COMPLETE)
- self.assertTrue(wi.get_handle() == "agent1" or
- wi.get_handle() == "agent2")
- reply = wi.get_params()
- self.assertTrue(len(reply) == 3)
- self.assertTrue(isinstance(reply[0], qmf2.console.QmfConsoleData))
- self.assertTrue(reply[0].is_described()) # has schema
- self.console.release_workitem(wi)
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(count == 2)
- # @todo test if the console has learned the corresponding schemas....
- self.console.destroy(10)
-
-
-
- def test_all_schemas(self):
- # create console
- # find agents
- # asynchronous query for all schemas
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- # test internal state using non-api calls:
- # no schemas present yet
- self.assertTrue(len(self.console._schema_cache) == 0)
- # end test
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # send queries
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA)
- rc = self.console.do_query(agent, query, _reply_handle=aname)
- self.assertTrue(rc)
-
- # done. Now wait for async responses
-
- count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- count += 1
- self.assertTrue(wi.get_type() == WorkItem.QUERY_COMPLETE)
- self.assertTrue(wi.get_handle() == "agent1" or
- wi.get_handle() == "agent2")
- reply = wi.get_params()
- self.assertTrue(len(reply) == 1)
- self.assertTrue(isinstance(reply[0], qmf2.common.SchemaObjectClass))
- self.assertTrue(reply[0].get_class_id().get_package_name() == "MyPackage")
- self.assertTrue(reply[0].get_class_id().get_class_name() == "MyClass")
- self.console.release_workitem(wi)
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(count == 2)
-
- # test internal state using non-api calls:
- # schema has been learned
- self.assertTrue(len(self.console._schema_cache) == 1)
- # end test
-
- self.console.destroy(10)
-
-
-
- def test_query_expiration(self):
- # create console
- # find agents
- # kill the agents
- # send async query
- # wait for & verify expiration
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=30)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- # find the agents
- agents = []
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
- agents.append(agent)
-
- # now nuke the agents from orbit. It's the only way to be sure.
-
- self.agent1.stop_app()
- self.agent1 = None
- self.agent2.stop_app()
- self.agent2 = None
-
- # now send queries to agents that no longer exist
- for agent in agents:
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA)
- rc = self.console.do_query(agent, query,
- _reply_handle=agent.get_name(),
- _timeout=2)
- self.assertTrue(rc)
-
- # done. Now wait for async responses due to timeouts
-
- count = 0
- while self.notifier.wait_for_work(3):
- wi = self.console.get_next_workitem(timeout=0)
- while wi is not None:
- count += 1
- self.assertTrue(wi.get_type() == WorkItem.QUERY_COMPLETE)
- self.assertTrue(wi.get_handle() == "agent1" or
- wi.get_handle() == "agent2")
- reply = wi.get_params()
- self.assertTrue(len(reply) == 0) # empty
-
- self.console.release_workitem(wi)
- wi = self.console.get_next_workitem(timeout=0)
-
- self.assertTrue(count == 2)
- self.console.destroy(10)
diff --git a/python/qmf2/tests/basic_method.py b/python/qmf2/tests/basic_method.py
deleted file mode 100644
index be2bdff9ab..0000000000
--- a/python/qmf2/tests/basic_method.py
+++ /dev/null
@@ -1,406 +0,0 @@
-# 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 unittest
-import logging
-from threading import Thread, Event
-
-import qpid.messaging
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData, WorkItem)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent, MethodCallParams)
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.notifier = _testNotifier()
- self.broker_url = broker_url
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
-
- # Dynamically construct a management database
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("MyPackage", "MyClass"),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"] )
- # add properties
- _schema.add_property( "index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property( "query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # These two properties can be set via the method call
- _schema.add_property( "set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # add method
- _meth = SchemaMethod( _desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- self.agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- _obj1 = QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":100, "index2":"a name"})
- _obj1.set_value("set_string", "UNSET")
- _obj1.set_value("set_int", 0)
- _obj1.set_value("query_count", 0)
- _obj1.set_value("method_call_count", 0)
- self.agent.add_object( _obj1 )
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":99,
- "index2": "another name",
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
- # add an "unstructured" object to the Agent
- _obj2 = QmfAgentData(self.agent, _object_id="01545")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 2)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- self.agent.add_object(_obj2)
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- self.conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- self.conn.connect()
- self.agent.set_connection(self.conn)
- self.ready.set()
-
- # Agent application main processing loop
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- if wi.get_type() == WorkItem.METHOD_CALL:
- mc = wi.get_params()
- if not isinstance(mc, MethodCallParams):
- raise Exception("Unexpected method call parameters")
-
- if mc.get_name() == "set_meth":
- obj = self.agent.get_object(mc.get_object_id(),
- mc.get_schema_id())
- if obj is None:
- error_info = QmfData.create({"code": -2,
- "description":
- "Bad Object Id."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- else:
- obj.inc_value("method_call_count")
- if "arg_int" in mc.get_args():
- obj.set_value("set_int", mc.get_args()["arg_int"])
- if "arg_str" in mc.get_args():
- obj.set_value("set_string", mc.get_args()["arg_str"])
- self.agent.method_response(wi.get_handle(),
- {"code" : 0})
- elif mc.get_name() == "a_method":
- obj = self.agent.get_object(mc.get_object_id(),
- mc.get_schema_id())
- if obj is None:
- error_info = QmfData.create({"code": -3,
- "description":
- "Unknown object id."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- elif obj.get_object_id() != "01545":
- error_info = QmfData.create( {"code": -4,
- "description":
- "Unexpected id."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- else:
- args = mc.get_args()
- if ("arg1" in args and args["arg1"] == 1 and
- "arg2" in args and args["arg2"] == "Now set!"
- and "arg3" in args and args["arg3"] == 1966):
- self.agent.method_response(wi.get_handle(),
- {"code" : 0})
- else:
- error_info = QmfData.create(
- {"code": -5,
- "description":
- "Bad Args."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(),
- _error=error_info)
- else:
- error_info = QmfData.create( {"code": -1,
- "description":
- "Unknown method call."},
- _object_id="_error")
- self.agent.method_response(wi.get_handle(), _error=error_info)
-
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- if self.conn:
- self.agent.remove_connection(10)
- self.agent.destroy(10)
-
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent heartbeat interval
- self.agent_heartbeat = 1
- self.agent1 = _agentApp("agent1", self.broker, self.agent_heartbeat)
- self.agent1.start_app()
- self.agent2 = _agentApp("agent2", self.broker, self.agent_heartbeat)
- self.agent2.start_app()
-
- def tearDown(self):
- if self.agent1:
- self.agent1.stop_app()
- self.agent1 = None
- if self.agent2:
- self.agent2.stop_app()
- self.agent2 = None
-
- def test_described_obj(self):
- # create console
- # find agents
- # synchronous query for all objects in schema
- # method call on each object
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
-
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == 1)
- for sid in sid_list:
- t_params = {QmfData.KEY_SCHEMA_ID: sid}
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT,
- _target_params=t_params)
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 2)
- for obj in obj_list:
- mr = obj.invoke_method( "set_meth", {"arg_int": -99,
- "arg_str": "Now set!"},
- _timeout=3)
- self.assertTrue(isinstance(mr, qmf2.console.MethodResult))
- self.assertTrue(mr.succeeded())
- self.assertTrue(mr.get_argument("code") == 0)
-
- self.assertTrue(obj.get_value("method_call_count") == 0)
- self.assertTrue(obj.get_value("set_string") == "UNSET")
- self.assertTrue(obj.get_value("set_int") == 0)
-
- obj.refresh()
-
- self.assertTrue(obj.get_value("method_call_count") == 1)
- self.assertTrue(obj.get_value("set_string") == "Now set!")
- self.assertTrue(obj.get_value("set_int") == -99)
-
- self.console.destroy(10)
-
-
- def test_bad_method_schema(self):
- # create console
- # find agents
- # synchronous query for all objects with schema
- # invalid method call on each object
- # - should throw a ValueError - NOT YET.
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
-
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == 1)
- for sid in sid_list:
-
- t_params = {QmfData.KEY_SCHEMA_ID: sid}
- query = QmfQuery.create_predicate(QmfQuery.TARGET_OBJECT,
- [QmfQuery.TRUE],
- _target_params=t_params)
-
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 2)
- for obj in obj_list:
- mr = obj.invoke_method("unknown_method",
- {"arg1": -99, "arg2": "Now set!"},
- _timeout=3)
- # self.failUnlessRaises(ValueError,
- # obj.invoke_method,
- # "unknown_meth",
- # {"arg1": -99, "arg2": "Now set!"},
- # _timeout=3)
- self.assertTrue(isinstance(mr, qmf2.console.MethodResult))
- self.assertFalse(mr.succeeded())
- self.assertTrue(isinstance(mr.get_exception(), QmfData))
-
- self.console.destroy(10)
-
- def test_bad_method_no_schema(self):
- # create console
- # find agents
- # synchronous query for all objects with no schema
- # invalid method call on each object
- # - should throw a ValueError
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT)
-
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 1)
- for obj in obj_list:
- self.assertTrue(obj.get_schema_class_id() == None)
- mr = obj.invoke_method("unknown_meth",
- {"arg1": -99, "arg2": "Now set!"},
- _timeout=3)
- self.assertTrue(isinstance(mr, qmf2.console.MethodResult))
- self.assertFalse(mr.succeeded())
- self.assertTrue(isinstance(mr.get_exception(), QmfData))
-
- self.console.destroy(10)
-
- def test_managed_obj(self):
- # create console
- # find agents
- # synchronous query for a managed object
- # method call on each object
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_id(QmfQuery.TARGET_OBJECT, "01545")
- obj_list = self.console.do_query(agent, query)
-
- self.assertTrue(isinstance(obj_list, type([])))
- self.assertTrue(len(obj_list) == 1)
- obj = obj_list[0]
-
- mr = obj.invoke_method("a_method",
- {"arg1": 1,
- "arg2": "Now set!",
- "arg3": 1966},
- _timeout=3)
- self.assertTrue(isinstance(mr, qmf2.console.MethodResult))
- self.assertTrue(mr.succeeded())
- self.assertTrue(mr.get_argument("code") == 0)
- # @todo refresh and verify changes
-
- self.console.destroy(10)
diff --git a/python/qmf2/tests/basic_query.py b/python/qmf2/tests/basic_query.py
deleted file mode 100644
index dd321cb4bb..0000000000
--- a/python/qmf2/tests/basic_query.py
+++ /dev/null
@@ -1,516 +0,0 @@
-# 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 unittest
-import logging
-from threading import Thread, Event
-
-import qpid.messaging
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent)
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.notifier = _testNotifier()
- self.broker_url = broker_url
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
-
- # Dynamically construct a management database
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("MyPackage", "MyClass"),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"] )
- # add properties
- _schema.add_property( "index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property( "query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # These two properties can be set via the method call
- _schema.add_property( "set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # add method
- _meth = SchemaMethod( _desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- self.agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- _obj1 = QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":100, "index2":"a name"})
- _obj1.set_value("set_string", "UNSET")
- _obj1.set_value("set_int", 0)
- _obj1.set_value("query_count", 0)
- _obj1.set_value("method_call_count", 0)
- self.agent.add_object( _obj1 )
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":99,
- "index2": "another name",
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":50,
- "index2": "my name",
- "set_string": "SET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
-
- # add an "unstructured" object to the Agent
- _obj2 = QmfAgentData(self.agent, _object_id="01545")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 2)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 50)
- self.agent.add_object(_obj2)
-
- _obj2 = QmfAgentData(self.agent, _object_id="01546")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 3)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 51)
- self.agent.add_object(_obj2)
-
- _obj2 = QmfAgentData(self.agent, _object_id="01544")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 4)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 49)
- self.agent.add_object(_obj2)
-
- _obj2 = QmfAgentData(self.agent, _object_id="01543")
- _obj2.set_value("field1", "a value")
- _obj2.set_value("field2", 4)
- _obj2.set_value("field3", {"a":1, "map":2, "value":3})
- _obj2.set_value("field4", ["a", "list", "value"])
- _obj2.set_value("index1", 48)
- self.agent.add_object(_obj2)
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- self.conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- self.conn.connect()
- self.agent.set_connection(self.conn)
- self.ready.set()
-
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- logging.error("UNEXPECTED AGENT WORKITEM RECEIVED=%s" % wi.get_type())
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- if self.conn:
- self.agent.remove_connection(10)
- self.agent.destroy(10)
-
-
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent indication interval
- self.agent_heartbeat = 1
- self.agent1 = _agentApp("agent1", self.broker, self.agent_heartbeat)
- self.agent1.start_app()
- self.agent2 = _agentApp("agent2", self.broker, self.agent_heartbeat)
- self.agent2.start_app()
-
- def tearDown(self):
- if self.agent1:
- self.agent1.stop_app()
- self.agent1 = None
- if self.agent2:
- self.agent2.stop_app()
- self.agent2 = None
-
- def test_all_oids(self):
- # create console
- # find agents
- # synchronous query for all schemas
- # synchronous query for all objects per schema
- # verify known object ids are returned
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # first, find objects per schema
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == 1)
- for sid in sid_list:
- t_params = {QmfData.KEY_SCHEMA_ID: sid}
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT_ID,
- _target_params=t_params)
-
- oid_list = self.console.do_query(agent, query)
-
- self.assertTrue(isinstance(oid_list, type([])),
- "Unexpected return type")
- self.assertTrue(len(oid_list) == 3, "Wrong count")
- self.assertTrue('100a name' in oid_list)
- self.assertTrue('99another name' in oid_list)
- self.assertTrue('50my name' in oid_list)
- self.assertTrue('01545' not in oid_list)
-
-
- # now, find all unmanaged objects (no schema)
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT_ID)
- oid_list = self.console.do_query(agent, query)
-
- self.assertTrue(isinstance(oid_list, type([])),
- "Unexpected return type")
- self.assertTrue(len(oid_list) == 4, "Wrong count")
- self.assertTrue('100a name' not in oid_list)
- self.assertTrue('99another name' not in oid_list)
- self.assertTrue('01545' in oid_list)
- self.assertTrue('01544' in oid_list)
- self.assertTrue('01543' in oid_list)
- self.assertTrue('01546' in oid_list)
-
- self.console.destroy(10)
-
-
- def test_direct_oids(self):
- # create console
- # find agents
- # synchronous query for each objects
- # verify objects and schemas are correct
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # first, find objects per schema
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == 1)
-
- for oid in ['100a name', '99another name']:
- query = QmfQuery.create_id_object(oid, sid_list[0])
- obj_list = self.console.do_query(agent, query)
-
- self.assertTrue(isinstance(obj_list, type([])),
- "Unexpected return type")
- self.assertTrue(len(obj_list) == 1)
- obj = obj_list[0]
- self.assertTrue(isinstance(obj, QmfData))
- self.assertTrue(obj.get_object_id() == oid)
- self.assertTrue(obj.get_schema_class_id() == sid_list[0])
- schema_id = obj.get_schema_class_id()
- self.assertTrue(isinstance(schema_id, SchemaClassId))
- self.assertTrue(obj.is_described())
-
- # now find schema-less objects
- for oid in ['01545']:
- query = QmfQuery.create_id_object(oid)
- obj_list = self.console.do_query(agent, query)
-
- self.assertTrue(isinstance(obj_list, type([])),
- "Unexpected return type")
- self.assertTrue(len(obj_list) == 1)
- obj = obj_list[0]
- self.assertTrue(isinstance(obj, QmfData))
- self.assertTrue(obj.get_object_id() == oid)
- self.assertFalse(obj.is_described())
-
- self.console.destroy(10)
-
-
-
- def test_packages(self):
- # create console
- # find agents
- # synchronous query all package names
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_PACKAGES)
- package_list = self.console.do_query(agent, query)
- self.assertTrue(len(package_list) == 1)
- self.assertTrue('MyPackage' in package_list)
-
-
- self.console.destroy(10)
-
-
-
- def test_predicate_schema_id(self):
- # create console
- # find agents
- # synchronous query for all schema by package name
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_predicate(QmfQuery.TARGET_SCHEMA,
- [QmfQuery.EQ,
- SchemaClassId.KEY_PACKAGE,
- [QmfQuery.QUOTE, "MyPackage"]])
-
- schema_list = self.console.do_query(agent, query)
- self.assertTrue(len(schema_list))
- for schema in schema_list:
- self.assertTrue(schema.get_class_id().get_package_name() ==
- "MyPackage")
-
-
- self.console.destroy(10)
-
-
-
- def test_predicate_no_match(self):
- # create console
- # find agents
- # synchronous query for all schema by package name
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- query = QmfQuery.create_predicate(QmfQuery.TARGET_SCHEMA,
- [QmfQuery.EQ,
- [QmfQuery.UNQUOTE, SchemaClassId.KEY_PACKAGE],
- [QmfQuery.QUOTE, "No-Such-Package"]])
-
- schema_list = self.console.do_query(agent, query)
- self.assertTrue(len(schema_list) == 0)
-
- self.console.destroy(10)
-
-
- def test_predicate_match_string(self):
- # create console
- # find agents
- # synchronous query for all objects with a value named
- # set_string which is < or equal to "UNSET"
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # get the schema id for MyPackage:MyClass schema
- query = QmfQuery.create_predicate(QmfQuery.TARGET_SCHEMA_ID,
- [QmfQuery.AND,
- [QmfQuery.EQ, SchemaClassId.KEY_PACKAGE,
- [QmfQuery.QUOTE, "MyPackage"]],
- [QmfQuery.EQ, SchemaClassId.KEY_CLASS,
- [QmfQuery.QUOTE, "MyClass"]]])
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(len(sid_list) == 1)
-
- query = QmfQuery.create_predicate(QmfQuery.TARGET_OBJECT,
- [QmfQuery.AND,
- [QmfQuery.EXISTS, [QmfQuery.QUOTE, "set_string"]],
- [QmfQuery.EQ, "set_string", [QmfQuery.QUOTE, "UNSET"]]],
- _target_params={QmfData.KEY_SCHEMA_ID: sid_list[0]})
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 2)
- for obj in obj_list:
- self.assertTrue(obj.has_value("set_string"))
- self.assertTrue(obj.get_value("set_string") == "UNSET")
-
- self.console.destroy(10)
-
-
-
- def test_predicate_match_integer(self):
- # create console
- # find agents
- # synchronous query for all objects with a value named
- # "index1" which is < or equal to various values
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # Query the unmanaged (no schema) objects
-
- # == 50
- query = QmfQuery.create_predicate(QmfQuery.TARGET_OBJECT,
- [QmfQuery.AND,
- [QmfQuery.EXISTS, [QmfQuery.QUOTE, "index1"]],
- [QmfQuery.EQ, "index1", 50]])
-
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 1)
- self.assertTrue(obj_list[0].has_value("index1"))
- self.assertTrue(obj_list[0].get_value("index1") == 50)
-
- # <= 50
- query = QmfQuery.create_predicate(QmfQuery.TARGET_OBJECT,
- [QmfQuery.AND,
- [QmfQuery.EXISTS, [QmfQuery.QUOTE, "index1"]],
- [QmfQuery.LE, "index1", 50]])
-
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 3)
- for obj in obj_list:
- self.assertTrue(obj.has_value("index1"))
- self.assertTrue(obj.get_value("index1") <= 50)
-
-
- # > 50
- query = QmfQuery.create_predicate(QmfQuery.TARGET_OBJECT,
- [QmfQuery.AND,
- [QmfQuery.EXISTS, [QmfQuery.QUOTE, "index1"]],
- [QmfQuery.GT, "index1", 50]])
-
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(len(obj_list) == 1)
- for obj in obj_list:
- self.assertTrue(obj.has_value("index1"))
- self.assertTrue(obj.get_value("index1") > 50)
-
- self.console.destroy(10)
-
diff --git a/python/qmf2/tests/console_test.py b/python/qmf2/tests/console_test.py
deleted file mode 100644
index ac0e064f20..0000000000
--- a/python/qmf2/tests/console_test.py
+++ /dev/null
@@ -1,175 +0,0 @@
-# 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 logging
-import time
-from threading import Semaphore
-
-
-from qpid.messaging import *
-from qmf2.common import (Notifier, QmfQuery, QmfQueryPredicate, MsgKey,
- SchemaClassId, SchemaClass, QmfData)
-from qmf2.console import Console
-
-
-class ExampleNotifier(Notifier):
- def __init__(self):
- self._sema4 = Semaphore(0) # locked
-
- def indication(self):
- self._sema4.release()
-
- def waitForWork(self):
- print("Waiting for event...")
- self._sema4.acquire()
- print("...event present")
-
-
-logging.getLogger().setLevel(logging.INFO)
-
-print( "Starting Connection" )
-_c = Connection("localhost")
-_c.connect()
-
-print( "Starting Console" )
-
-_notifier = ExampleNotifier()
-_myConsole = Console(notifier=_notifier)
-_myConsole.addConnection( _c )
-
-# Allow discovery only for the agent named "qmf.testAgent"
-# @todo: replace "manual" query construction with
-# a formal class-based Query API
-_query = QmfQuery.create_predicate(QmfQuery.TARGET_AGENT,
- QmfQueryPredicate({QmfQuery.CMP_EQ:
- [QmfQuery.KEY_AGENT_NAME,
- "qmf.testAgent"]}))
-_myConsole.enable_agent_discovery(_query)
-
-_done = False
-while not _done:
-# try:
- _notifier.waitForWork()
-
- _wi = _myConsole.get_next_workitem(timeout=0)
- while _wi:
- print("!!! work item received %d:%s" % (_wi.get_type(),
- str(_wi.get_params())))
-
-
- if _wi.get_type() == _wi.AGENT_ADDED:
- _agent = _wi.get_params().get("agent")
- if not _agent:
- print("!!!! AGENT IN REPLY IS NULL !!! ")
-
- _query = QmfQuery.create_wildcard(QmfQuery.TARGET_OBJECT_ID)
- oid_list = _myConsole.doQuery(_agent, _query)
-
- print("!!!************************** REPLY=%s" % oid_list)
-
- for oid in oid_list:
- _query = QmfQuery.create_id(QmfQuery.TARGET_OBJECT,
- oid)
- obj_list = _myConsole.doQuery(_agent, _query)
-
- print("!!!************************** REPLY=%s" % obj_list)
-
- if obj_list is None:
- obj_list={}
-
- for obj in obj_list:
- resp = obj.invoke_method( "set_meth",
- {"arg_int": -11,
- "arg_str": "are we not goons?"},
- None,
- 3)
- if resp is None:
- print("!!!*** NO RESPONSE FROM METHOD????")
- else:
- print("!!! method succeeded()=%s" % resp.succeeded())
- print("!!! method exception()=%s" % resp.get_exception())
- print("!!! method get args() = %s" % resp.get_arguments())
-
- if not obj.is_described():
- resp = obj.invoke_method( "bad method",
- {"arg_int": -11,
- "arg_str": "are we not goons?"},
- None,
- 3)
- if resp is None:
- print("!!!*** NO RESPONSE FROM METHOD????")
- else:
- print("!!! method succeeded()=%s" % resp.succeeded())
- print("!!! method exception()=%s" % resp.get_exception())
- print("!!! method get args() = %s" % resp.get_arguments())
-
-
- #---------------------------------
- #_query = QmfQuery.create_id(QmfQuery.TARGET_OBJECT, "99another name")
-
- #obj_list = _myConsole.doQuery(_agent, _query)
-
- #---------------------------------
-
- # _query = QmfQuery.create_wildcard(QmfQuery.TARGET_PACKAGES)
-
- # package_list = _myConsole.doQuery(_agent, _query)
-
- # for pname in package_list:
- # print("!!! Querying for schema from package: %s" % pname)
- # _query = QmfQuery.create_predicate(QmfQuery.TARGET_SCHEMA_ID,
- # QmfQueryPredicate(
- # {QmfQuery.CMP_EQ: [SchemaClassId.KEY_PACKAGE, pname]}))
-
- # schema_id_list = _myConsole.doQuery(_agent, _query)
- # for sid in schema_id_list:
- # _query = QmfQuery.create_predicate(QmfQuery.TARGET_SCHEMA,
- # QmfQueryPredicate(
- # {QmfQuery.CMP_EQ: [SchemaClass.KEY_SCHEMA_ID,
- # sid.map_encode()]}))
-
- # schema_list = _myConsole.doQuery(_agent, _query)
- # for schema in schema_list:
- # sid = schema.get_class_id()
- # _query = QmfQuery.create_predicate(
- # QmfQuery.TARGET_OBJECT_ID,
- # QmfQueryPredicate({QmfQuery.CMP_EQ:
- # [QmfData.KEY_SCHEMA_ID,
- # sid.map_encode()]}))
-
- # oid_list = _myConsole.doQuery(_agent, _query)
- # for oid in oid_list:
- # _query = QmfQuery.create_id(
- # QmfQuery.TARGET_OBJECT, oid)
- # _reply = _myConsole.doQuery(_agent, _query)
-
- # print("!!!************************** REPLY=%s" % _reply)
-
-
- _myConsole.release_workitem(_wi)
- _wi = _myConsole.get_next_workitem(timeout=0)
-# except:
-# logging.info( "shutting down..." )
-# _done = True
-
-print( "Removing connection" )
-_myConsole.removeConnection( _c, 10 )
-
-print( "Destroying console:" )
-_myConsole.destroy( 10 )
-
-print( "******** console test done ********" )
diff --git a/python/qmf2/tests/events.py b/python/qmf2/tests/events.py
deleted file mode 100644
index e55dc8572e..0000000000
--- a/python/qmf2/tests/events.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# 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 unittest
-import time
-import datetime
-import logging
-from threading import Thread, Event
-
-import qpid.messaging
-from qpid.harness import Skipped
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData, SchemaEventClass,
- QmfEvent)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent)
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.timeout = 3
- self.broker_url = broker_url
- self.notifier = _testNotifier()
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
-
- # Dynamically construct a management database
-
- _schema = SchemaEventClass(_classId=SchemaClassId("MyPackage",
- "MyClass",
- stype=SchemaClassId.TYPE_EVENT),
- _desc="A test event schema")
- # add properties
- _schema.add_property( "prop-1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "prop-2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # Add schema to Agent
- self.schema = _schema
- self.agent.register_object_class(_schema)
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
- # time.sleep(1)
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(self.timeout)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- try:
- conn.connect()
- except qpid.messaging.ConnectError, e:
- raise Skipped(e)
-
- self.agent.set_connection(conn)
- self.ready.set()
-
- counter = 1
- while self.running:
- # post an event every second
- event = QmfEvent.create(long(time.time() * 1000),
- QmfEvent.SEV_WARNING,
- {"prop-1": counter,
- "prop-2": str(datetime.datetime.utcnow())},
- _schema_id=self.schema.get_class_id())
- counter += 1
- self.agent.raise_event(event)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- logging.error("UNEXPECTED AGENT WORKITEM RECEIVED=%s" % wi.get_type())
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
- self.notifier.wait_for_work(1)
-
- self.agent.remove_connection(self.timeout)
- self.agent.destroy(self.timeout)
-
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent indication interval
- self.agent1 = _agentApp("agent1", self.broker, 1)
- self.agent1.start_app()
- self.agent2 = _agentApp("agent2", self.broker, 1)
- self.agent2.start_app()
-
- def tearDown(self):
- if self.agent1:
- self.agent1.stop_app()
- self.agent1 = None
- if self.agent2:
- self.agent2.stop_app()
- self.agent2 = None
-
- def test_get_events(self):
- # create console
- # find agents
-
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- try:
- self.conn.connect()
- except qpid.messaging.ConnectError, e:
- raise Skipped(e)
-
- self.console.add_connection(self.conn)
-
- # find the agents
- for aname in ["agent1", "agent2"]:
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # now wait for events
- agent1_events = agent2_events = 0
- wi = self.console.get_next_workitem(timeout=4)
- while wi:
- if wi.get_type() == wi.EVENT_RECEIVED:
- event = wi.get_params().get("event")
- self.assertTrue(isinstance(event, QmfEvent))
- self.assertTrue(event.get_severity() == QmfEvent.SEV_WARNING)
- self.assertTrue(event.get_value("prop-1") > 0)
-
- agent = wi.get_params().get("agent")
- if not agent or not isinstance(agent, qmf2.console.Agent):
- self.fail("Unexpected workitem from agent")
- else:
- if agent.get_name() == "agent1":
- agent1_events += 1
- elif agent.get_name() == "agent2":
- agent2_events += 1
- else:
- self.fail("Unexpected agent name received: %s" %
- agent.get_name())
- if agent1_events and agent2_events:
- break;
-
- wi = self.console.get_next_workitem(timeout=4)
-
- self.assertTrue(agent1_events > 0 and agent2_events > 0)
-
- self.console.destroy(10)
-
-
-
-
diff --git a/python/qmf2/tests/multi_response.py b/python/qmf2/tests/multi_response.py
deleted file mode 100644
index d3d00a70c5..0000000000
--- a/python/qmf2/tests/multi_response.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# 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 unittest
-import logging
-from threading import Thread, Event
-
-import qpid.messaging
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent)
-
-# note: objects, schema per agent must each be > max objs
-_SCHEMAS_PER_AGENT=7
-_OBJS_PER_AGENT=19
-_MAX_OBJS_PER_MSG=3
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.schema_count = _SCHEMAS_PER_AGENT
- self.obj_count = _OBJS_PER_AGENT
- self.notifier = _testNotifier()
- self.broker_url = broker_url
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat,
- _max_msg_size=_MAX_OBJS_PER_MSG)
-
- # Dynamically construct a management database
- for i in range(self.schema_count):
- _schema = SchemaObjectClass( _classId=SchemaClassId("MyPackage",
- "MyClass-" + str(i)),
- _desc="A test data schema",
- _object_id_names=["index1", "index2"] )
- # add properties
- _schema.add_property( "index1", SchemaProperty(qmfTypes.TYPE_UINT8))
- _schema.add_property( "index2", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- # these two properties are statistics
- _schema.add_property( "query_count", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "method_call_count", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # These two properties can be set via the method call
- _schema.add_property( "set_string", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "set_int", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- # add method
- _meth = SchemaMethod( _desc="Method to set string and int in object." )
- _meth.add_argument( "arg_int", SchemaProperty(qmfTypes.TYPE_UINT32) )
- _meth.add_argument( "arg_str", SchemaProperty(qmfTypes.TYPE_LSTR) )
- _schema.add_method( "set_meth", _meth )
-
- # Add schema to Agent
-
- self.agent.register_object_class(_schema)
-
- # instantiate managed data objects matching the schema
-
- for j in range(self.obj_count):
-
- self.agent.add_object( QmfAgentData( self.agent, _schema=_schema,
- _values={"index1":j,
- "index2": "name-" + str(j),
- "set_string": "UNSET",
- "set_int": 0,
- "query_count": 0,
- "method_call_count": 0} ))
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- # wake main thread
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- self.conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- self.conn.connect()
- self.agent.set_connection(self.conn)
- self.ready.set()
-
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- logging.error("UNEXPECTED AGENT WORKITEM RECEIVED=%s" % wi.get_type())
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- if self.conn:
- self.agent.remove_connection(10)
- self.agent.destroy(10)
-
-
-
-
-class BaseTest(unittest.TestCase):
- def configure(self, config):
- self.agent_count = 2
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- # one second agent indication interval
- self.agent_heartbeat = 1
- self.agents = []
- for a in range(self.agent_count):
- agent = _agentApp("agent-" + str(a),
- self.broker,
- self.agent_heartbeat)
- agent.start_app()
- self.agents.append(agent)
-
- def tearDown(self):
- for agent in self.agents:
- if agent is not None:
- agent.stop_app()
-
- def test_all_schema_id(self):
- # create console
- # find agents
- # synchronous query for all schemas_ids
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- agent = self.console.find_agent(agent_app.agent.get_name(), timeout=3)
- self.assertTrue(agent and agent.get_name() == agent_app.agent.get_name())
-
- # get a list of all schema_ids
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == _SCHEMAS_PER_AGENT)
- for sid in sid_list:
- self.assertTrue(isinstance(sid, SchemaClassId))
- self.assertTrue(sid.get_package_name() == "MyPackage")
- self.assertTrue(sid.get_class_name().split('-')[0] == "MyClass")
-
- self.console.destroy(10)
-
-
- def test_all_schema(self):
- # create console
- # find agents
- # synchronous query for all schemas
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- agent = self.console.find_agent(agent_app.agent.get_name(), timeout=3)
- self.assertTrue(agent and agent.get_name() == agent_app.agent.get_name())
-
- # get a list of all schema_ids
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA)
- schema_list = self.console.do_query(agent, query)
- self.assertTrue(schema_list and
- len(schema_list) == _SCHEMAS_PER_AGENT)
- for schema in schema_list:
- self.assertTrue(isinstance(schema, SchemaObjectClass))
-
- self.console.destroy(10)
-
-
- def test_all_object_id(self):
- # create console
- # find agents
- # synchronous query for all object_ids by schema_id
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- agent = self.console.find_agent(agent_app.agent.get_name(), timeout=3)
- self.assertTrue(agent and agent.get_name() == agent_app.agent.get_name())
-
- # get a list of all schema_ids
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == _SCHEMAS_PER_AGENT)
- for sid in sid_list:
- query = QmfQuery.create_wildcard_object_id(sid)
- oid_list = self.console.do_query(agent, query)
- self.assertTrue(oid_list and
- len(oid_list) == _OBJS_PER_AGENT)
- for oid in oid_list:
- self.assertTrue(isinstance(oid, basestring))
-
- self.console.destroy(10)
-
-
- def test_all_objects(self):
- # create console
- # find agents
- # synchronous query for all objects by schema_id
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- agent = self.console.find_agent(agent_app.agent.get_name(), timeout=3)
- self.assertTrue(agent and agent.get_name() == agent_app.agent.get_name())
-
- # get a list of all schema_ids
- query = QmfQuery.create_wildcard(QmfQuery.TARGET_SCHEMA_ID)
- sid_list = self.console.do_query(agent, query)
- self.assertTrue(sid_list and len(sid_list) == _SCHEMAS_PER_AGENT)
- for sid in sid_list:
- query = QmfQuery.create_wildcard_object(sid)
- obj_list = self.console.do_query(agent, query)
- self.assertTrue(obj_list and
- len(obj_list) == _OBJS_PER_AGENT)
- for obj in obj_list:
- self.assertTrue(isinstance(obj,
- qmf2.console.QmfConsoleData))
-
- self.console.destroy(10)
diff --git a/python/qmf2/tests/obj_gets.py b/python/qmf2/tests/obj_gets.py
deleted file mode 100644
index 5b1446bb3a..0000000000
--- a/python/qmf2/tests/obj_gets.py
+++ /dev/null
@@ -1,599 +0,0 @@
-# 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 unittest
-import logging
-import datetime
-from threading import Thread, Event
-
-import qpid.messaging
-from qmf2.common import (Notifier, SchemaObjectClass, SchemaClassId,
- SchemaProperty, qmfTypes, SchemaMethod, QmfQuery,
- QmfData)
-import qmf2.console
-from qmf2.agent import(QmfAgentData, Agent)
-
-
-class _testNotifier(Notifier):
- def __init__(self):
- self._event = Event()
-
- def indication(self):
- # note: called by qmf daemon thread
- self._event.set()
-
- def wait_for_work(self, timeout):
- # note: called by application thread to wait
- # for qmf to generate work
- self._event.wait(timeout)
- timed_out = self._event.isSet() == False
- if not timed_out:
- self._event.clear()
- return True
- return False
-
-
-class _agentApp(Thread):
- def __init__(self, name, broker_url, heartbeat):
- Thread.__init__(self)
- self.notifier = _testNotifier()
- self.broker_url = broker_url
- self.agent = Agent(name,
- _notifier=self.notifier,
- _heartbeat_interval=heartbeat)
-
- # Management Database
- # - two different schema packages,
- # - two classes within one schema package
- # - multiple objects per schema package+class
- # - two "undescribed" objects
-
- # "package1/class1"
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("package1", "class1"),
- _desc="A test data schema - one",
- _object_id_names=["key"] )
-
- _schema.add_property( "key", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "count1", SchemaProperty(qmfTypes.TYPE_UINT32))
- _schema.add_property( "count2", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- self.agent.register_object_class(_schema)
-
- _obj = QmfAgentData( self.agent,
- _values={"key":"p1c1_key1"},
- _schema=_schema)
- _obj.set_value("count1", 0)
- _obj.set_value("count2", 0)
- self.agent.add_object( _obj )
-
- _obj = QmfAgentData( self.agent,
- _values={"key":"p1c1_key2"},
- _schema=_schema )
- _obj.set_value("count1", 9)
- _obj.set_value("count2", 10)
- self.agent.add_object( _obj )
-
- # "package1/class2"
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("package1", "class2"),
- _desc="A test data schema - two",
- _object_id_names=["name"] )
- # add properties
- _schema.add_property( "name", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "string1", SchemaProperty(qmfTypes.TYPE_LSTR))
-
- self.agent.register_object_class(_schema)
-
- _obj = QmfAgentData( self.agent,
- _values={"name":"p1c2_name1"},
- _schema=_schema )
- _obj.set_value("string1", "a data string")
- self.agent.add_object( _obj )
-
-
- # "package2/class1"
-
- _schema = SchemaObjectClass( _classId=SchemaClassId("package2", "class1"),
- _desc="A test data schema - second package",
- _object_id_names=["key"] )
-
- _schema.add_property( "key", SchemaProperty(qmfTypes.TYPE_LSTR))
- _schema.add_property( "counter", SchemaProperty(qmfTypes.TYPE_UINT32))
-
- self.agent.register_object_class(_schema)
-
- _obj = QmfAgentData( self.agent,
- _values={"key":"p2c1_key1"},
- _schema=_schema )
- _obj.set_value("counter", 0)
- self.agent.add_object( _obj )
-
- _obj = QmfAgentData( self.agent,
- _values={"key":"p2c1_key2"},
- _schema=_schema )
- _obj.set_value("counter", 2112)
- self.agent.add_object( _obj )
-
-
- # add two "unstructured" objects to the Agent
-
- _obj = QmfAgentData(self.agent, _object_id="undesc-1")
- _obj.set_value("field1", "a value")
- _obj.set_value("field2", 2)
- _obj.set_value("field3", {"a":1, "map":2, "value":3})
- _obj.set_value("field4", ["a", "list", "value"])
- self.agent.add_object(_obj)
-
-
- _obj = QmfAgentData(self.agent, _object_id="undesc-2")
- _obj.set_value("key-1", "a value")
- _obj.set_value("key-2", 2)
- self.agent.add_object(_obj)
-
- self.running = False
- self.ready = Event()
-
- def start_app(self):
- self.running = True
- self.start()
- self.ready.wait(10)
- if not self.ready.is_set():
- raise Exception("Agent failed to connect to broker.")
-
- def stop_app(self):
- self.running = False
- self.notifier.indication() # hmmm... collide with daemon???
- self.join(10)
- if self.isAlive():
- raise Exception("AGENT DID NOT TERMINATE AS EXPECTED!!!")
-
- def run(self):
- # broker_url = "user/passwd@hostname:port"
- self.conn = qpid.messaging.Connection(self.broker_url.host,
- self.broker_url.port,
- self.broker_url.user,
- self.broker_url.password)
- self.conn.connect()
- self.agent.set_connection(self.conn)
- self.ready.set()
-
- while self.running:
- self.notifier.wait_for_work(None)
- wi = self.agent.get_next_workitem(timeout=0)
- while wi is not None:
- logging.error("UNEXPECTED AGENT WORKITEM RECEIVED=%s" % wi.get_type())
- self.agent.release_workitem(wi)
- wi = self.agent.get_next_workitem(timeout=0)
-
- if self.conn:
- self.agent.remove_connection(10)
- self.agent.destroy(10)
-
-
-class BaseTest(unittest.TestCase):
- agent_count = 5
-
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- self.agents = []
- for i in range(self.agent_count):
- agent = _agentApp("agent-" + str(i), self.broker, 1)
- agent.start_app()
- self.agents.append(agent)
- #print("!!!! STARTING TEST: %s" % datetime.datetime.utcnow())
-
- def tearDown(self):
- #print("!!!! STOPPING TEST: %s" % datetime.datetime.utcnow())
- for agent in self.agents:
- if agent is not None:
- agent.stop_app()
-
-
- def test_all_agents(self):
- # create console
- # find all agents
- # synchronous query for all objects by id
- # verify known object ids are returned
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- aname = agent_app.agent.get_name()
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # console has discovered all agents, now query all undesc-2 objects
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_object_id="undesc-2", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_object_id() == "undesc-2")
-
- # now query all objects from schema "package1"
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package1", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == (self.agent_count * 3))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
-
- # now query all objects from schema "package2"
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package2", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == (self.agent_count * 2))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package2")
-
- # now query all objects from schema "package1/class2"
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package1", _cname="class2",
- _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class2")
-
- # given the schema identifier from the last query, repeat using the
- # specific schema id
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- schema_id = objs[0].get_schema_class_id()
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_schema_id=schema_id, _timeout=5)
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id() == schema_id)
-
-
- self.console.destroy(10)
-
-
-
- def test_agent_subset(self):
- # create console
- # find all agents
- # synchronous query for all objects by id
- # verify known object ids are returned
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- agent_list = []
- for agent_app in self.agents:
- aname = agent_app.agent.get_name()
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
- agent_list.append(agent)
-
- # Only use a subset of the agents:
- agent_list = agent_list[:len(agent_list)/2]
-
- # console has discovered all agents, now query all undesc-2 objects
- objs = self.console.get_objects(_object_id="undesc-2",
- _agents=agent_list, _timeout=5)
- self.assertTrue(len(objs) == len(agent_list))
- for obj in objs:
- self.assertTrue(obj.get_object_id() == "undesc-2")
-
- # now query all objects from schema "package1"
- objs = self.console.get_objects(_pname="package1",
- _agents=agent_list,
- _timeout=5)
- self.assertTrue(len(objs) == (len(agent_list) * 3))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
-
- # now query all objects from schema "package2"
- objs = self.console.get_objects(_pname="package2",
- _agents=agent_list,
- _timeout=5)
- self.assertTrue(len(objs) == (len(agent_list) * 2))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package2")
-
- # now query all objects from schema "package1/class2"
- objs = self.console.get_objects(_pname="package1", _cname="class2",
- _agents=agent_list,
- _timeout=5)
- self.assertTrue(len(objs) == len(agent_list))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class2")
-
- # given the schema identifier from the last query, repeat using the
- # specific schema id
- schema_id = objs[0].get_schema_class_id()
- objs = self.console.get_objects(_schema_id=schema_id,
- _agents=agent_list,
- _timeout=5)
- self.assertTrue(len(objs) == len(agent_list))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id() == schema_id)
-
-
- self.console.destroy(10)
-
-
-
- def test_single_agent(self):
- # create console
- # find all agents
- # synchronous query for all objects by id
- # verify known object ids are returned
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- agent_list = []
- for agent_app in self.agents:
- aname = agent_app.agent.get_name()
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
- agent_list.append(agent)
-
- # Only use one agent
- agent = agent_list[0]
-
- # console has discovered all agents, now query all undesc-2 objects
- objs = self.console.get_objects(_object_id="undesc-2",
- _agents=agent, _timeout=5)
- self.assertTrue(len(objs) == 1)
- for obj in objs:
- self.assertTrue(obj.get_object_id() == "undesc-2")
-
- # now query all objects from schema "package1"
- objs = self.console.get_objects(_pname="package1",
- _agents=agent,
- _timeout=5)
- self.assertTrue(len(objs) == 3)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
-
- # now query all objects from schema "package2"
- objs = self.console.get_objects(_pname="package2",
- _agents=agent,
- _timeout=5)
- self.assertTrue(len(objs) == 2)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package2")
-
- # now query all objects from schema "package1/class2"
- objs = self.console.get_objects(_pname="package1", _cname="class2",
- _agents=agent,
- _timeout=5)
- self.assertTrue(len(objs) == 1)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class2")
-
- # given the schema identifier from the last query, repeat using the
- # specific schema id
- schema_id = objs[0].get_schema_class_id()
- objs = self.console.get_objects(_schema_id=schema_id,
- _agents=agent,
- _timeout=5)
- self.assertTrue(len(objs) == 1)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id() == schema_id)
-
-
- self.console.destroy(10)
-
-
-
- def test_all_objs_by_oid(self):
- # create console
- # find all agents
- # synchronous query for all described objects by:
- # oid & schema_id
- # oid & package name
- # oid & package and class name
- # verify known object ids are returned
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- aname = agent_app.agent.get_name()
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- # now query all objects from schema "package1"
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package1",
- _object_id="p1c1_key1", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
- self.assertTrue(obj.get_object_id() == "p1c1_key1")
- # mooch the schema for a later test
- schema_id_p1c1 = objs[0].get_schema_class_id()
-
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package1",
- _object_id="p1c2_name1", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class2")
- self.assertTrue(obj.get_object_id() == "p1c2_name1")
-
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package2", _cname="class1",
- _object_id="p2c1_key1", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package2")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
- self.assertTrue(obj.get_object_id() == "p2c1_key1")
-
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_schema_id=schema_id_p1c1,
- _object_id="p1c1_key2", _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
- self.assertTrue(obj.get_object_id() == "p1c1_key2")
-
- # this should return all "undescribed" objects
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(len(objs) == (self.agent_count * 2))
- for obj in objs:
- self.assertTrue(obj.get_object_id() == "undesc-1" or
- obj.get_object_id() == "undesc-2")
-
- # these should fail
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_schema_id=schema_id_p1c1,
- _object_id="does not exist",
- _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(objs == None)
-
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package2",
- _object_id="does not exist",
- _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(objs == None)
-
- #print("!!!! STARTING GET: %s" % datetime.datetime.utcnow())
- objs = self.console.get_objects(_pname="package3",
- _object_id="does not exist",
- _timeout=5)
- #print("!!!! STOPPING GET: %s" % datetime.datetime.utcnow())
- self.assertTrue(objs == None)
-
- self.console.destroy(10)
-
-
- def test_wildcard_schema_id(self):
- # create console
- # find all agents
- # synchronous query for all described objects by:
- # oid & wildcard schema_id
- # wildcard schema_id
- # verify known object ids are returned
- self.notifier = _testNotifier()
- self.console = qmf2.console.Console(notifier=self.notifier,
- agent_timeout=3)
- self.conn = qpid.messaging.Connection(self.broker.host,
- self.broker.port,
- self.broker.user,
- self.broker.password)
- self.conn.connect()
- self.console.add_connection(self.conn)
-
- for agent_app in self.agents:
- aname = agent_app.agent.get_name()
- agent = self.console.find_agent(aname, timeout=3)
- self.assertTrue(agent and agent.get_name() == aname)
-
- wild_schema_id = SchemaClassId("package1", "class1")
- objs = self.console.get_objects(_schema_id=wild_schema_id, _timeout=5)
- self.assertTrue(len(objs) == (self.agent_count * 2))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
-
- wild_schema_id = SchemaClassId("package1", "class2")
- objs = self.console.get_objects(_schema_id=wild_schema_id, _timeout=5)
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class2")
- self.assertTrue(obj.get_object_id() == "p1c2_name1")
-
- wild_schema_id = SchemaClassId("package2", "class1")
- objs = self.console.get_objects(_schema_id=wild_schema_id, _timeout=5)
- self.assertTrue(len(objs) == (self.agent_count * 2))
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package2")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
-
- wild_schema_id = SchemaClassId("package1", "class1")
- objs = self.console.get_objects(_schema_id=wild_schema_id,
- _object_id="p1c1_key2", _timeout=5)
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package1")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
- self.assertTrue(obj.get_object_id() == "p1c1_key2")
-
- # should fail
- objs = self.console.get_objects(_schema_id=wild_schema_id,
- _object_id="does not exist",
- _timeout=5)
- self.assertTrue(objs == None)
-
- wild_schema_id = SchemaClassId("package2", "class1")
- objs = self.console.get_objects(_schema_id=wild_schema_id,
- _object_id="p2c1_key2", _timeout=5)
- self.assertTrue(len(objs) == self.agent_count)
- for obj in objs:
- self.assertTrue(obj.get_schema_class_id().get_package_name() == "package2")
- self.assertTrue(obj.get_schema_class_id().get_class_name() == "class1")
- self.assertTrue(obj.get_object_id() == "p2c1_key2")
-
- # should fail
- wild_schema_id = SchemaClassId("package1", "bad-class")
- objs = self.console.get_objects(_schema_id=wild_schema_id,
- _object_id="p1c1_key2", _timeout=5)
- self.assertTrue(objs == None)
-
- self.console.destroy(10)
-
diff --git a/python/setup.py b/python/setup.py
index 5178bad0ed..2bd6e7fe0d 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -21,15 +21,8 @@ from distutils.core import setup
setup(name="qpid",
version="0.7",
- packages=["mllib", "qpid", "qpid.tests", "qmf", "qmf2", "qmf2.tests"],
- scripts=["qpid-python-test",
- "commands/qpid-cluster",
- "commands/qpid-config",
- "commands/qpid-printevents",
- "commands/qpid-queue-stats",
- "commands/qpid-route",
- "commands/qpid-stat",
- "commands/qpid-tool"],
+ packages=["mllib", "qpid", "qpid.tests"],
+ scripts=["qpid-python-test"],
url="http://qpid.apache.org/",
license="Apache Software License",
description="Python language client implementation for Apache Qpid")