Example #1
0
    def run(self):
        set_thread_name('mdns_discover')
        if not mDNSDaemonMonitor.instance.mdnsd_running.wait(timeout=10):
            return

        sdRef = pybonjour.DNSServiceBrowse(
            regtype=self.regtype,
            callBack=self.on_discover
        )

        while True:
            r, w, x = select.select([sdRef, self.pipe[0]], [], [])
            if self.pipe[0] in r:
                break

            for ref in r:
                try:
                    pybonjour.DNSServiceProcessResult(ref)

                # mdnsd was probaly killed, so just continue since this thread will be restarted
                except pybonjour.BonjourError:
                    continue

            if self.finished.is_set():
                break

        if self.active(sdRef):
            sdRef.close()
Example #2
0
    def run(self):
        set_thread_name('mdns_resolve')
        while True:
            if not self.mdnsd.is_alive():
                self.mdnsd.wait(timeout=10)

            try:
                obj = self.queue.get(block=True, timeout=self.timeout)
            except queue.Empty:
                if self.finished.is_set():
                    break
                continue

            sdRef = pybonjour.DNSServiceResolve(flags=obj.flags,
                                                interfaceIndex=obj.interface,
                                                name=obj.name,
                                                regtype=obj.regtype,
                                                domain=obj.domain,
                                                callBack=self.on_resolve)

            self.references.append(sdRef)
            _references = list(filter(self.active, self.references))

            r, w, x = select.select(_references, [], [])
            for ref in r:
                pybonjour.DNSServiceProcessResult(ref)

            if self.finished.is_set():
                break

        for ref in self.references:
            self.references.remove(ref)
            if self.active(ref):
                ref.close()
Example #3
0
    def run(self):
        set_thread_name('mdns_discover')
        if not self.mdnsd.is_alive():
            self.mdnsd.wait(timeout=10)

        sdRef = pybonjour.DNSServiceBrowse(regtype=self.regtype,
                                           callBack=self.on_discover)

        while True:
            r, w, x = select.select([sdRef, self.pipe[0]], [], [])
            if self.pipe[0] in r:
                break

            for ref in r:
                try:
                    pybonjour.DNSServiceProcessResult(ref)

                # mdnsd was probaly killed, so just continue since this thread will be restarted
                except pybonjour.BonjourError:
                    continue

            if self.finished.is_set():
                break

        if self.active(sdRef):
            sdRef.close()
Example #4
0
 def run(self):
     set_thread_name(f'mdns_svc_{self.service}')
     try:
         self.register()
     except pybonjour.BonjourError:
         self.logger.debug(
             "ServiceThread: failed to register '%s', is mdnsd running?",
             self.service)
    def _target(self):
        set_thread_name(self.name)
        try:
            while True:
                work_item = self.executor.get_work_item(self)
                if work_item is None:
                    return

                work_item.run()
                del work_item
        except Exception:
            logger.critical("Exception in worker", exc_info=True)
        finally:
            self.executor.remove_worker(self)
Example #6
0
 def __init__(self,
              loop_debug=False,
              loop_monitor=True,
              overlay_dirs=None,
              debug_level=None):
     self.logger = logger.Logger('middlewared', debug_level).getLogger()
     self.crash_reporting = logger.CrashReporting()
     self.crash_reporting_semaphore = asyncio.Semaphore(value=2)
     self.loop_debug = loop_debug
     self.loop_monitor = loop_monitor
     self.overlay_dirs = overlay_dirs or []
     self.__loop = None
     self.__thread_id = threading.get_ident()
     # Spawn new processes for ProcessPool instead of forking
     multiprocessing.set_start_method('spawn')
     self.__procpool = concurrent.futures.ProcessPoolExecutor(
         max_workers=2,
         initializer=worker_init,
     )
     self.__threadpool = concurrent.futures.ThreadPoolExecutor(
         initializer=lambda: set_thread_name('threadpool_ws'),
         max_workers=10,
     )
     self.jobs = JobsQueue(self)
     self.__schemas = Schemas()
     self.__services = {}
     self.__wsclients = {}
     self.__event_sources = {}
     self.__event_subs = defaultdict(list)
     self.__hooks = defaultdict(list)
     self.__server_threads = []
     self.__init_services()
