def validate(self, props):
     # validate arguments, can changes props
     # throws ArgumentError if invalid in total
     # throws MessageError if content invalid
     if not OPT_ADDRESS in props:
         raise MessageError('address is missing')
     if not OPT_CLUSTER in props:
         raise MessageError('cluster is missing')
     elif not isinstance(props[OPT_CLUSTER], list):
         raise MessageError('cluster malformed: list expected')
     elif len(props[OPT_CLUSTER]) == 0:
         raise MessageError('cluster is empty')
     if not OPT_IDENTIFIER in props:
         raise MessageError('identifier is missing')
Exemple #2
0
    def execute(self, arbiter, props):
        options = props.get('options', {})

        # check for endpoint_owner uid restriction mode
        # it would be better to use some type of SO_PEERCRED lookup on the ipc
        # socket to get the uid of the client process and restrict on that,
        # but there's no good portable pythonic way of doing that right now
        # inside pyzmq or here. So we'll assume that the administrator has
        # set good rights on the ipc socket to help prevent privilege
        # escalation
        if arbiter.endpoint_owner_mode:
            cmd_uid = options.get('uid', None)
            if cmd_uid != arbiter.endpoint_owner:
                raise MessageError("uid does not match endpoint_owner")

        # convert all rlimit_* options into one rlimits dict which is required
        # by the watcher constructor (follows same pattern as config.py)
        rlimits = {}
        for key, val in options.items():
            if key.startswith('rlimit_'):
                rlimits[key[7:]] = rlimit_value(val)

        if len(rlimits) > 0:
            options['rlimits'] = rlimits
            for key in rlimits.keys():
                del options['rlimit_' + key]

        # now create and start the watcher
        watcher = arbiter.add_watcher(props['name'],
                                      props['cmd'],
                                      args=props.get('args'),
                                      **options)
        if props.get('start', False):
            return watcher.start()
Exemple #3
0
def execute_watcher_start_stop_restart(arbiter, props, watcher_function_name,
                                       watchers_function, arbiter_function):
    """base function to handle start/stop/restart watcher requests.
    since this is always the same procedure except some function names this
    function handles all watcher start/stop commands
    """
    if 'name' in props:
        name = re.compile(fnmatch.translate(props['name']))
        watchers = [watcher
                    for watcher in arbiter.iter_watchers()
                    if name.match(watcher.name.lower())]
        if not watchers:
            raise MessageError("program %s not found" % props['name'])

        if len(watchers) == 1:
            if props.get('waiting'):
                resp = TransformableFuture()
                func = getattr(watchers[0], watcher_function_name)
                resp.set_upstream_future(func())
                resp.set_transform_function(lambda x: {"info": x})
                return resp
            return getattr(watchers[0], watcher_function_name)()

        def watcher_iter_func(reverse=True):
            return sorted(watchers, key=lambda a: a.priority, reverse=reverse)

        return watchers_function(watcher_iter_func=watcher_iter_func)
    else:
        return arbiter_function()
Exemple #4
0
    def validate(self, props):
        if not self.properties:
            return

        for propname in self.properties:
            if propname not in props:
                raise MessageError("message invalid %r is missing" % propname)
Exemple #5
0
 def execute(self, arbiter, props):
     if 'name' in props:
         watcher = self._get_watcher(arbiter, props['name'])
         if 'process' in props:
             try:
                 return {
                     "process":
                     props['process'],
                     "info":
                     watcher.process_info(props['process'],
                                          props.get('extended')),
                 }
             except KeyError:
                 raise MessageError("process %r not found in %r" %
                                    (props['process'], props['name']))
         else:
             return {
                 "name": props['name'],
                 "info": watcher.info(props.get('extended'))
             }
     else:
         infos = {}
         for watcher in arbiter.watchers:
             infos[watcher.name] = watcher.info()
         return {"infos": infos}
