Exemplo n.º 1
0
 def wait(self):
     for x in self.timers:
         try:
             x.wait()
         except eventlet.greenlet.GreenletExit:
             pass
         except Exception:
             LOG.exception(_LE('Error waiting on timer.'))
     self._perform_action_on_threads(
         lambda x: x.wait(),
         lambda x: LOG.exception(_LE('Error waiting on thread.')))
Exemplo n.º 2
0
 def wait(self):
     for x in self.timers:
         try:
             x.wait()
         except eventlet.greenlet.GreenletExit:  # nosec
             # greenlet exited successfully
             pass
         except Exception:
             LOG.exception(_LE('Error waiting on timer.'))
     self._perform_action_on_threads(
         lambda x: x.wait(),
         lambda x: LOG.exception(_LE('Error waiting on thread.')))
Exemplo n.º 3
0
    def _get_socket(self, host, port, backlog):
        bind_addr = (host, port)
        # TODO(dims): eventlet's green dns/socket module does not actually
        # support IPv6 in getaddrinfo(). We need to get around this in the
        # future or monitor upstream for a fix
        try:
            info = socket.getaddrinfo(bind_addr[0],
                                      bind_addr[1],
                                      socket.AF_UNSPEC,
                                      socket.SOCK_STREAM)[0]
            family = info[0]
            bind_addr = info[-1]
        except Exception:
            family = socket.AF_INET

        try:
            sock = eventlet.listen(bind_addr, family, backlog=backlog)
        except EnvironmentError:
            LOG.error(_LE("Could not bind to %(host)s:%(port)s"),
                      {'host': host, 'port': port})
            raise
        sock = self._set_socket_opts(sock)
        LOG.info(_LI("%(name)s listening on %(host)s:%(port)s"),
                 {'name': self.name, 'host': host, 'port': port})
        return sock
Exemplo n.º 4
0
 def _run_loop(self, kind, event, idle_for_func, initial_delay=None):
     if initial_delay:
         greenthread.sleep(initial_delay)
     try:
         watch = timeutils.StopWatch()
         while self._running:
             watch.restart()
             result = self.f(*self.args, **self.kw)
             watch.stop()
             if not self._running:
                 break
             idle = idle_for_func(result, watch.elapsed())
             LOG.debug(
                 "%(kind)s %(func_name)r sleeping " "for %(idle).02f seconds",
                 {"func_name": self.f, "idle": idle, "kind": kind},
             )
             greenthread.sleep(idle)
     except LoopingCallDone as e:
         event.send(e.retvalue)
     except Exception:
         exc_info = sys.exc_info()
         try:
             LOG.error(_LE("%(kind)s %(func_name)r failed"), {"kind": kind, "func_name": self.f}, exc_info=exc_info)
             event.send_exception(*exc_info)
         finally:
             del exc_info
         return
     else:
         event.send(True)
Exemplo n.º 5
0
 def stop_timers(self):
     for x in self.timers:
         try:
             x.stop()
         except Exception:
             LOG.exception(_LE('Error stopping timer.'))
     self.timers = []
Exemplo n.º 6
0
    def _get_socket(self, host, port, backlog):
        bind_addr = (host, port)
        # TODO(dims): eventlet's green dns/socket module does not actually
        # support IPv6 in getaddrinfo(). We need to get around this in the
        # future or monitor upstream for a fix
        try:
            info = socket.getaddrinfo(bind_addr[0], bind_addr[1],
                                      socket.AF_UNSPEC, socket.SOCK_STREAM)[0]
            family = info[0]
            bind_addr = info[-1]
        except Exception:
            family = socket.AF_INET

        try:
            sock = eventlet.listen(bind_addr, family, backlog=backlog)
        except EnvironmentError:
            LOG.error(_LE("Could not bind to %(host)s:%(port)s"), {
                'host': host,
                'port': port
            })
            raise
        sock = self._set_socket_opts(sock)
        LOG.info(_LI("%(name)s listening on %(host)s:%(port)s"), {
            'name': self.name,
            'host': host,
            'port': port
        })
        return sock