Example #7
0
 def __init__(
     self, loop_debug=False, loop_monitor=True, overlay_dirs=None, debug_level=None,
     log_handler=None, startup_seq_path=None,
 ):
     super().__init__(overlay_dirs)
     self.logger = logger.Logger('middlewared', debug_level).getLogger()
     self.crash_reporting = logger.CrashReporting()
     self.crash_reporting_semaphore = asyncio.Semaphore(value=2)
     self.loop_debug = loop_debug
     self.loop_monitor = loop_monitor
     self.debug_level = debug_level
     self.log_handler = log_handler
     self.startup_seq = 0
     self.startup_seq_path = startup_seq_path
     self.app = None
     self.__loop = None
     self.__thread_id = threading.get_ident()
     # Spawn new processes for ProcessPool instead of forking
     multiprocessing.set_start_method('spawn')
     self.__threadpool = concurrent.futures.ThreadPoolExecutor(
         initializer=lambda: set_thread_name('threadpool_ws'),
         max_workers=10,
     )
     self.__init_procpool()
     self.__wsclients = {}
     self.__events = Events()
     self.__event_sources = {}
     self.__event_subs = defaultdict(list)
     self.__hooks = defaultdict(list)
     self.__server_threads = []
     self.__init_services()
     self.__console_io = False if os.path.exists(self.CONSOLE_ONCE_PATH) else None
     self.jobs = JobsQueue(self)
Example #8
0
 def __init__(
     self, loop_debug=False, loop_monitor=True, overlay_dirs=None, debug_level=None,
     log_handler=None, startup_seq_path=None,
 ):
     super().__init__(overlay_dirs)
     self.logger = logger.Logger('middlewared', debug_level).getLogger()
     self.crash_reporting = logger.CrashReporting()
     self.crash_reporting_semaphore = asyncio.Semaphore(value=2)
     self.loop_debug = loop_debug
     self.loop_monitor = loop_monitor
     self.debug_level = debug_level
     self.log_handler = log_handler
     self.startup_seq = 0
     self.startup_seq_path = startup_seq_path
     self.app = None
     self.__loop = None
     self.__thread_id = threading.get_ident()
     # Spawn new processes for ProcessPool instead of forking
     multiprocessing.set_start_method('spawn')
     self.__threadpool = concurrent.futures.ThreadPoolExecutor(
         initializer=lambda: set_thread_name('threadpool_ws'),
         max_workers=10,
     )
     self.__init_procpool()
     self.__wsclients = {}
     self.__events = Events()
     self.__event_sources = {}
     self.__event_subs = defaultdict(list)
     self.__hooks = defaultdict(list)
     self.__server_threads = []
     self.__init_services()
     self.__console_io = False if os.path.exists(self.CONSOLE_ONCE_PATH) else None
     self.jobs = JobsQueue(self)
Example #9
0
 async def run_in_thread(self, method, *args, **kwargs):
     executor = concurrent.futures.ThreadPoolExecutor(
         max_workers=1,
         initializer=lambda: set_thread_name('io_thread'),
     )
     try:
         return await self.loop.run_in_executor(executor, functools.partial(method, *args, **kwargs))
     finally:
         executor.shutdown(wait=False)
Example #10
0
 async def run_in_thread(self, method, *args, **kwargs):
     executor = concurrent.futures.ThreadPoolExecutor(
         max_workers=1,
         initializer=lambda: set_thread_name('io_thread'),
     )
     try:
         return await self.loop.run_in_executor(executor, functools.partial(method, *args, **kwargs))
     finally:
         executor.shutdown(wait=False)