Exemple #6
0
def validate_option(key, val):
    if key not in ('numprocesses', 'warmup_delay', 'working_dir', 'uid', 'gid',
                   'send_hup', 'shell', 'env', 'cmd', 'flapping_attempts',
                   'flapping_window', 'retry_in', 'max_retry',
                   'graceful_timeout', 'stdout_stream', 'stderr_stream',
                   'max_age', 'max_age_variance'):
        raise MessageError('unknown key %r' % key)

    if key in (
            'numprocesses',
            'flapping_attempts',
            'max_retry',
            'max_age',
            'max_age_variance',
    ):
        if not isinstance(val, int):
            raise MessageError("%r isn't an integer" % key)

    if key in (
            'warmup_delay',
            'flapping_window',
            'retry_in',
            'graceful_timeout',
    ):
        if not isinstance(val, (
                int,
                float,
        )):
            raise MessageError("%r isn't a number" % key)

    if key in (
            'uid',
            'gid',
    ):
        if not isinstance(val, int) or not isinstance(val, string_types):
            raise MessageError("%r isn't an integer or string" % key)

    if key in (
            'send_hup',
            'shell',
    ):
        if not isinstance(val, bool):
            raise MessageError("%r isn't a valid boolean" % key)

    if key in ('env', ):
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid object" % key)

        for k, v in val.items():
            if not isinstance(v, string_types):
                raise MessageError("%r isn't a string" % k)

    if key in ('stderr_stream', 'stdout_stream'):
        for k, v in val.items():
            if not k in ('class', 'filename', 'refresh_time'):
                raise MessageError("%r is an invalid option for %r" % \
                        (k, key))
Exemple #7
0
    def validate(self, props):
        super(Set, self).validate(props)

        options = props['options']
        if not isinstance(options, dict):
            raise MessageError("'options' property should be an object")

        for key, val in options.items():
            validate_option(key, val)
Exemple #8
0
    def validate(self, props):
        super(AddWatcher, self).validate(props)
        if 'options' in props:
            options = props.get('options')
            if not isinstance(options, dict):
                raise MessageError("'options' property should be an object")

            for key, val in props['options'].items():
                validate_option(key, val)
Exemple #9
0
    def validate(self, props):
        super(Signal, self).validate(props)

        if 'childpid' in props and not 'pid' in props:
            raise ArgumentError('cannot specify childpid without pid')

        try:
            props['signum'] = to_signum(props['signum'])
        except ValueError:
            raise MessageError('signal invalid')
Exemple #10
0
    def validate(self, props):
        super(Kill, self).validate(props)

        if 'pid' in props:
            props['pid'] = int(props['pid'])

        try:
            if 'signum' in props:
                props['signum'] = to_signum(props['signum'])
        except ValueError:
            raise MessageError('signal invalid')
Exemple #11
0
    def validate(self, props):
        super(Signal, self).validate(props)

        signum = props.get('signum')
        if 'statspid' in props and not 'pid' in props:
            raise ArgumentError('cannot specify childpid without pid')
        if 'children' in props and not 'pid' in props:
            raise ArgumentError('cannot specify children without pid')

        if isinstance(signum, int):
            if signum not in (signal.SIGQUIT, signal.SIGHUP, signal.SIGKILL,
                              signal.SIGTERM, signal.SIGTTIN, signal.SIGTTOU,
                              signal.SIGUSR1, signal.SIGUSR2):
                raise MessageError('signal invalid')

        elif isinstance(signum, string_types):
            if signum.lower() in ('quit', 'hup', 'kill', 'term', 'ttin',
                                  'ttou', 'usr1', 'usr2'):
                props['signum'] = getattr(signal, "SIG%s" % signum.upper())
            else:
                raise MessageError('signal invalid')
Exemple #12
0
    def execute(self, arbiter, props):
        watcher = self._get_watcher(arbiter, props.get('name'))

        # get options values. It return an error if one of the asked
        # options isn't found
        options = {}
        for name in props.get('keys', []):
            if name in watcher.optnames:
                options[name] = getattr(watcher, name)
            else:
                raise MessageError("%r option not found" % name)

        return {"options": options}
Exemple #13
0
    def execute(self, arbiter, props):
        wanted = props.get('option')
        if wanted:
            if wanted not in _OPTIONS:
                raise MessageError('%r not an existing option' % wanted)
            options = (wanted,)
        else:
            options = _OPTIONS

        res = {}

        for option in options:
            res[option] = getattr(arbiter, option)

        return {"options": res}