Exemplo n.º 7
0
    def run_periodic_tasks(self, context, raise_on_error=False):
        """Tasks to be run at a periodic interval."""
        idle_for = DEFAULT_INTERVAL
        for task_name, task in self._periodic_tasks:
            if (task._periodic_external_ok and not
               self.conf.run_external_periodic_tasks):
                continue
            full_task_name = '.'.join([self.__class__.__name__, task_name])

            spacing = self._periodic_spacing[task_name]
            last_run = self._periodic_last_run[task_name]

            # Check if due, if not skip
            idle_for = min(idle_for, spacing)
            if last_run is not None:
                delta = last_run + spacing - now()
                if delta > 0:
                    idle_for = min(idle_for, delta)
                    continue

            LOG.debug("Running periodic task %(full_task_name)s",
                      {"full_task_name": full_task_name})
            self._periodic_last_run[task_name] = _nearest_boundary(
                last_run, spacing)

            try:
                task(self, context)
            except Exception:
                if raise_on_error:
                    raise
                LOG.exception(_LE("Error during %(full_task_name)s"),
                              {"full_task_name": full_task_name})
            time.sleep(0)

        return idle_for
Exemplo n.º 8
0
 def _run_loop(self, kind, event, idle_for_func,
               initial_delay=None, stop_on_exception=True):
     func_name = reflection.get_callable_name(self.f)
     func = self.f if stop_on_exception else _safe_wrapper(self.f, kind,
                                                           func_name)
     if initial_delay:
         greenthread.sleep(initial_delay)
     try:
         watch = timeutils.StopWatch()
         while self._running:
             watch.restart()
             result = func(*self.args, **self.kw)
             watch.stop()
             if not self._running:
                 break
             idle = idle_for_func(result, watch.elapsed())
             LOG.trace('%(kind)s %(func_name)r sleeping '
                       'for %(idle).02f seconds',
                       {'func_name': func_name, 'idle': idle,
                        'kind': kind})
             greenthread.sleep(idle)
     except LoopingCallDone as e:
         event.send(e.retvalue)
     except Exception:
         exc_info = sys.exc_info()
         try:
             LOG.error(_LE('%(kind)s %(func_name)r failed'),
                       {'kind': kind, 'func_name': func_name},
                       exc_info=exc_info)
             event.send_exception(*exc_info)
         finally:
             del exc_info
         return
     else:
         event.send(True)
Exemplo n.º 9
0
        def _inner():
            if initial_delay:
                greenthread.sleep(initial_delay)

            try:
                while self._running:
                    start = _ts()
                    self.f(*self.args, **self.kw)
                    end = _ts()
                    if not self._running:
                        break
                    delay = end - start - interval
                    if delay > 0:
                        LOG.warning(_LW('task %(func_name)r run outlasted '
                                        'interval by %(delay).2f sec'),
                                    {'func_name': self.f, 'delay': delay})
                    greenthread.sleep(-delay if delay < 0 else 0)
            except LoopingCallDone as e:
                self.stop()
                done.send(e.retvalue)
            except Exception:
                LOG.exception(_LE('in fixed duration looping call'))
                done.send_exception(*sys.exc_info())
                return
            else:
                done.send(True)
Exemplo n.º 10
0
 def _func(*args, **kwargs):
     result = None
     try:
         if self._retry_count:
             LOG.debug("Invoking %(func_name)s; retry count is "
                       "%(retry_count)d.",
                       {'func_name': func_name,
                        'retry_count': self._retry_count})
         result = f(*args, **kwargs)
     except self._exceptions:
         with excutils.save_and_reraise_exception() as ctxt:
             LOG.warn(_LW("Exception which is in the suggested list of "
                          "exceptions occurred while invoking function:"
                          " %s."),
                      func_name,
                      exc_info=True)
             if (self._max_retry_count != -1 and
                     self._retry_count >= self._max_retry_count):
                 LOG.error(_LE("Cannot retry %(func_name)s upon "
                               "suggested exception "
                               "since retry count (%(retry_count)d) "
                               "reached max retry count "
                               "(%(max_retry_count)d)."),
                           {'retry_count': self._retry_count,
                            'max_retry_count': self._max_retry_count,
                            'func_name': func_name})
             else:
                 ctxt.reraise = False
                 self._retry_count += 1
                 self._sleep_time += self._inc_sleep_time
                 return self._sleep_time
     raise LoopingCallDone(result)
