Ejemplo n.º 1
0
    def __init__(self):
        """
        Construct a new AMQPClientHandler instance based on the configuration
        stored in the environment.

        @type env: Environment
        @param env: L{Environment} object
        """
        env = Environment.getInstance()
        self.log = logging.getLogger(__name__)
        self.log.debug("initializing AMQP client handler")
        self.env = env

        # Enable debugging for qpid if we're in debug mode
        #if self.env.config.get('core.loglevel') == 'DEBUG':
        #    enable('qpid', DEBUG)

        # Load configuration
        self.url = parseURL(self.env.config.get('amqp.url', None))
        self.domain = self.env.config.get('ampq.domain', default="org.gosa")
        self.dns_domain = socket.getfqdn().split('.', 1)[1]

        # Use zeroconf if there's no URL
        if not self.url:
            url = ZeroconfClient.discover(['_amqps._tcp', '_amqp._tcp'], domain=self.domain)[0]

            o = urlparse(url)
            # pylint: disable=E1101
            self.domain = o.path[1::]
            self.log.info("using service '%s'" % url)

            # Configure system
            user = self.env.config.get('amqp.id', default=None)
            if not user:
                user = self.env.uuid

            key = self.env.config.get('amqp.key')
            if key:
                # pylint: disable=E1101
                self.url = parseURL('%s://%s:%s@%s' % (o.scheme, user, key, o.netloc))
            else:
                self.url = parseURL(url)

        # Set params and go for it
        self.reconnect = self.env.config.get('amqp.reconnect', True)
        self.reconnect_interval = self.env.config.get('amqp.reconnect-interval', 3)
        self.reconnect_limit = self.env.config.get('amqp.reconnect-limit', 0)

        # Check if credentials are supplied
        if not self.env.config.get("amqp.key"):
            raise Exception("no key supplied - please join the client")

        # Start connection
        self.start()
Ejemplo n.º 2
0
    def serve(self):
        """ Start AMQP service for this GOsa service provider. """
        # Load AMQP and Command registry instances
        amqp = PluginRegistry.getInstance('AMQPHandler')
        self.__cr = PluginRegistry.getInstance('CommandRegistry')

        # Create a list of queues we need here
        queues = {}
        for dsc in self.__cr.commands.values():
            queues[dsc['target']] = True

        # Finally create the queues
        for queue in queues:
            # Add round robin processor for queue
            self.__cmdWorker = AMQPWorker(self.env, connection=amqp.getConnection(),
                r_address='%s.command.%s; { create:always, node:{ type:queue, x-bindings:[ { exchange:"amq.direct", queue:"%s.command.%s" } ] } }' % (self.env.domain, queue, self.env.domain, queue),
                workers=self.env.config.get('amqp.command-worker', default=1),
                callback=self.commandReceived)

            # Add private processor for queue
            self.__cmdWorker = AMQPWorker(self.env, connection=amqp.getConnection(),
                    r_address='%s.command.%s.%s; { create:always, delete:receiver, node:{ type:queue, x-bindings:[ { exchange:"amq.direct", queue:"%s.command.%s.%s" } ] } }' % (self.env.domain, queue, self.env.id, self.env.domain, queue, self.env.id),
                workers=self.env.config.get('amqp.command-worker', default=1),
                callback=self.commandReceived)

        # Announce service
        url = parseURL(self.env.config.get("amqp.url"))
        self.__zeroconf = ZeroconfService(name="GOsa AMQP command service",
                port=url['port'],
                stype="_%s._tcp" % url['scheme'],
                text="path=%s\001service=gosa" % url['path'])
        self.__zeroconf.publish()

        self.log.info("ready to process incoming requests")
Ejemplo n.º 3
0
    def __init__(self):
        env = Environment.getInstance()
        self.log = logging.getLogger(__name__)
        self.log.debug("initializing AMQP handler")
        self.env = env
        self.config = env.config

        # Initialize parser
        schema_root = etree.XML(PluginRegistry.getEventSchema())
        schema = etree.XMLSchema(schema_root)
        self._parser = objectify.makeparser(schema=schema)

        # Evaluate username
        user = self.config.get("amqp.id", default=None)
        if not user:
            user = self.env.uuid
        password = self.config.get("amqp.key")

        # Load configuration
        self.url = parseURL(makeAuthURL(self.config.get('amqp.url'), user, password))
        self.reconnect = self.config.get('amqp.reconnect', True)
        self.reconnect_interval = self.config.get('amqp.reconnect_interval', 3)
        self.reconnect_limit = self.config.get('amqp.reconnect_limit', 0)

        # Go for it
        self.start()