Example #11
0
    def run(self):
        set_thread_name('mdns_services')
        while True:
            if not mDNSDaemonMonitor.instance.mdnsd_running.wait(timeout=10):
                return

            try:
                obj = self.queue.get(block=True, timeout=self.timeout)
            except queue.Empty:
                if self.finished.is_set():
                    break
                continue

            regtype = self.to_regtype(obj)
            if not regtype:
                continue

            sdRef = pybonjour.DNSServiceBrowse(
                regtype=regtype,
                callBack=self.on_discover
            )

            self.references.append(sdRef)
            _references = list(filter(self.active, self.references))

            r, w, x = select.select(_references + [self.pipe[0]], [], [])
            if self.pipe[0] in r:
                break
            for ref in r:
                pybonjour.DNSServiceProcessResult(ref)
            if not (obj.flags & kDNSServiceFlagsAdd):
                self.references.remove(sdRef)
                if self.active(sdRef):
                    sdRef.close()

            if self.finished.is_set():
                break

        for ref in self.references:
            self.references.remove(ref)
            if self.active(ref):
                ref.close()
Example #12
0
    def _loop_monitor_thread(self):
        """
        Thread responsible for checking current tasks that are taking too long
        to finish and printing the stack.

        DISCLAIMER/TODO: This is not free of race condition so it may show
        false positives.
        """
        set_thread_name('loop_monitor')
        last = None
        while True:
            time.sleep(2)
            current = asyncio.current_task(loop=self.__loop)
            if current is None:
                last = None
                continue
            if last == current:
                frame = sys._current_frames()[self.__thread_id]
                stack = traceback.format_stack(frame, limit=-10)
                self.logger.warn(''.join(['Task seems blocked:\n'] + stack))
            last = current
Example #13
0
    def _loop_monitor_thread(self):
        """
        Thread responsible for checking current tasks that are taking too long
        to finish and printing the stack.

        DISCLAIMER/TODO: This is not free of race condition so it may show
        false positives.
        """
        set_thread_name('loop_monitor')
        last = None
        while True:
            time.sleep(2)
            current = asyncio.current_task(loop=self.__loop)
            if current is None:
                last = None
                continue
            if last == current:
                frame = sys._current_frames()[self.__thread_id]
                stack = traceback.format_stack(frame, limit=-10)
                self.logger.warn(''.join(['Task seems blocked:'] + stack))
            last = current
Example #14
0
    def run(self):
        set_thread_name('mdns_services')
        while True:
            if not self.mdnsd.is_alive():
                self.mdnsd.wait(timeout=10)

            try:
                obj = self.queue.get(block=True, timeout=self.timeout)
            except queue.Empty:
                if self.finished.is_set():
                    break
                continue

            regtype = self.to_regtype(obj)
            if not regtype:
                continue

            sdRef = pybonjour.DNSServiceBrowse(regtype=regtype,
                                               callBack=self.on_discover)

            self.references.append(sdRef)
            _references = list(filter(self.active, self.references))

            r, w, x = select.select(_references + [self.pipe[0]], [], [])
            if self.pipe[0] in r:
                break
            for ref in r:
                pybonjour.DNSServiceProcessResult(ref)
            if not (obj.flags & kDNSServiceFlagsAdd):
                self.references.remove(sdRef)
                if self.active(sdRef):
                    sdRef.close()

            if self.finished.is_set():
                break

        for ref in self.references:
            self.references.remove(ref)
            if self.active(ref):
                ref.close()
Example #15
0
    def run(self):
        set_thread_name('mdnsd_monitor')
        while True:
            """
            If the system has not completely booted yet we need to way at least
            for DNS to be configured.

            In case middlewared is started after boot, system.ready will be set after this plugin
            is loaded, hence the dns_sync timeout.
            """
            if not self.middleware.call_sync('system.ready'):
                if not self.dns_sync.wait(timeout=2):
                    continue

            pid = self.is_alive()
            if not pid:
                self.start_mdnsd()
                time.sleep(2)
                continue
            kqueue = select.kqueue()
            try:
                kqueue.control([
                    select.kevent(
                        pid,
                        filter=select.KQ_FILTER_PROC,
                        flags=select.KQ_EV_ADD,
                        fflags=select.KQ_NOTE_EXIT,
                    )
                ], 0, 0)
            except ProcessLookupError:
                continue
            self.mdnsd_running.set()
            self.middleware.call_sync('mdnsadvertise.restart')
            self.middleware.call_sync('mdnsbrowser.restart')
            kqueue.control(None, 1)
            self.mdnsd_running.clear()
            kqueue.close()