Exemplo n.º 11
0
    def run_periodic_tasks(self, context, raise_on_error=False):
        """Tasks to be run at a periodic interval."""
        idle_for = DEFAULT_INTERVAL
        for task_name, task in self._periodic_tasks:
            if (task._periodic_external_ok
                    and not self.conf.run_external_periodic_tasks):
                continue
            full_task_name = '.'.join([self.__class__.__name__, task_name])

            spacing = self._periodic_spacing[task_name]
            last_run = self._periodic_last_run[task_name]

            # Check if due, if not skip
            idle_for = min(idle_for, spacing)
            if last_run is not None:
                delta = last_run + spacing - now()
                if delta > 0:
                    idle_for = min(idle_for, delta)
                    continue

            LOG.debug("Running periodic task %(full_task_name)s",
                      {"full_task_name": full_task_name})
            self._periodic_last_run[task_name] = _nearest_boundary(
                last_run, spacing)

            try:
                task(self, context)
            except Exception:
                if raise_on_error:
                    raise
                LOG.exception(_LE("Error during %(full_task_name)s"),
                              {"full_task_name": full_task_name})
            time.sleep(0)

        return idle_for
Exemplo n.º 12
0
        def _inner():
            if initial_delay:
                greenthread.sleep(initial_delay)

            try:
                while self._running:
                    idle = self.f(*self.args, **self.kw)
                    if not self._running:
                        break

                    if periodic_interval_max is not None:
                        idle = min(idle, periodic_interval_max)
                    LOG.debug('Dynamic looping call %(func_name)r sleeping '
                              'for %(idle).02f seconds',
                              {'func_name': self.f, 'idle': idle})
                    greenthread.sleep(idle)
            except LoopingCallDone as e:
                self.stop()
                done.send(e.retvalue)
            except Exception:
                LOG.exception(_LE('in dynamic looping call'))
                done.send_exception(*sys.exc_info())
                return
            else:
                done.send(True)
Exemplo n.º 13
0
 def stop_timers(self):
     for x in self.timers:
         try:
             x.stop()
         except Exception:
             LOG.exception(_LE('Error stopping timer.'))
     self.timers = []
