예제 #1
0
    def __init__(self, conf, name, app, host='0.0.0.0', port=0,  # nosec
                 pool_size=None, protocol=eventlet.wsgi.HttpProtocol,
                 backlog=128, use_ssl=False, max_url_len=None,
                 logger_name='eventlet.wsgi.server',
                 socket_family=None, socket_file=None, socket_mode=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.
        :param logger_name: The name for the logger.
        :param socket_family: Socket family.
        :param socket_file: location of UNIX socket.
        :param socket_mode: UNIX socket mode.
        :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(logger_name)
        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'))

        if not socket_family or socket_family in [socket.AF_INET,
                                                  socket.AF_INET6]:
            self.socket = self._get_socket(host, port, backlog)
        elif hasattr(socket, "AF_UNIX") and socket_family == socket.AF_UNIX:
            self.socket = self._get_unix_socket(socket_file, socket_mode,
                                                backlog)
        else:
            raise ValueError(_("Unsupported socket family: %s"), socket_family)

        (self.host, self.port) = self.socket.getsockname()[0:2]

        if self._use_ssl:
            sslutils.is_enabled(conf)
예제 #2
0
def launch(conf, service, workers=1, restart_method='reload'):
    """Launch a service with a given number of workers.

    :param conf: an instance of ConfigOpts
    :param service: a service to launch, must be an instance of
           :class:`oslo_service.service.ServiceBase`
    :param workers: a number of processes in which a service will be running,
        type should be int.
    :param restart_method: Passed to the constructed launcher. If 'reload', the
        launcher will call reload_config_files on SIGHUP. If 'mutate', it will
        call mutate_config_files on SIGHUP. Other values produce a ValueError.
    :returns: instance of a launcher that was used to launch the service
    """

    if workers is not None and not isinstance(workers, int):
        raise TypeError(_("Type of workers should be int!"))

    if workers is not None and workers <= 0:
        raise ValueError(_("Number of workers should be positive!"))

    if workers is None or workers == 1:
        launcher = ServiceLauncher(conf, restart_method=restart_method)
    else:
        launcher = ProcessLauncher(conf, restart_method=restart_method)
    launcher.launch_service(service, workers=workers)

    return launcher
예제 #3
0
def wrap(conf, sock):
    conf.register_opts(_options.ssl_opts, config_section)
    ssl_kwargs = {
        'server_side': True,
        'certfile': conf.ssl.cert_file,
        'keyfile': conf.ssl.key_file,
        'cert_reqs': ssl.CERT_NONE,
    }

    if conf.ssl.ca_file:
        ssl_kwargs['ca_certs'] = conf.ssl.ca_file
        ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED

        if conf.ssl.version:
            key = conf.ssl.version.lower()
            try:
                ssl_kwargs['ssl_version'] = _SSL_PROTOCOLS[key]
            except KeyError:
                raise RuntimeError(
                    _("Invalid SSL version : %s") % conf.ssl.version)

        if conf.ssl.ciphers:
            ssl_kwargs['ciphers'] = conf.ssl.ciphers

    # NOTE(eezhova): SSL/TLS protocol version is injected in ssl_kwargs above,
    # so skipping bandit check
    return ssl.wrap_socket(sock, **ssl_kwargs)  # nosec
예제 #4
0
def wrap(conf, sock):
    conf.register_opts(_options.ssl_opts, config_section)
    ssl_kwargs = {
        'server_side': True,
        'certfile': conf.ssl.cert_file,
        'keyfile': conf.ssl.key_file,
        'cert_reqs': ssl.CERT_NONE,
    }

    if conf.ssl.ca_file:
        ssl_kwargs['ca_certs'] = conf.ssl.ca_file
        ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED

        if conf.ssl.version:
            key = conf.ssl.version.lower()
            try:
                ssl_kwargs['ssl_version'] = _SSL_PROTOCOLS[key]
            except KeyError:
                raise RuntimeError(
                    _("Invalid SSL version : %s") % conf.ssl.version)

        if conf.ssl.ciphers:
            ssl_kwargs['ciphers'] = conf.ssl.ciphers

    return ssl.wrap_socket(sock, **ssl_kwargs)
예제 #5
0
 def __init__(self, restart_method='reload'):
     if restart_method not in _LAUNCHER_RESTART_METHODS:
         raise ValueError(_("Invalid restart_method: %s") % restart_method)
     self.restart_method = restart_method
     self.services = []
     self.tg = threadgroup.ThreadGroup()
     self.done = event.Event()
예제 #6
0
def wrap(conf, sock):
    conf.register_opts(_options.ssl_opts, config_section)
    ssl_kwargs = {
        'server_side': True,
        'certfile': conf.ssl.cert_file,
        'keyfile': conf.ssl.key_file,
        'cert_reqs': ssl.CERT_NONE,
    }

    if conf.ssl.ca_file:
        ssl_kwargs['ca_certs'] = conf.ssl.ca_file
        ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED

        if conf.ssl.version:
            key = conf.ssl.version.lower()
            try:
                ssl_kwargs['ssl_version'] = _SSL_PROTOCOLS[key]
            except KeyError:
                raise RuntimeError(
                    _("Invalid SSL version : %s") % conf.ssl.version)

        if conf.ssl.ciphers:
            ssl_kwargs['ciphers'] = conf.ssl.ciphers

    # NOTE(eezhova): SSL/TLS protocol version is injected in ssl_kwargs above,
    # so skipping bandit check
    return ssl.wrap_socket(sock, **ssl_kwargs)  # nosec
예제 #7
0
def _check_service_base(service):
    if not isinstance(service, ServiceBase):
        raise TypeError(
            _("Service %(service)s must an instance of %(base)s!") % {
                'service': service,
                'base': ServiceBase
            })
예제 #8
0
 def __init__(self, port_range, help_msg, ex):
     msg = (_('Invalid backdoor_port configuration %(range)s: %(ex)s. '
              '%(help)s') % {
                  'range': port_range,
                  'ex': ex,
                  'help': help_msg
              })
     super(EventletBackdoorConfigValueError, self).__init__(msg)
     self.port_range = port_range
예제 #9
0
class FixedIntervalLoopingCall(LoopingCallBase):
    """A fixed interval looping call."""

    _RUN_ONLY_ONE_MESSAGE = _("A fixed interval looping call can only run"
                              " one function at a time")

    _KIND = _('Fixed interval looping call')

    def start(self, interval, initial_delay=None, stop_on_exception=True):
        def _idle_for(result, elapsed):
            delay = round(elapsed - interval, 2)
            if delay > 0:
                func_name = reflection.get_callable_name(self.f)
                LOG.warning(_LW('Function %(func_name)r run outlasted '
                                'interval by %(delay).2f sec'),
                            {'func_name': func_name, 'delay': delay})
            return -delay if delay < 0 else 0
        return self._start(_idle_for, initial_delay=initial_delay,
                           stop_on_exception=stop_on_exception)
예제 #10
0
class DynamicLoopingCall(LoopingCallBase):
    """A looping call which sleeps until the next known event.

    The function called should return how long to sleep for before being
    called again.
    """

    _RUN_ONLY_ONE_MESSAGE = _("A dynamic interval looping call can only run"
                              " one function at a time")

    _KIND = _('Dynamic interval looping call')

    def start(self, initial_delay=None, periodic_interval_max=None):
        def _idle_for(suggested_delay, elapsed):
            delay = suggested_delay
            if periodic_interval_max is not None:
                delay = min(delay, periodic_interval_max)
            return delay

        return self._start(_idle_for, initial_delay=initial_delay)
예제 #11
0
def is_enabled():
    cert_file = CONF.ssl.cert_file
    key_file = CONF.ssl.key_file
    ca_file = CONF.ssl.ca_file
    use_ssl = cert_file or key_file

    if cert_file and not os.path.exists(cert_file):
        raise RuntimeError(_("Unable to find cert_file : %s") % cert_file)

    if ca_file and not os.path.exists(ca_file):
        raise RuntimeError(_("Unable to find ca_file : %s") % ca_file)

    if key_file and not os.path.exists(key_file):
        raise RuntimeError(_("Unable to find key_file : %s") % key_file)

    if use_ssl and (not cert_file or not key_file):
        raise RuntimeError(_("When running server in SSL mode, you must "
                             "specify both a cert_file and key_file "
                             "option value in your configuration file"))

    return use_ssl
예제 #12
0
class FixedIntervalLoopingCall(LoopingCallBase):
    """A fixed interval looping call."""

    _RUN_ONLY_ONE_MESSAGE = _("A fixed interval looping call can only run"
                              " one function at a time")

    _KIND = _('Fixed interval looping call')

    def start(self, interval, initial_delay=None):
        def _idle_for(result, elapsed):
            delay = elapsed - interval
            if delay > 0:
                LOG.warning(
                    _LW('Function %(func_name)r run outlasted '
                        'interval by %(delay).2f sec'), {
                            'func_name': self.f,
                            'delay': delay
                        })
            return -delay if delay < 0 else 0

        return self._start(_idle_for, initial_delay=initial_delay)
예제 #13
0
 def _idle_for(result, elapsed):
     delay = round(elapsed - interval, 2)
     if delay > 0:
         func_name = reflection.get_callable_name(self.f)
         LOG.warning('Function %(func_name)r run outlasted '
                     'interval by %(delay).2f sec',
                     {'func_name': func_name, 'delay': delay})
     elapsed_time = time.time() - start_time
     if timeout > 0 and elapsed_time > timeout:
         raise LoopingCallTimeOut(
             _('Looping call timed out after %.02f seconds')
             % elapsed_time)
     return -delay if delay < 0 else 0
예제 #14
0
def is_enabled(conf):
    conf.register_opts(_options.ssl_opts, config_section)
    cert_file = conf.ssl.cert_file
    key_file = conf.ssl.key_file
    ca_file = conf.ssl.ca_file
    use_ssl = cert_file or key_file

    if cert_file and not os.path.exists(cert_file):
        raise RuntimeError(_("Unable to find cert_file : %s") % cert_file)

    if ca_file and not os.path.exists(ca_file):
        raise RuntimeError(_("Unable to find ca_file : %s") % ca_file)

    if key_file and not os.path.exists(key_file):
        raise RuntimeError(_("Unable to find key_file : %s") % key_file)

    if use_ssl and (not cert_file or not key_file):
        raise RuntimeError(
            _("When running server in SSL mode, you must "
              "specify both a cert_file and key_file "
              "option value in your configuration file"))

    return use_ssl
예제 #15
0
class DynamicLoopingCall(LoopingCallBase):
    """A looping call which sleeps until the next known event.

    The function called should return how long to sleep for before being
    called again.
    """

    _RUN_ONLY_ONE_MESSAGE = _("A dynamic interval looping call can only run"
                              " one function at a time")
    _TASK_MISSING_SLEEP_VALUE_MESSAGE = _(
        "A dynamic interval looping call should supply either an"
        " interval or periodic_interval_max")

    _KIND = _('Dynamic interval looping call')

    def start(self,
              initial_delay=None,
              periodic_interval_max=None,
              stop_on_exception=True):
        def _idle_for(suggested_delay, elapsed):
            delay = suggested_delay
            if delay is None:
                if periodic_interval_max is not None:
                    delay = periodic_interval_max
                else:
                    # Note(suro-patz): An application used to receive a
                    #     TypeError thrown from eventlet layer, before
                    #     this RuntimeError was introduced.
                    raise RuntimeError(self._TASK_MISSING_SLEEP_VALUE_MESSAGE)
            else:
                if periodic_interval_max is not None:
                    delay = min(delay, periodic_interval_max)
            return delay

        return self._start(_idle_for,
                           initial_delay=initial_delay,
                           stop_on_exception=stop_on_exception)
예제 #16
0
class FixedIntervalWithTimeoutLoopingCall(LoopingCallBase):
    """A fixed interval looping call with timeout checking mechanism."""

    _RUN_ONLY_ONE_MESSAGE = _("A fixed interval looping call with timeout"
                              " checking and can only run one function at"
                              " at a time")

    _KIND = _('Fixed interval looping call with timeout checking.')

    def start(self,
              interval,
              initial_delay=None,
              stop_on_exception=True,
              timeout=0):
        start_time = time.time()

        def _idle_for(result, elapsed):
            delay = round(elapsed - interval, 2)
            if delay > 0:
                func_name = reflection.get_callable_name(self.f)
                LOG.warning(
                    'Function %(func_name)r run outlasted '
                    'interval by %(delay).2f sec', {
                        'func_name': func_name,
                        'delay': delay
                    })
            elapsed_time = time.time() - start_time
            if timeout > 0 and elapsed_time > timeout:
                raise LoopingCallTimeOut(
                    _('Looping call timed out after %.02f seconds') %
                    elapsed_time)
            return -delay if delay < 0 else 0

        return self._start(_idle_for,
                           initial_delay=initial_delay,
                           stop_on_exception=stop_on_exception)
예제 #17
0
 def _idle_for(result, elapsed):
     delay = round(elapsed - interval, 2)
     if delay > 0:
         func_name = reflection.get_callable_name(self.f)
         LOG.warning(
             'Function %(func_name)r run outlasted '
             'interval by %(delay).2f sec', {
                 'func_name': func_name,
                 'delay': delay
             })
     elapsed_time = time.time() - start_time
     if timeout > 0 and elapsed_time > timeout:
         raise LoopingCallTimeOut(
             _('Looping call timed out after %.02f seconds') %
             elapsed_time)
     return -delay if delay < 0 else 0
예제 #18
0
    def launch_service(self, service, workers=1):
        """Load and start the given service.

        :param service: The service you would like to start, must be an
                        instance of :class:`oslo_service.service.ServiceBase`
        :param workers: This param makes this method compatible with
                        ProcessLauncher.launch_service. It must be None, 1 or
                        omitted.
        :returns: None

        """
        if workers is not None and workers != 1:
            raise ValueError(_("Launcher asked to start multiple workers"))
        _check_service_base(service)
        service.backdoor_port = self.backdoor_port
        self.services.add(service)
예제 #19
0
    def launch_service(self, service, workers=1):
        """Load and start the given service.

        :param service: The service you would like to start, must be an
                        instance of :class:`oslo_service.service.ServiceBase`
        :param workers: This param makes this method compatible with
                        ProcessLauncher.launch_service. It must be None, 1 or
                        omitted.
        :returns: None

        """
        if workers is not None and workers != 1:
            raise ValueError(_("Launcher asked to start multiple workers"))
        _check_service_base(service)
        service.backdoor_port = self.backdoor_port
        self.services.add(service)
예제 #20
0
    def __init__(self, conf, restart_method='reload'):
        """Initialize the service launcher.

        :param restart_method: If 'reload', calls reload_config_files on
            SIGHUP. If 'mutate', calls mutate_config_files on SIGHUP. Other
            values produce a ValueError.
        :returns: None

        """
        self.conf = conf
        conf.register_opts(_options.service_opts)
        self.services = Services()
        self.backdoor_port = (
            eventlet_backdoor.initialize_if_enabled(self.conf))
        self.restart_method = restart_method
        if restart_method not in _LAUNCHER_RESTART_METHODS:
            raise ValueError(_("Invalid restart_method: %s") % restart_method)
예제 #21
0
    def __init__(self, conf, restart_method='reload'):
        """Initialize the service launcher.

        :param restart_method: If 'reload', calls reload_config_files on
            SIGHUP. If 'mutate', calls mutate_config_files on SIGHUP. Other
            values produce a ValueError.
        :returns: None

        """
        self.conf = conf
        conf.register_opts(_options.service_opts)
        self.services = Services()
        self.backdoor_port = (eventlet_backdoor.initialize_if_enabled(
            self.conf))
        self.restart_method = restart_method
        if restart_method not in _LAUNCHER_RESTART_METHODS:
            raise ValueError(_("Invalid restart_method: %s") % restart_method)
예제 #22
0
def _main():
    import eventlet
    eventlet.monkey_patch(all=True)

    from oslo_config import cfg

    logging.basicConfig(level=logging.DEBUG)

    conf = cfg.ConfigOpts()
    conf.register_cli_opts(_options.eventlet_backdoor_opts)
    conf(sys.argv[1:])

    where_running_thread = _initialize_if_enabled(conf)
    if not where_running_thread:
        raise RuntimeError(_("Did not create backdoor at requested location"))
    else:
        _where_running, thread = where_running_thread
        thread.wait()
예제 #23
0
def _main():
    import eventlet
    eventlet.monkey_patch(all=True)

    from oslo_config import cfg

    logging.basicConfig(level=logging.DEBUG)

    conf = cfg.ConfigOpts()
    conf.register_cli_opts(_options.eventlet_backdoor_opts)
    conf(sys.argv[1:])

    where_running_thread = _initialize_if_enabled(conf)
    if not where_running_thread:
        raise RuntimeError(_("Did not create backdoor at requested location"))
    else:
        _where_running, thread = where_running_thread
        thread.wait()
예제 #24
0
 def _idle_for(success, _elapsed):
     random_jitter = self._RNG.gauss(jitter, 0.1)
     if success:
         # Reset error state now that it didn't error...
         self._interval = starting_interval
         self._error_time = 0
         return self._interval * random_jitter
     else:
         # Perform backoff
         self._interval = idle = min(
             self._interval * 2 * random_jitter, max_interval)
         # Don't go over timeout, end early if necessary. If
         # timeout is 0, keep going.
         if timeout > 0 and self._error_time + idle > timeout:
             raise LoopingCallTimeOut(
                 _('Looping call timed out after %.02f seconds')
                 % self._error_time)
         self._error_time += idle
         return idle
예제 #25
0
def launch(conf, service, workers=1):
    """Launch a service with a given number of workers.

    :param conf: an instance of ConfigOpts
    :param service: a service to launch, must be an instance of
           :class:`oslo_service.service.ServiceBase`
    :param workers: a number of processes in which a service will be running
    :returns: instance of a launcher that was used to launch the service
    """

    if workers is not None and workers <= 0:
        raise ValueError(_("Number of workers should be positive!"))

    if workers is None or workers == 1:
        launcher = ServiceLauncher(conf)
        launcher.launch_service(service)
    else:
        launcher = ProcessLauncher(conf)
        launcher.launch_service(service, workers=workers)

    return launcher
예제 #26
0
def launch(conf, service, workers=1):
    """Launch a service with a given number of workers.

    :param conf: an instance of ConfigOpts
    :param service: a service to launch, must be an instance of
           :class:`oslo_service.service.ServiceBase`
    :param workers: a number of processes in which a service will be running
    :returns: instance of a launcher that was used to launch the service
    """

    if workers is not None and workers <= 0:
        raise ValueError(_("Number of workers should be positive!"))

    if workers is None or workers == 1:
        launcher = ServiceLauncher(conf)
        launcher.launch_service(service)
    else:
        launcher = ProcessLauncher(conf)
        launcher.launch_service(service, workers=workers)

    return launcher
예제 #27
0
def launch(conf, service, workers=1, restart_method='reload'):
    """Launch a service with a given number of workers.

    :param conf: an instance of ConfigOpts
    :param service: a service to launch, must be an instance of
           :class:`oslo_service.service.ServiceBase`
    :param workers: a number of processes in which a service will be running
    :param restart_method: Passed to the constructed launcher. If 'reload', the
        launcher will call reload_config_files on SIGHUP. If 'mutate', it will
        call mutate_config_files on SIGHUP. Other values produce a ValueError.
    :returns: instance of a launcher that was used to launch the service
    """

    if workers is not None and workers <= 0:
        raise ValueError(_("Number of workers should be positive!"))

    if workers is None or workers == 1:
        launcher = ServiceLauncher(conf, restart_method=restart_method)
    else:
        launcher = ProcessLauncher(conf, restart_method=restart_method)
    launcher.launch_service(service, workers=workers)

    return launcher
예제 #28
0
 def _idle_for(success, _elapsed):
     random_jitter = abs(self._RNG.gauss(jitter, 0.1))
     if success:
         # Reset error state now that it didn't error...
         self._interval = starting_interval
         self._error_time = 0
         return self._interval * random_jitter
     else:
         # Perform backoff, random jitter around the next interval
         # bounded by min_interval and max_interval.
         idle = max(self._interval * 2 * random_jitter, min_interval)
         idle = min(idle, max_interval)
         # Calculate the next interval based on the mean, so that the
         # backoff grows at the desired rate.
         self._interval = max(self._interval * 2 * jitter, min_interval)
         # Don't go over timeout, end early if necessary. If
         # timeout is 0, keep going.
         if timeout > 0 and self._error_time + idle > timeout:
             raise LoopingCallTimeOut(
                 _('Looping call timed out after %.02f seconds') %
                 self._error_time)
         self._error_time += idle
         return idle
예제 #29
0
 def _idle_for(success, _elapsed):
     random_jitter = abs(self._RNG.gauss(jitter, 0.1))
     if success:
         # Reset error state now that it didn't error...
         self._interval = starting_interval
         self._error_time = 0
         return self._interval * random_jitter
     else:
         # Perform backoff, random jitter around the next interval
         # bounded by min_interval and max_interval.
         idle = max(self._interval * 2 * random_jitter, min_interval)
         idle = min(idle, max_interval)
         # Calculate the next interval based on the mean, so that the
         # backoff grows at the desired rate.
         self._interval = max(self._interval * 2 * jitter, min_interval)
         # Don't go over timeout, end early if necessary. If
         # timeout is 0, keep going.
         if timeout > 0 and self._error_time + idle > timeout:
             raise LoopingCallTimeOut(
                 _('Looping call timed out after %.02f seconds')
                 % self._error_time)
         self._error_time += idle
         return idle
예제 #30
0
def _main():
    import eventlet
    eventlet.monkey_patch(all=True)
    # Monkey patch the original current_thread to use the up-to-date _active
    # global variable. See https://bugs.launchpad.net/bugs/1863021 and
    # https://github.com/eventlet/eventlet/issues/592
    import __original_module_threading as orig_threading
    import threading  # noqa
    orig_threading.current_thread.__globals__['_active'] = threading._active

    from oslo_config import cfg

    logging.basicConfig(level=logging.DEBUG)

    conf = cfg.ConfigOpts()
    conf.register_cli_opts(_options.eventlet_backdoor_opts)
    conf(sys.argv[1:])

    where_running_thread = _initialize_if_enabled(conf)
    if not where_running_thread:
        raise RuntimeError(_("Did not create backdoor at requested location"))
    else:
        _where_running, thread = where_running_thread
        thread.wait()
예제 #31
0
    def __init__(self, conf, wait_interval=0.01, restart_method='reload'):
        """Constructor.

        :param conf: an instance of ConfigOpts
        :param wait_interval: The interval to sleep for between checks
                              of child process exit.
        :param restart_method: If 'reload', calls reload_config_files on
            SIGHUP. If 'mutate', calls mutate_config_files on SIGHUP. Other
            values produce a ValueError.
        """
        self.conf = conf
        conf.register_opts(_options.service_opts)
        self.children = {}
        self.sigcaught = None
        self.running = True
        self.wait_interval = wait_interval
        self.launcher = None
        rfd, self.writepipe = os.pipe()
        self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
        self.signal_handler = SignalHandler()
        self.handle_signal()
        self.restart_method = restart_method
        if restart_method not in _LAUNCHER_RESTART_METHODS:
            raise ValueError(_("Invalid restart_method: %s") % restart_method)
예제 #32
0
    def __init__(self, conf, wait_interval=0.01, restart_method='reload'):
        """Constructor.

        :param conf: an instance of ConfigOpts
        :param wait_interval: The interval to sleep for between checks
                              of child process exit.
        :param restart_method: If 'reload', calls reload_config_files on
            SIGHUP. If 'mutate', calls mutate_config_files on SIGHUP. Other
            values produce a ValueError.
        """
        self.conf = conf
        conf.register_opts(_options.service_opts)
        self.children = {}
        self.sigcaught = None
        self.running = True
        self.wait_interval = wait_interval
        self.launcher = None
        rfd, self.writepipe = os.pipe()
        self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
        self.signal_handler = SignalHandler()
        self.handle_signal()
        self.restart_method = restart_method
        if restart_method not in _LAUNCHER_RESTART_METHODS:
            raise ValueError(_("Invalid restart_method: %s") % restart_method)
예제 #33
0
 def __init__(self, name, path):
     msg = (_("Could not load paste app '%(name)s' from %(path)s") %
            {'name': name, 'path': path})
     super(PasteAppNotFound, self).__init__(msg)
예제 #34
0
class BackOffLoopingCall(LoopingCallBase):
    """Run a method in a loop with backoff on error.

    The passed in function should return True (no error, return to
    initial_interval),
    False (error, start backing off), or raise LoopingCallDone(retvalue=None)
    (quit looping, return retvalue if set).

    When there is an error, the call will backoff on each failure. The
    backoff will be equal to double the previous base interval times some
    jitter. If a backoff would put it over the timeout, it halts immediately,
    so the call will never take more than timeout, but may and likely will
    take less time.

    When the function return value is True or False, the interval will be
    multiplied by a random jitter. If min_jitter or max_jitter is None,
    there will be no jitter (jitter=1). If min_jitter is below 0.5, the code
    may not backoff and may increase its retry rate.

    If func constantly returns True, this function will not return.

    To run a func and wait for a call to finish (by raising a LoopingCallDone):

        timer = BackOffLoopingCall(func)
        response = timer.start().wait()

    :param initial_delay: delay before first running of function
    :param starting_interval: initial interval in seconds between calls to
                              function. When an error occurs and then a
                              success, the interval is returned to
                              starting_interval
    :param timeout: time in seconds before a LoopingCallTimeout is raised.
                    The call will never take longer than timeout, but may quit
                    before timeout.
    :param max_interval: The maximum interval between calls during errors
    :param jitter: Used to vary when calls are actually run to avoid group of
                   calls all coming at the exact same time. Uses
                   random.gauss(jitter, 0.1), with jitter as the mean for the
                   distribution. If set below .5, it can cause the calls to
                   come more rapidly after each failure.
    :param min_interval: The minimum interval in seconds between calls to
                         function.
    :raises: LoopingCallTimeout if time spent doing error retries would exceed
             timeout.
    """

    _RNG = random.SystemRandom()
    _KIND = _('Dynamic backoff interval looping call')
    _RUN_ONLY_ONE_MESSAGE = _("A dynamic backoff interval looping call can"
                              " only run one function at a time")

    def __init__(self, f=None, *args, **kw):
        super(BackOffLoopingCall, self).__init__(f=f, *args, **kw)
        self._error_time = 0
        self._interval = 1

    def start(self,
              initial_delay=None,
              starting_interval=1,
              timeout=300,
              max_interval=300,
              jitter=0.75,
              min_interval=0.001):
        if self._thread is not None:
            raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE)

        # Reset any prior state.
        self._error_time = 0
        self._interval = starting_interval

        def _idle_for(success, _elapsed):
            random_jitter = abs(self._RNG.gauss(jitter, 0.1))
            if success:
                # Reset error state now that it didn't error...
                self._interval = starting_interval
                self._error_time = 0
                return self._interval * random_jitter
            else:
                # Perform backoff, random jitter around the next interval
                # bounded by min_interval and max_interval.
                idle = max(self._interval * 2 * random_jitter, min_interval)
                idle = min(idle, max_interval)
                # Calculate the next interval based on the mean, so that the
                # backoff grows at the desired rate.
                self._interval = max(self._interval * 2 * jitter, min_interval)
                # Don't go over timeout, end early if necessary. If
                # timeout is 0, keep going.
                if timeout > 0 and self._error_time + idle > timeout:
                    raise LoopingCallTimeOut(
                        _('Looping call timed out after %.02f seconds') %
                        self._error_time)
                self._error_time += idle
                return idle

        return self._start(_idle_for, initial_delay=initial_delay)