Example #16
0
    def run(self):
        set_thread_name('mdnsd_monitor')
        while True:
            """
            If the system has not completely booted yet we need to way at least
            for DNS to be configured.

            In case middlewared is started after boot, system.ready will be set after this plugin
            is loaded, hence the dns_sync timeout.
            """
            if not self.middleware.call_sync('system.ready'):
                if not self.dns_sync.wait(timeout=2):
                    continue

            pid = self.is_alive()
            if not pid:
                self.start_mdnsd()
                time.sleep(2)
                continue
            kqueue = select.kqueue()
            try:
                kqueue.control([
                    select.kevent(
                        pid,
                        filter=select.KQ_FILTER_PROC,
                        flags=select.KQ_EV_ADD,
                        fflags=select.KQ_NOTE_EXIT,
                    )
                ], 0, 0)
            except ProcessLookupError:
                continue
            self.mdnsd_running.set()
            self.middleware.call_sync('mdnsadvertise.restart')
            kqueue.control(None, 1)
            self.mdnsd_running.clear()
            kqueue.close()
Example #17
0
    def run(self):
        set_thread_name('mdns_resolve')
        while True:
            if not mDNSDaemonMonitor.instance.mdnsd_running.wait(timeout=10):
                return

            try:
                obj = self.queue.get(block=True, timeout=self.timeout)
            except queue.Empty:
                if self.finished.is_set():
                    break
                continue

            sdRef = pybonjour.DNSServiceResolve(
                flags=obj.flags,
                interfaceIndex=obj.interface,
                name=obj.name,
                regtype=obj.regtype,
                domain=obj.domain,
                callBack=self.on_resolve
            )

            self.references.append(sdRef)
            _references = list(filter(self.active, self.references))

            r, w, x = select.select(_references, [], [])
            for ref in r:
                pybonjour.DNSServiceProcessResult(ref)

            if self.finished.is_set():
                break

        for ref in self.references:
            self.references.remove(ref)
            if self.active(ref):
                ref.close()
Example #18
0
    def run(self):

        self._console_write('starting')

        set_thread_name('asyncio_loop')
        self.loop = self.__loop = asyncio.get_event_loop()

        if self.loop_debug:
            self.__loop.set_debug(True)
            self.__loop.slow_callback_duration = 0.2

        self.app = app = web.Application(middlewares=[
            normalize_path_middleware(redirect_class=HTTPPermanentRedirect)
        ], loop=self.__loop)

        # Needs to happen after setting debug or may cause race condition
        # http://bugs.python.org/issue30805
        self.__loop.run_until_complete(self.__plugins_load())

        self._console_write('registering services')

        if self.loop_monitor:
            # Start monitor thread after plugins have been loaded
            # because of the time spent doing I/O
            t = threading.Thread(target=self._loop_monitor_thread)
            t.setDaemon(True)
            t.start()

        self.__loop.add_signal_handler(signal.SIGINT, self.terminate)
        self.__loop.add_signal_handler(signal.SIGTERM, self.terminate)
        self.__loop.add_signal_handler(signal.SIGUSR1, self.pdb)
        self.__loop.add_signal_handler(signal.SIGUSR2, self.log_threads_stacks)

        app.router.add_route('GET', '/websocket', self.ws_handler)

        app.router.add_route('*', '/api/docs{path_info:.*}', WSGIHandler(apidocs_app))
        app.router.add_route('*', '/ui{path_info:.*}', WebUIAuth(self))

        self.fileapp = FileApplication(self, self.__loop)
        app.router.add_route('*', '/_download{path_info:.*}', self.fileapp.download)
        app.router.add_route('*', '/_upload{path_info:.*}', self.fileapp.upload)

        shellapp = ShellApplication(self)
        app.router.add_route('*', '/_shell{path_info:.*}', shellapp.ws_handler)

        restful_api = RESTfulAPI(self, app)
        self.__loop.run_until_complete(
            asyncio.ensure_future(restful_api.register_resources())
        )
        asyncio.ensure_future(self.jobs.run())

        self.__setup_periodic_tasks()

        # Start up middleware worker process pool
        self.__procpool._start_queue_management_thread()

        runner = web.AppRunner(app, handle_signals=False, access_log=None)
        self.__loop.run_until_complete(runner.setup())
        self.__loop.run_until_complete(
            web.TCPSite(runner, '0.0.0.0', 6000, reuse_address=True, reuse_port=True).start()
        )
        self.__loop.run_until_complete(web.UnixSite(runner, '/var/run/middlewared.sock').start())

        self.logger.debug('Accepting connections')
        self._console_write('loading completed\n')

        try:
            self.__loop.run_forever()
        except RuntimeError as e:
            if e.args[0] != "Event loop is closed":
                raise