Exemplo n.º 14
0
 def func(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except LoopingCallDone:
         raise  # let the outer handler process this
     except Exception:
         LOG.error(_LE('%(kind)s %(func_name)r failed'),
                   {'kind': kind, 'func_name': func_name},
                   exc_info=True)
         return 0
Exemplo n.º 15
0
 def func(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except LoopingCallDone:
         raise  # let the outer handler process this
     except Exception:
         LOG.error(_LE('%(kind)s %(func_name)r failed'),
                   {'kind': kind, 'func_name': func_name},
                   exc_info=True)
         return 0
Exemplo n.º 16
0
 def stop_timers(self):
     stopped_timers = []
     for x in self.timers:
         try:
             x.stop()
         except Exception:
             LOG.exception(_LE('Error stopping timer.'))
         else:
             stopped_timers.append(x)
     for x in stopped_timers:
         try:
             self.timers.remove(x)
         except ValueError:
             pass
Exemplo n.º 17
0
    def load_app(self, name):
        """Return the paste URLMap wrapped WSGI application.

        :param name: Name of the application to load.
        :returns: Paste URLMap object wrapping the requested application.
        :raises: PasteAppNotFound

        """
        try:
            LOG.debug("Loading app %(name)s from %(path)s", {"name": name, "path": self.config_path})
            return deploy.loadapp("config:%s" % self.config_path, name=name)
        except LookupError:
            LOG.exception(_LE("Couldn't lookup app: %s"), name)
            raise PasteAppNotFound(name=name, path=self.config_path)
Exemplo n.º 18
0
    def run_service(service, done):
        """Service start wrapper.

        :param service: service to run
        :param done: event to wait on until a shutdown is triggered
        :returns: None

        """
        try:
            service.start()
        except Exception:
            LOG.exception(_LE('Error starting thread.'))
            raise SystemExit(1)
        else:
            done.wait()
Exemplo n.º 19
0
    def load_app(self, name):
        """Return the paste URLMap wrapped WSGI application.

        :param name: Name of the application to load.
        :returns: Paste URLMap object wrapping the requested application.
        :raises: PasteAppNotFound

        """
        try:
            LOG.debug("Loading app %(name)s from %(path)s",
                      {'name': name, 'path': self.config_path})
            return deploy.loadapp("config:%s" % self.config_path, name=name)
        except LookupError:
            LOG.exception(_LE("Couldn't lookup app: %s"), name)
            raise PasteAppNotFound(name=name, path=self.config_path)
Exemplo n.º 20
0
    def _stop_threads(self):
        current = threading.current_thread()

        # Iterate over a copy of self.threads so thread_done doesn't
        # modify the list while we're iterating
        for x in self.threads[:]:
            if x is current:
                # don't kill the current thread.
                continue
            try:
                x.stop()
            except eventlet.greenlet.GreenletExit:
                pass
            except Exception:
                LOG.exception(_LE('Error stopping thread.'))
Exemplo n.º 21
0
    def run_service(service, done):
        """Service start wrapper.

        :param service: service to run
        :param done: event to wait on until a shutdown is triggered
        :returns: None

        """
        try:
            service.start()
        except Exception:
            LOG.exception(_LE('Error starting thread.'))
            raise SystemExit(1)
        else:
            done.wait()
Exemplo n.º 22
0
    def _stop_threads(self):
        current = threading.current_thread()

        # Iterate over a copy of self.threads so thread_done doesn't
        # modify the list while we're iterating
        for x in self.threads[:]:
            if x.ident == current.ident:
                # don't kill the current thread.
                continue
            try:
                x.stop()
            except eventlet.greenlet.GreenletExit:
                pass
            except Exception:
                LOG.exception(_LE('Error stopping thread.'))
Exemplo n.º 23
0
    def cancel(self, *throw_args, **kwargs):
        self._perform_action_on_threads(
            lambda x: x.cancel(*throw_args),
            lambda x: LOG.exception(_LE('Error canceling thread.')))

        timeout = kwargs.get('timeout', None)
        if timeout is None:
            return
        wait_time = kwargs.get('wait_time', 1)
        watch = timeutils.StopWatch(duration=timeout)
        watch.start()
        while self._any_threads_alive():
            if not watch.expired():
                eventlet.sleep(wait_time)
                continue
            LOG.debug("Cancel timeout reached, stopping threads.")
            self.stop()
Exemplo n.º 24
0
 def _run_loop(self,
               kind,
               event,
               idle_for_func,
               initial_delay=None,
               stop_on_exception=True):
     func_name = reflection.get_callable_name(self.f)
     func = self.f if stop_on_exception else _safe_wrapper(
         self.f, kind, func_name)
     if initial_delay:
         greenthread.sleep(initial_delay)
     try:
         watch = timeutils.StopWatch()
         while self._running:
             watch.restart()
             result = func(*self.args, **self.kw)
             watch.stop()
             if not self._running:
                 break
             idle = idle_for_func(result, watch.elapsed())
             LOG.trace(
                 '%(kind)s %(func_name)r sleeping '
                 'for %(idle).02f seconds', {
                     'func_name': func_name,
                     'idle': idle,
                     'kind': kind
                 })
             greenthread.sleep(idle)
     except LoopingCallDone as e:
         event.send(e.retvalue)
     except Exception:
         exc_info = sys.exc_info()
         try:
             LOG.error(_LE('%(kind)s %(func_name)r failed'), {
                 'kind': kind,
                 'func_name': func_name
             },
                       exc_info=exc_info)
             event.send_exception(*exc_info)
         finally:
             del exc_info
         return
     else:
         event.send(True)
Exemplo n.º 25
0
    def wait(self):
        for x in self.timers:
            try:
                x.wait()
            except eventlet.greenlet.GreenletExit:
                pass
            except Exception:
                LOG.exception(_LE('Error waiting on ThreadGroup.'))
        current = threading.current_thread()

        # Iterate over a copy of self.threads so thread_done doesn't
        # modify the list while we're iterating
        for x in self.threads[:]:
            if x is current:
                continue
            try:
                x.wait()
            except eventlet.greenlet.GreenletExit:
                pass
            except Exception as ex:
                LOG.exception(ex)
Exemplo n.º 26
0
    def wait(self):
        for x in self.timers:
            try:
                x.wait()
            except eventlet.greenlet.GreenletExit:
                pass
            except Exception:
                LOG.exception(_LE('Error waiting on ThreadGroup.'))
        current = threading.current_thread()

        # Iterate over a copy of self.threads so thread_done doesn't
        # modify the list while we're iterating
        for x in self.threads[:]:
            if x.ident == current.ident:
                continue
            try:
                x.wait()
            except eventlet.greenlet.GreenletExit:
                pass
            except Exception as ex:
                LOG.exception(ex)
Exemplo n.º 27
0
    def _child_wait_for_exit_or_signal(self, launcher):
        status = 0
        signo = 0

        # NOTE(johannes): All exceptions are caught to ensure this
        # doesn't fallback into the loop spawning children. It would
        # be bad for a child to spawn more children.
        try:
            launcher.wait()
        except SignalExit as exc:
            signame = self.signal_handler.signals_to_name[exc.signo]
            LOG.info(_LI('Child caught %s, exiting'), signame)
            status = exc.code
            signo = exc.signo
        except SystemExit as exc:
            status = exc.code
        except BaseException:
            LOG.exception(_LE('Unhandled exception'))
            status = 2

        return status, signo
Exemplo n.º 28
0
    def _child_wait_for_exit_or_signal(self, launcher):
        status = 0
        signo = 0

        # NOTE(johannes): All exceptions are caught to ensure this
        # doesn't fallback into the loop spawning children. It would
        # be bad for a child to spawn more children.
        try:
            launcher.wait()
        except SignalExit as exc:
            signame = self.signal_handler.signals_to_name[exc.signo]
            LOG.info(_LI('Child caught %s, exiting'), signame)
            status = exc.code
            signo = exc.signo
        except SystemExit as exc:
            status = exc.code
        except BaseException:
            LOG.exception(_LE('Unhandled exception'))
            status = 2

        return status, signo
Exemplo n.º 29
0
 def _func(*args, **kwargs):
     result = None
     try:
         if self._retry_count:
             LOG.debug(
                 "Invoking %(func_name)s; retry count is "
                 "%(retry_count)d.", {
                     'func_name': func_name,
                     'retry_count': self._retry_count
                 })
         result = f(*args, **kwargs)
     except self._exceptions:
         with excutils.save_and_reraise_exception() as ctxt:
             LOG.warn(_LW("Exception which is in the suggested list of "
                          "exceptions occurred while invoking function:"
                          " %s."),
                      func_name,
                      exc_info=True)
             if (self._max_retry_count != -1
                     and self._retry_count >= self._max_retry_count):
                 LOG.error(
                     _LE("Cannot retry %(func_name)s upon "
                         "suggested exception "
                         "since retry count (%(retry_count)d) "
                         "reached max retry count "
                         "(%(max_retry_count)d)."), {
                             'retry_count': self._retry_count,
                             'max_retry_count': self._max_retry_count,
                             'func_name': func_name
                         })
             else:
                 ctxt.reraise = False
                 self._retry_count += 1
                 self._sleep_time += self._inc_sleep_time
                 return self._sleep_time
     raise LoopingCallDone(result)
Exemplo n.º 30
0
 def _stop_threads(self):
     self._perform_action_on_threads(
         lambda x: x.stop(),
         lambda x: LOG.exception(_LE('Error stopping thread.')))
Exemplo n.º 31
0
    def __init__(self, conf, name, app, host='0.0.0.0', port=0, pool_size=None,
                 protocol=eventlet.wsgi.HttpProtocol, backlog=128,
                 use_ssl=False, max_url_len=None):
        """Initialize, but do not start, a WSGI server.

        :param conf: Instance of ConfigOpts.
        :param name: Pretty name for logging.
        :param app: The WSGI application to serve.
        :param host: IP address to serve the application.
        :param port: Port number to server the application.
        :param pool_size: Maximum number of eventlets to spawn concurrently.
        :param protocol: Protocol class.
        :param backlog: Maximum number of queued connections.
        :param use_ssl: Wraps the socket in an SSL context if True.
        :param max_url_len: Maximum length of permitted URLs.
        :returns: None
        :raises: InvalidInput
        :raises: EnvironmentError
        """

        self.conf = conf
        self.conf.register_opts(_options.wsgi_opts)

        self.default_pool_size = self.conf.wsgi_default_pool_size

        # Allow operators to customize http requests max header line size.
        eventlet.wsgi.MAX_HEADER_LINE = conf.max_header_line
        self.name = name
        self.app = app
        self._server = None
        self._protocol = protocol
        self.pool_size = pool_size or self.default_pool_size
        self._pool = eventlet.GreenPool(self.pool_size)
        self._logger = logging.getLogger("eventlet.wsgi.server")
        self._use_ssl = use_ssl
        self._max_url_len = max_url_len
        self.client_socket_timeout = conf.client_socket_timeout or None

        if backlog < 1:
            raise InvalidInput(reason=_('The backlog must be more than 0'))

        bind_addr = (host, port)
        # TODO(dims): eventlet's green dns/socket module does not actually
        # support IPv6 in getaddrinfo(). We need to get around this in the
        # future or monitor upstream for a fix
        try:
            info = socket.getaddrinfo(bind_addr[0],
                                      bind_addr[1],
                                      socket.AF_UNSPEC,
                                      socket.SOCK_STREAM)[0]
            family = info[0]
            bind_addr = info[-1]
        except Exception:
            family = socket.AF_INET

        if self._use_ssl:
            sslutils.is_enabled(conf)

        try:
            self._socket = eventlet.listen(bind_addr, family, backlog=backlog)
        except EnvironmentError:
            LOG.error(_LE("Could not bind to %(host)s:%(port)s"),
                      {'host': host, 'port': port})
            raise

        (self.host, self.port) = self._socket.getsockname()[0:2]
        LOG.info(_LI("%(name)s listening on %(host)s:%(port)s"),
                 {'name': self.name, 'host': self.host, 'port': self.port})
Exemplo n.º 32
0
 def _stop_threads(self):
     self._perform_action_on_threads(
         lambda x: x.stop(),
         lambda x: LOG.exception(_LE('Error stopping thread.')))
Exemplo n.º 33
0
    def __init__(self,
                 conf,
                 name,
                 app,
                 host='0.0.0.0',
                 port=0,
                 pool_size=None,
                 protocol=eventlet.wsgi.HttpProtocol,
                 backlog=128,
                 use_ssl=False,
                 max_url_len=None):
        """Initialize, but do not start, a WSGI server.

        :param name: Pretty name for logging.
        :param app: The WSGI application to serve.
        :param host: IP address to serve the application.
        :param port: Port number to server the application.
        :param pool_size: Maximum number of eventlets to spawn concurrently.
        :param backlog: Maximum number of queued connections.
        :param max_url_len: Maximum length of permitted URLs.
        :returns: None
        :raises: InvalidInput
        """

        self.conf = conf
        self.conf.register_opts(_options.wsgi_opts)

        self.default_pool_size = self.conf.wsgi_default_pool_size

        # Allow operators to customize http requests max header line size.
        eventlet.wsgi.MAX_HEADER_LINE = conf.max_header_line
        self.name = name
        self.app = app
        self._server = None
        self._protocol = protocol
        self.pool_size = pool_size or self.default_pool_size
        self._pool = eventlet.GreenPool(self.pool_size)
        self._logger = logging.getLogger("eventlet.wsgi.server")
        self._use_ssl = use_ssl
        self._max_url_len = max_url_len
        self.client_socket_timeout = conf.client_socket_timeout or None
        self.default_pool_size = conf.wsgi_default_pool_size

        if backlog < 1:
            raise InvalidInput(reason='The backlog must be more than 0')

        bind_addr = (host, port)
        # TODO(dims): eventlet's green dns/socket module does not actually
        # support IPv6 in getaddrinfo(). We need to get around this in the
        # future or monitor upstream for a fix
        try:
            info = socket.getaddrinfo(bind_addr[0], bind_addr[1],
                                      socket.AF_UNSPEC, socket.SOCK_STREAM)[0]
            family = info[0]
            bind_addr = info[-1]
        except Exception:
            family = socket.AF_INET

        if self._use_ssl:
            sslutils.is_enabled(conf)

        try:
            self._socket = eventlet.listen(bind_addr, family, backlog=backlog)
        except EnvironmentError:
            LOG.error(_LE("Could not bind to %(host)s:%(port)s"), {
                'host': host,
                'port': port
            })
            raise

        (self.host, self.port) = self._socket.getsockname()[0:2]
        LOG.info(_LI("%(name)s listening on %(host)s:%(port)s"), {
            'name': self.name,
            'host': self.host,
            'port': self.port
        })