Ejemplo n.º 4
0
    def __init__(self, url, domain="org.gosa", xquery=".", callback=None):

        # Build connection
        url = parseURL(url)
        self.__conn = Connection(url['url'], transport=url['transport'], reconnect=True)
        self.__conn.open()

        # Assemble subscription query
        queue = 'event-listener-%s' % uuid4()
        address = """%s; {
            create: always,
            delete:always,
            node: {
                durable: False,
                x-declare: {
                    exclusive: True,
                    auto-delete: True }
            },
            link: {
                x-bindings: [
                        {
                            exchange: '%s',
                            queue: %s,
                            key: event,
                            arguments: { xquery: %r}
                        }
                    ]
                }
            }""" % (queue, domain, queue, xquery)

        # Add processor for core.event queue
        self.__callback = callback
        self.__eventWorker = AMQPStandaloneWorker(
                        self.__conn,
                        r_address=address,
                        workers=1,
                        callback=self.__eventProcessor)
Ejemplo n.º 5
0
def connect(service_uri='', username='', password=''):
    """ Creates a service proxy object from the arguments. """

    # Clean arguments
    username = username.strip()
    password = password.strip()
    service_uri = service_uri.strip()

    # Test if one argument is still needed.
    if len(service_uri) <= 0:
        tmp = service_uri
        service_uri = input('Service URI: [%s]' % service_uri).strip()
        if len(service_uri) <= 0:
            service_uri = tmp

    # Chek if URL is parsable
    url = parseURL(service_uri)

    # If we have still no service host, quit, because the connect will fail
    # pylint: disable-msg=E1101
    if not url:
        print(_("Need at least a service URI!"))
        sys.exit(1)

    # TRANSLATOR: Conected to URL, i.e. https://gosa.local:8080/rpc
    print(_("Connected to %s://%s:%s/%s") %
            (url['scheme'], url['host'], url['port'], url['path']))

    # Check weather to use method parameters or the URI elements.
    # If URI username is set and the method username is not set
    if url['user']:
        username = url['user']
    # If URI password is set and the username is set and the method password is not set
    if url['password']:
        password = url['password']

    # If we have still no credentials query for them
    if len(username) <= 0:
        # TRANSLATOR: This is a prompt - Username [joe]:
        username = input(_("Username") + " [%s]: " % getpass.getuser()).strip()
        if len(username) <= 0:
            username = getpass.getuser()

    if len(password) <= 0:
        # TRANSLATOR: This is a prompt - Password:
        password = getpass.getpass(_("Password") + ': ')

    # Create service proxy
    if url['scheme'][0:4] == "http":
        connection = '%s://%s:%s/%s' % (
                url['scheme'],
                url['host'],
                url['port'],
                url['path'])

        proxy = JSONServiceProxy(connection)
    else:
        print(_("The selected protocol is not supported!"))
        sys.exit(1)

    # Try to log in
    auth_handler = ConsoleHandler(proxy)
    auth_handler.login(username, password)

    return proxy
Ejemplo n.º 6
0
    def __init__(self, serviceURL, serviceAddress=None, serviceName=None,
                 conn=None, workers=3):
        self.__URL = url = parseURL(serviceURL)
        self.__serviceURL = serviceURL
        self.__serviceName = serviceName
        self.__serviceAddress = serviceAddress
        self.__workers = workers
        domain = url['path']

        # Prepare AMQP connection if not already there
        if not conn:
            conn = Connection(url['url'], transport=url['transport'], reconnect=True)
            conn.open()
            AMQPServiceProxy.domain= domain

            # Prefill __serviceAddress correctly if domain is given
            if AMQPServiceProxy.domain:
                self.__serviceAddress = '%s.command.core' % AMQPServiceProxy.domain

            if not self.__serviceAddress:
                raise AMQPException("no serviceAddress or domain specified")

            try:
                AMQPServiceProxy.worker[self.__serviceAddress]
            except KeyError:
                AMQPServiceProxy.worker[self.__serviceAddress] = {}

            # Pre instanciate core sessions
            for i in range(0, workers):
                ssn = conn.session(str(uuid4()))
                AMQPServiceProxy.worker[self.__serviceAddress][i] = {
                        'ssn': ssn,
                        'sender': ssn.sender(self.__serviceAddress),
                        'receiver': ssn.receiver('reply-%s; {create:always, delete:always, node: { type: queue, durable: False, x-declare: { exclusive: False, auto-delete: True } }}' % ssn.name),
                        'locked': False}

        # Store connection
        self.__conn = conn
        self.__ssn = None
        self.__sender = None
        self.__receiver = None
        self.__worker = None

        # Retrieve methods
        try:
            AMQPServiceProxy.methods
        except AttributeError:
            AMQPServiceProxy.methods = None
            AMQPServiceProxy.methods = {}

        # Retrieve methods
        try:
            AMQPServiceProxy.methods[self.__serviceAddress]
        except KeyError:
            AMQPServiceProxy.methods[self.__serviceAddress] = None
            AMQPServiceProxy.methods[self.__serviceAddress] = self.getMethods()

            # If we've no direct queue, we need to push to different queues
            if AMQPServiceProxy.domain:
                queues = set([
                        x['target'] for x in AMQPServiceProxy.methods[self.__serviceAddress].itervalues()
                        if x['target'] != 'core'
                    ])

                # Pre instanciate queue sessions
                for queue in queues:
                    for i in range(0, workers):
                        ssn = conn.session(str(uuid4()))
                        AMQPServiceProxy.worker[queue] = {}
                        AMQPServiceProxy.worker[queue][i] = {
                                'ssn': ssn,
                                'sender': ssn.sender("%s.command.%s" %
                                    (AMQPServiceProxy.domain, queue)),
                                'receiver': ssn.receiver('reply-%s; {create:always, delete:always, node: { type: queue, durable: False, x-declare: { exclusive: False, auto-delete: True } }}' % ssn.name),
                                'locked': False}