Exemple #14
0
    def validate(self, props):
        super(Signal, self).validate(props)
        if 'pid' in props and not 'process' in props:
            raise MessageError('process ID is missing')

        if props.get('children', False) and not 'process':
            raise MessageError('process ID is missing')

        signum = props.get('signum')

        if isinstance(signum, int):
            if signum not in (signal.SIGQUIT, signal.SIGHUP, signal.SIGKILL,
                              signal.SIGTERM, signal.SIGTTIN, signal.SIGTTOU,
                              signal.SIGUSR1, signal.SIGUSR2):
                raise MessageError('signal invalid')
        elif isinstance(signum, string_types):
            if signum.lower() in ('quit', 'hup', 'kill', 'term', 'ttin',
                                  'ttou', 'usr1', 'usr2'):
                props['signum'] = getattr(signal, "SIG%s" % signum.upper())
            else:
                raise MessageError('signal invalid')

        else:
            raise MessageError('signal invalid')
Exemple #15
0
def validate_option(key, val):
    if key not in ('numprocesses', 'warmup_delay', 'working_dir', 'uid', 'gid',
                   'send_hup', 'shell', 'env', 'cmd', 'flapping_attempts',
                   'flapping_window', 'retry_in', 'max_retry',
                   'graceful_timeout'):
        raise MessageError('unkown key %r' % key)

    if key in (
            'numprocesses',
            'flapping_attempts',
            'max_retry',
    ):
        if not isinstance(val, int):
            raise MessageError("%r isn't an integer" % key)

    if key in (
            'warmup_delay',
            'flapping_window',
            'retry_in',
            'graceful_timeout',
    ):
        if not isinstance(val, (
                int,
                float,
        )):
            raise MessageError("%r isn't a number" % key)

    if key in (
            'uid',
            'gid',
    ):
        if not isinstance(val, int) or not isinstance(val, string_types):
            raise MessageError("%r isn't an integer or string" % key)

    if key in (
            'send_hup',
            'shell',
    ):
        if not isinstance(val, bool):
            raise MessageError("%r isn't a valid boolean" % key)

    if key == "env":
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid object" % key)

        for k, v in val.items():
            if not isinstance(v, string_types):
                raise MessageError("%r isn't a string" % k)
Exemple #16
0
    def execute(self, arbiter, props):
        options = props.get('options', {})

        # check for endpoint_owner uid restriction mode
        # it would be better to use some type of SO_PEERCRED lookup on the ipc
        # socket to get the uid of the client process and restrict on that,
        # but there's no good portable pythonic way of doing that right now
        # inside pyzmq or here. So we'll assume that the administrator has
        # set good rights on the ipc socket to help prevent privilege
        # escalation
        if arbiter.endpoint_owner_mode:
            cmd_uid = options.get('uid', None)
            if cmd_uid != arbiter.endpoint_owner:
                raise MessageError("uid does not match endpoint_owner")
        watcher = arbiter.add_watcher(props['name'], props['cmd'],
                                      args=props.get('args'), **options)
        if props.get('start', False):
            return watcher.start()
Exemple #17
0
    def execute(self, arbiter, props):
        wanted = props.get('option')
        available = ('endpoint', 'pubsub_endpoint', 'check_delay')

        if wanted:
            if wanted not in available:
                raise MessageError('%r not an existing option' % wanted)
            options = (wanted, )
        else:
            options = ('endpoint', 'pubsub_endpoint', 'stats_endpoint',
                       'check_delay')

        res = {}

        for option in options:
            res[option] = getattr(arbiter, option)

        return {"options": res}