예제 #35
0
class LoopingCallBase(object):
    _KIND = _("Unknown looping call")

    _RUN_ONLY_ONE_MESSAGE = _("A looping call can only run one function"
                              " at a time")

    def __init__(self, f=None, *args, **kw):
        self.args = args
        self.kw = kw
        self.f = f
        self._running = False
        self._thread = None
        self.done = None

    def stop(self):
        self._running = False

    def wait(self):
        return self.done.wait()

    def _on_done(self, gt, *args, **kwargs):
        self._thread = None
        self._running = False

    def _start(self, idle_for, initial_delay=None):
        if self._thread is not None:
            raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE)
        self._running = True
        self.done = event.Event()
        self._thread = greenthread.spawn(self._run_loop,
                                         self._KIND,
                                         self.done,
                                         idle_for,
                                         initial_delay=initial_delay)
        self._thread.link(self._on_done)
        return self.done

    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)
예제 #36
0
class InvalidPeriodicTaskArg(Exception):
    message = _("Unexpected argument for periodic task creation: %(arg)s.")
예제 #37
0
class LoopingCallBase(object):
    _KIND = _("Unknown looping call")

    _RUN_ONLY_ONE_MESSAGE = _("A looping call can only run one function"
                              " at a time")

    def __init__(self, f=None, *args, **kw):
        self.args = args
        self.kw = kw
        self.f = f
        self._running = False
        self._thread = None
        self.done = None

    def stop(self):
        self._running = False

    def wait(self):
        return self.done.wait()

    def _on_done(self, gt, *args, **kwargs):
        self._thread = None
        self._running = False

    def _start(self, idle_for, initial_delay=None, stop_on_exception=True):
        """Start the looping

        :param idle_for: Callable that takes two positional arguments, returns
                         how long to idle for. The first positional argument is
                         the last result from the function being looped and the
                         second positional argument is the time it took to
                         calculate that result.
        :param initial_delay: How long to delay before starting the looping.
                              Value is in seconds.
        :param stop_on_exception: Whether to stop if an exception occurs.
        :returns: eventlet event instance
        """
        if self._thread is not None:
            raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE)
        self._running = True
        self.done = event.Event()
        self._thread = greenthread.spawn(self._run_loop,
                                         idle_for,
                                         initial_delay=initial_delay,
                                         stop_on_exception=stop_on_exception)
        self._thread.link(self._on_done)
        return self.done

    def _run_loop(self,
                  idle_for_func,
                  initial_delay=None,
                  stop_on_exception=True):
        kind = self._KIND
        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:
            self.done.send(e.retvalue)
        except Exception:
            exc_info = sys.exc_info()
            try:
                LOG.error('%(kind)s %(func_name)r failed', {
                    'kind': kind,
                    'func_name': func_name
                },
                          exc_info=exc_info)
                self.done.send_exception(*exc_info)
            finally:
                del exc_info
            return
        else:
            self.done.send(True)
