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()
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")
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()
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)
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
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}
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