From f71bb3a588ea9ebfa3ef4d05a52316ed5a039e41 Mon Sep 17 00:00:00 2001 From: Gordon Sim Date: Thu, 21 Mar 2013 18:13:34 +0000 Subject: QPID-4586: Add generic (and somewhat experimental) tool for creating, deleting and listing qpidd entities e.g. domains and incoming- or outgoing- links git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1459434 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/src/tests/CMakeLists.txt | 2 + qpid/cpp/src/tests/Makefile.am | 4 +- qpid/cpp/src/tests/qpidt | 141 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 qpid/cpp/src/tests/qpidt diff --git a/qpid/cpp/src/tests/CMakeLists.txt b/qpid/cpp/src/tests/CMakeLists.txt index f77863a146..001b5d2d69 100644 --- a/qpid/cpp/src/tests/CMakeLists.txt +++ b/qpid/cpp/src/tests/CMakeLists.txt @@ -293,6 +293,8 @@ install (TARGETS qpid-receive qpid-send qpid-topic-listener qpid-topic-publisher receiver sender qpid-txtest RUNTIME DESTINATION ${QPID_INSTALL_TESTDIR}) +install (PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/qpidt + DESTINATION ${QPID_INSTALL_TESTDIR}) # This should ideally be done as part of the test run, but I don't know a way # to get these arguments and the working directory set like Makefile.am does, diff --git a/qpid/cpp/src/tests/Makefile.am b/qpid/cpp/src/tests/Makefile.am index 2e55b24c3e..3943e21b7f 100644 --- a/qpid/cpp/src/tests/Makefile.am +++ b/qpid/cpp/src/tests/Makefile.am @@ -146,8 +146,8 @@ endif # Test programs that are installed and therefore built as part of make, not make check -qpidexectest_SCRIPTS += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh -EXTRA_DIST += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh +qpidexectest_SCRIPTS += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh qpidt +EXTRA_DIST += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh qpidt qpidexectest_PROGRAMS += receiver receiver_SOURCES = \ diff --git a/qpid/cpp/src/tests/qpidt b/qpid/cpp/src/tests/qpidt new file mode 100644 index 0000000000..5bdfb6eefd --- /dev/null +++ b/qpid/cpp/src/tests/qpidt @@ -0,0 +1,141 @@ +#!/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 pdb + +import os +from optparse import OptionParser +import sys + +home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools")) +sys.path.append(os.path.join(home, "python")) + +from qpid.messaging import Connection +from qpidtoollibs import BrokerAgent, BrokerObject + +desc = """Experimental generic configuration tool for qpidd. Note: this may be +modified or removed in subsequent releases. +""" +usage = """ + %prog [OPTIONS] create [properties] + %prog [OPTIONS] delete [arguments] + %prog [OPTIONS] list +""" +def add_nameval(m, s): + idx = s.find("=") + if idx >= 0: + name = s[0:idx] + value = s[idx+1:] + else: + name = s + value = None + m[name] = value + +class Manager: + def __init__(self): + self.parser = OptionParser(description=desc, usage=usage) + self.url = None + self.conn_options = {} + self.command = None + self.typename = None + self.name = None + self.extra = {} + self.parser.add_option("-b", "--broker", action="store", type="string", metavar="
", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:]") + self.parser.add_option("--sasl-mechanism", action="store", type="string", metavar="", help="SASL mechanism for authentication") + self.parser.add_option("--ssl-certificate", action="store", type="string", metavar="", help="Client SSL certificate (PEM Format)") + self.parser.add_option("--ssl-key", action="store", type="string", metavar="", help="Client SSL private key (PEM Format)") + self.parser.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.") + + def parse_args(self, argv): + opts, args = self.parser.parse_args(args=argv) + self.url = opts.broker or "localhost:5672" + self.get_connection_options(opts) + + if len(args) == 0: + self.command = "list" + elif len(args) == 1: + self.command = args.pop() + elif len(args) == 2: + self.command, self.typename = args[:2] + else: + self.command, self.typename, self.name = args[:3] + if len(args) > 3: + other = args[3:] + while len(other): + add_nameval(self.extra, other.pop()) + if self.command == "create" or self.command == "delete": + if not self.typename: + parser.error("%s requires a type to be named (e.g. queue, exchange)") + if not self.name: + parser.error("%s requires an object name to be specified") + elif self.command != "list": + parser.error("Invalid command: %s. You must specify one of 'create', 'delete' or 'list'" % command) + + def get_connection_options(self, opts): + if opts.sasl_mechanism: + self.conn_options['sasl_mechanisms'] = opts.sasl_mechanism + if opts.ssl_certificate: + self.conn_options['ssl_certfile'] = opts.ssl_certificate + if opts.ssl_key: + if not opts.ssl_certificate: + self.parser.error("missing '--ssl-certificate' (required by '--ssl-key')") + conn_options['ssl_keyfile'] = opts.ssl_key + if opts.ha_admin: + self.conn_options['client_properties'] = {'qpid.ha-admin' : 1} + + def connect(self): + self.connection = Connection.establish(self.url, **self.conn_options) + self.agent = BrokerAgent(self.connection) + + def disconnect(self): + self.connection.close() + + def execute(self): + if self.command == "list": + objects = [i["_values"] for i in self.agent._doClassQuery(self.typename.lower())] + for o in objects: + name = "" + details = "" + for k, v in o.items(): + if k == "name": + name = v + elif v: + if isinstance(v, dict) and v["_object_name"]: + v = v["_object_name"] + details += "%s=%s " %(k,v) + print "%-25s %s" % (name, details) + elif self.command == "create": + self.agent.create(self.typename, self.name, self.extra) + elif self.command == "delete": + self.agent.delete(self.typename, self.name, self.extra) + +def main(argv=None): + manager = Manager() + try: + manager.parse_args(argv) + manager.connect() + manager.execute() + manager.disconnect() + except Exception,e: + print "Failed: %s - %s" % (e.__class__.__name__, e) + +if __name__ == "__main__": + sys.exit(main()) + -- cgit v1.2.1