예제 #38
0
 def __init__(self, name, path):
     msg = _("Could not load paste app '%(name)s' from %(path)s") % {"name": name, "path": path}
     super(PasteAppNotFound, self).__init__(msg)
예제 #39
0
 def __init__(self, path):
     msg = _("Could not find config at %(path)s") % {"path": path}
     super(ConfigNotFound, self).__init__(msg)
예제 #40
0
def _check_service_base(service):
    if not isinstance(service, ServiceBase):
        raise TypeError(_("Service %(service)s must an instance of %(base)s!")
                        % {'service': service, 'base': ServiceBase})
예제 #41
0
 def __init__(self, name, path):
     msg = (_("Could not load paste app '%(name)s' from %(path)s") % {
         'name': name,
         'path': path
     })
     super(PasteAppNotFound, self).__init__(msg)
예제 #42
0
class InvalidInput(Exception):
    message = _("Invalid input received: "
                "Unexpected argument for periodic task creation: %(arg)s.")
예제 #43
0
 def __init__(self, port_range, help_msg, ex):
     msg = (_('Invalid backdoor_port configuration %(range)s: %(ex)s. '
            '%(help)s') %
            {'range': port_range, 'ex': ex, 'help': help_msg})
     super(EventletBackdoorConfigValueError, self).__init__(msg)
     self.port_range = port_range
예제 #44
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})
예제 #45
0
 def __init__(self, path):
     msg = _('Could not find config at %(path)s') % {'path': path}
     super(ConfigNotFound, self).__init__(msg)
예제 #46
0
 def __init__(self, path):
     msg = _('Could not find config at %(path)s') % {'path': path}
     super(ConfigNotFound, self).__init__(msg)