Exemple #18
0
def validate_option(key, val):
    valid_keys = ('numprocesses', 'warmup_delay', 'working_dir', 'uid',
                  'gid', 'send_hup', 'stop_signal', 'stop_children',
                  'shell', 'env', 'cmd', 'args', 'copy_env', 'retry_in',
                  'max_retry', 'graceful_timeout', 'stdout_stream',
                  'stderr_stream', 'max_age', 'max_age_variance', 'respawn',
                  'singleton', 'hooks', 'close_child_stdin',
                  'close_child_stdout', 'close_child_stderr', 'use_papa')

    valid_prefixes = ('stdout_stream.', 'stderr_stream.', 'hooks.', 'rlimit_')

    def _valid_prefix():
        for prefix in valid_prefixes:
            if key.startswith('%s' % prefix):
                return True
        return False

    if key not in valid_keys and not _valid_prefix():
        raise MessageError('unknown key %r' % key)

    if key in ('numprocesses', 'max_retry', 'max_age', 'max_age_variance',
               'stop_signal'):
        if not isinstance(val, int):
            raise MessageError("%r isn't an integer" % key)

    elif key in ('warmup_delay', 'retry_in', 'graceful_timeout',):
        if not isinstance(val, (int, float)):
            raise MessageError("%r isn't a number" % key)

    elif key in ('uid', 'gid',):
        if not isinstance(val, int) and not isinstance(val, string_types):
            raise MessageError("%r isn't an integer or string" % key)

    elif key in ('send_hup', 'shell', 'copy_env', 'respawn', 'stop_children',
                 'close_child_stdin', 'close_child_stdout',
                 'close_child_stderr'):
        if not isinstance(val, bool):
            raise MessageError("%r isn't a valid boolean" % key)

    elif key in ('env', ):
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid object" % key)

        for k, v in val.items():
            if not isinstance(v, string_types):
                raise MessageError("%r isn't a string" % k)

    elif key == 'hooks':
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid hook dict" % val)

        for key in val:
            if key not in _HOOKS:
                raise MessageError("Unknown hook %r" % val)

    elif key in ('stderr_stream', 'stdout_stream'):
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid object" % key)
        if 'class' not in val:
            raise MessageError("%r must have a 'class' key" % key)
        if 'refresh_time' in val:
            warnings.warn("'refresh_time' is deprecated and not useful "
                          "anymore for %r" % key)

    elif key.startswith('rlimit_'):
        if resource:
            rlimit_key = key[7:]
            rlimit_int = getattr(
                resource, 'RLIMIT_' + rlimit_key.upper(), None
            )
            if rlimit_int is None:
                raise MessageError("%r isn't a valid rlimit setting" % key)
        else:
            raise MessageError("rlimit options are not supported on this"
                               " platform")

        # note that a null val means RLIM_INFINITY
        if val is not None and not isinstance(val, int):
            raise MessageError("%r rlimit value isn't a valid int" % val)
Exemple #19
0
 def execute(self, arbiter, args):
     raise MessageError("invalid message. use a pub/sub socket")
Exemple #20
0
def validate_option(key, val):
    valid_keys = ('numprocesses', 'warmup_delay', 'working_dir', 'uid',
                  'gid', 'send_hup', 'shell', 'env', 'cmd', 'copy_env',
                  'flapping_attempts', 'flapping_window', 'retry_in',
                  'max_retry', 'graceful_timeout', 'stdout_stream',
                  'stderr_stream', 'max_age', 'max_age_variance', 'respawn',
                  'hooks')

    valid_prefixes = ('stdout_stream', 'stderr_stream')

    def _valid_prefix():
        for prefix in valid_prefixes:
            if key.startswith('%s.' % prefix):
                return True
        return False

    if key not in valid_keys and not _valid_prefix():
        raise MessageError('unknown key %r' % key)

    if key in ('numprocesses', 'flapping_attempts', 'max_retry', 'max_age',
               'max_age_variance'):
        if not isinstance(val, int):
            raise MessageError("%r isn't an integer" % key)

    if key in ('warmup_delay', 'flapping_window', 'retry_in',
               'graceful_timeout',):
        if not isinstance(val, (int, float,)):
            raise MessageError("%r isn't a number" % key)

    if key in ('uid', 'gid',):
        if not isinstance(val, int) and not isinstance(val, string_types):
            raise MessageError("%r isn't an integer or string" % key)

    if key in ('send_hup', 'shell', 'copy_env', 'respawn'):
        if not isinstance(val, bool):
            raise MessageError("%r isn't a valid boolean" % key)

    if key in ('env', ):
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid object" % key)

        for k, v in val.items():
            if not isinstance(v, string_types):
                raise MessageError("%r isn't a string" % k)

    if key == 'hooks':
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid hook dict" % val)

        for key in val:
            if key not in _HOOKS:
                raise MessageError("Unknown hook %r" % val)

    if key in ('stderr_stream', 'stdout_stream'):
        if not isinstance(val, dict):
            raise MessageError("%r isn't a valid object" % key)
        if not 'class' in val:
            raise MessageError("%r must have a 'class' key" % key)
        if 'refresh_time' in val:
            warnings.warn(u"'refresh_time' is deprecated and not useful "
                          u"anymore for %r" % key)
Exemple #21
0
 def _get_watcher(self, arbiter, watcher_name):
     """Get watcher from the arbiter if any."""
     try:
         return arbiter.get_watcher(watcher_name.lower())
     except KeyError:
         raise MessageError("program %s not found" % watcher_name)