Ejemplo n.º 7
0
Archivo: main.py Proyecto: peuter/gosa
def main(argv=sys.argv):

    # Print help/usage and exit
    if '-h' in argv or '--help' in argv:
        print(__doc__)
        return 0
    try:
        opts, args = getopt.getopt(argv[1:], "u:p:c:d", ["user="******"password="******"command=", "debug"])
    except getopt.GetoptError:
        print(__doc__)
        sys.exit(2)

    service_uri = ''
    username = ''
    password = ''
    command = ''
    debug = False

    if len(args) >= 1:
        service_uri = args[0]

    for opt, arg in opts:
        if opt in ("-u", "--user"):
            username = arg
        elif opt in ("-p", "--password"):
            password = arg
        elif opt in ("-c", "--command"):
            command = arg
        elif opt in ("-d", "--debug"):
            debug = True

    # Create service object
    service = GosaService()

    # Check if connection could be established
    try:
        service_uri, username, password = service.connect(service_uri, username, password)
    except KeyboardInterrupt:
        print()
        sys.exit(1)

    if debug:
        # Connect to the SSE service and show incoming messages on console
        sse_client = SseClient()
        parsed_url = parseURL(service_uri)
        sse_client.connect(format('%s://%s:%d/%s' % (parsed_url['scheme'], parsed_url['host'], parsed_url['port'], 'events')))

    # Prepare to enter the interactive console.
    # Make the the GosaService instance available to the console via the
    # "gosa" object.
    service.proxy.help = service.help
    context = {'gosa': service.proxy, 'service': service, '__name__': '__console__', '__doc__': None}

    # This python wrap string catches any exception, prints it and exists the
    # program with a failure that can be processed by the caller (e.g. on a
    # command line).
    wrap = """
import sys, traceback
try:
    %s
except:
    traceback.print_exc()
    sys.exit(1)
"""
    startup = """
import readline
import rlcompleter
import atexit
import os

# Tab completion
readline.parse_and_bind('tab: complete')

# history file
histfile = os.path.join(os.environ['HOME'], '.gosa.history')
try:
    readline.read_history_file(histfile)
except IOError:
    pass
atexit.register(readline.write_history_file, histfile)
del os, histfile, readline, rlcompleter

for i in gosa.getMethods().keys():
    globals()[i] = getattr(gosa, i)
"""
    if service_uri[0:5] == "https":
        startup += """
# override setTwoFactorMethod as we need the result to e.g. calculate QR-Code or setup U2F
globals()['setTwoFactorMethod'] = service.setTwoFactorMethod
"""
    else:
        startup += """
# setTwoFactorMethod not allowed in non https environment
globals()['setTwoFactorMethod'] = service.twoFactorNotAllowed
"""

    # Use script mode:
    if not sys.stdin.isatty():
        pyconsole = code.InteractiveInterpreter(context)
        try:
            cake = sys.stdin.read()
            pyconsole.runcode(cake)
            letRun = 0
        except Exception:
            traceback.print_exc()
            return 1
    # Use one-shot mode
    elif len(argv) >= 5:
        pyconsole = code.InteractiveInterpreter(context)
        try:
            commands = command.split(';')
            for cake in commands:
                if not cake:
                    continue

                pyconsole.runcode(wrap % cake)
            letRun = 0
        except Exception:
            return 1
    # Use interactive mode
    else:
        letRun = 1
        pyconsole = None
        while(letRun):
            try:
                if not pyconsole:
                    pyconsole = MyConsole(context)
                    pyconsole.proxy = service.proxy
                    pyconsole.runcode(startup)
                    pyconsole.interact(_("GOsa infrastructure shell. Use Ctrl+D to exit."))
                else:
                    mycode = pyconsole.getLastCode()
                    pyconsole = MyConsole(context)
                    pyconsole.proxy = service.proxy
                    pyconsole.runcode(mycode)
                    pyconsole.interact("")

                print(_("Closing session"))
                service.proxy.logout()
                letRun = 0

            # In case of a gosa-backend restart we have to double check login
            except HTTPError as e:
                if e.code == 401:
                    service.reconnectJson(service_uri, username, password)
                    context = {'gosa': service.proxy, 'service': service,
                        '__name__': '__console__', '__doc__': None}
                else:
                    print(e)
                    sys.exit(1)
    return 0