Example #19
0
 def __init__(self, **kwargs):
     kwargs['service'] = 'middleware'
     super(mDNSServiceMiddlewareThread, self).__init__(**kwargs)
     set_thread_name(f'mdns_{self.service}')
Example #20
0
    def run(self):

        self._console_write('starting')

        set_thread_name('asyncio_loop')
        self.loop = self.__loop = asyncio.get_event_loop()

        if self.loop_debug:
            self.__loop.set_debug(True)
            self.__loop.slow_callback_duration = 0.2

        self.app = app = web.Application(middlewares=[
            normalize_path_middleware(redirect_class=HTTPPermanentRedirect)
        ], loop=self.__loop)

        # Needs to happen after setting debug or may cause race condition
        # http://bugs.python.org/issue30805
        self.__loop.run_until_complete(self.__plugins_load())

        self._console_write('registering services')

        if self.loop_monitor:
            # Start monitor thread after plugins have been loaded
            # because of the time spent doing I/O
            t = threading.Thread(target=self._loop_monitor_thread)
            t.setDaemon(True)
            t.start()

        self.__loop.add_signal_handler(signal.SIGINT, self.terminate)
        self.__loop.add_signal_handler(signal.SIGTERM, self.terminate)
        self.__loop.add_signal_handler(signal.SIGUSR1, self.pdb)
        self.__loop.add_signal_handler(signal.SIGUSR2, self.log_threads_stacks)

        app.router.add_route('GET', '/websocket', self.ws_handler)

        app.router.add_route('*', '/api/docs{path_info:.*}', WSGIHandler(apidocs_app))
        app.router.add_route('*', '/ui{path_info:.*}', WebUIAuth(self))

        self.fileapp = FileApplication(self, self.__loop)
        app.router.add_route('*', '/_download{path_info:.*}', self.fileapp.download)
        app.router.add_route('*', '/_upload{path_info:.*}', self.fileapp.upload)

        shellapp = ShellApplication(self)
        app.router.add_route('*', '/_shell{path_info:.*}', shellapp.ws_handler)

        restful_api = RESTfulAPI(self, app)
        self.__loop.run_until_complete(
            asyncio.ensure_future(restful_api.register_resources())
        )
        asyncio.ensure_future(self.jobs.run())

        self.__setup_periodic_tasks()

        # Start up middleware worker process pool
        self.__procpool._start_queue_management_thread()

        runner = web.AppRunner(app, handle_signals=False, access_log=None)
        self.__loop.run_until_complete(runner.setup())
        self.__loop.run_until_complete(
            web.TCPSite(runner, '0.0.0.0', 6000, reuse_address=True, reuse_port=True).start()
        )
        self.__loop.run_until_complete(web.UnixSite(runner, '/var/run/middlewared.sock').start())

        self.logger.debug('Accepting connections')
        self._console_write('loading completed\n')

        try:
            self.__loop.run_forever()
        except RuntimeError as e:
            if e.args[0] != "Event loop is closed":
                raise
Example #21
0
 def __init__(self, **kwargs):
     kwargs['service'] = 'middleware'
     super(mDNSServiceMiddlewareThread, self).__init__(**kwargs)
     set_thread_name(f'mdns_{self.service}')
Example #22
0
 def run(self):
     set_thread_name(f'mdns_svc_{self.service}')
     try:
         self.register()
     except pybonjour.BonjourError:
         self.logger.trace("ServiceThread: failed to register '%s', is mdnsd running?", self.service)