#!/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 <type> <name> [properties]
  %prog [OPTIONS] delete <type> <name> [arguments]
  %prog [OPTIONS] list <type>
"""
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="<address>", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:<port>]")
        self.parser.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>", help="SASL mechanism for authentication")
        self.parser.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
        self.parser.add_option("--ssl-key", action="store", type="string", metavar="<key>", 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())

