def __init__(self, scan_dirs, service_dirs, policy_impl, down_action, event_hook=None): self._dirwatcher = None self._down_action = down_action self._down_reasons = collections.deque() self._event_hook = event_hook self._policy_impl = policy_impl self._services = list(utils.get_iterable(service_dirs)) self._scan_dirs = set(utils.get_iterable(scan_dirs)) self._service_policies = {}
def control_svscan(scan_dir, actions): """Sends a control signal to a svscan instance.""" action_str = '-' for action in utils.get_iterable(actions): action_str += action.value subproc.check_call([_get_cmd('svscanctl'), action_str, scan_dir])
def control_service(service_dir, actions, wait=None, timeout=0): """Sends a control signal to the supervised process. :returns: ``True`` - Command was successuful. ``False`` - Command timedout (only if `wait` was provided). :raises ``subproc.CalledProcessError``: With `returncode` set to `ERR_NO_SUP` if the service is not supervised. With `returncode` set to `ERR_COMMAND` if there is a problem communicating with the supervisor. """ cmd = [_get_cmd('svc')] if wait: cmd.append('-w' + _get_wait_action(wait).value) if timeout > 0: cmd.extend(['-T{}'.format(timeout)]) action_str = '-' for action in utils.get_iterable(actions): action_str += action.value cmd.append(action_str) cmd.append(service_dir) try: subproc.check_call(cmd) except subproc.CalledProcessError as err: if err.returncode == ERR_TIMEOUT: return False else: raise return True
def _sync(self): """Initial sync of placement.""" self._servers_watch.sync() self._synced = True dn_mapping = {} conn = None for server_info in self._servers_watch.get_all_server_info(): dn_mapping[server_info[servers.DN_KEY]] = server_info if conn is None: conn = self._servers_watch.get_ldap_connection(server_info) if conn is None: _LOGGER.error('No ldap connection information available') return conn.search( search_base=self._config.group_ou, search_filter='(objectclass=group)', attributes=['samAccountName', 'member'] ) if not _check_ldap3_operation(conn): _LOGGER.error('Failed to get groups from AD') return all_proids = {} for entry in conn.response: match = self._config.parse_group_name( entry['attributes']['samAccountName']) if match is None: continue members = set() if 'member' in entry['attributes']: members = set(utils.get_iterable( entry['attributes']['member'])) all_proids[match] = members for proid in all_proids: server_dn_set = set( k for (k, v) in self._get_server_dn_set(proid).items() ) actual_dn_set = all_proids[proid] _LOGGER.debug('Sync proid %s, expected %r - actual %r', proid, server_dn_set, actual_dn_set) diff = server_dn_set.symmetric_difference(actual_dn_set) for dn in diff: if dn not in dn_mapping: continue if dn in server_dn_set: self._add_dn_to_proid_group(conn, dn, proid, force=True) else: self._remove_dn_from_proid_group(conn, dn, proid, force=True)
def wait_service(service_dirs, action, all_services=True, timeout=0): """Performs a wait task on the given list of service directories. """ cmd = [_get_cmd('svwait')] if timeout > 0: cmd.extend(['-t{}'.format(timeout)]) if not all_services: cmd.append('-o') cmd.append('-' + _get_wait_action(action).value) cmd.extend(utils.get_iterable(service_dirs)) subproc.check_call(cmd)
def unmount(target, mnt_flags=()): """Umount ``target``. """ target = target.encode() mnt_flags = utils.get_iterable(mnt_flags) mnt_flags = six.moves.reduce(operator.or_, mnt_flags, 0) _LOGGER.debug('umount(%r, %r)', target, utils.parse_mask(mnt_flags, MNTFlags)) if not mnt_flags: return _umount(target) else: return _umount2(target, mnt_flags)
def mount(source, target, fs_type, *mnt_opts_args, mnt_flags=(), **mnt_opts_kwargs): """Mount ``source`` on ``target`` using filesystem type ``fs_type`` and mount flags ``mnt_flags``. NOTE: Mount data argument is not supported. :params `str` source: What to mount :params `str` target: Where to mount it """ if source is not None: source = source.encode() if target is not None: target = target.encode() else: target = source if fs_type is not None: fs_type = fs_type.encode() # Fix up mount flags mnt_flags = utils.get_iterable(mnt_flags) flags = int(six.moves.reduce(operator.or_, mnt_flags, MS_MGC_VAL)) # Fix up mount options options = ','.join( itertools.chain(mnt_opts_args, ('%s=%s' % (key, value) for (key, value) in six.iteritems(mnt_opts_kwargs)))) if options: options = options.encode() else: options = None _LOGGER.debug('mount(%r, %r, %r, %r, %r)', source, target, fs_type, utils.parse_mask(flags, MSFlags), options) return _mount(source, target, fs_type, flags, options)
def query_spn(self, proid): """ Return list of spn registered for a GMSA On success return a dict: { 'dn': dn, 'spn': [spn] } On failure throw exception """ gmsa_obj = self._get_gmsa_obj(proid) if gmsa_obj: result = {'dn': gmsa_obj['dn'], 'spn': []} if 'servicePrincipalName' in gmsa_obj['attributes']: result['spn'].extend( utils.get_iterable( gmsa_obj['attributes']['servicePrincipalName'])) return result else: raise RuntimeError('GMSA \'{}\' not found'.format(proid))
def control_service(service_dir, actions, wait=None, timeout=0): """Sends a control signal to the supervised process. :returns: ``True`` - Command was successuful. ``False`` - Command timedout (only if `wait` was provided). :raises ``subproc.CalledProcessError``: With `returncode` set to `ERR_NO_SUP` if the service is not supervised. With `returncode` set to `ERR_COMMAND` if there is a problem communicating with the supervisor. """ cmd = [_get_cmd('svc')] # XXX: A bug in s6 2.6.0.0 causes svc command to hang if the service is not # supervised. Disable for now. # This does not happen in winss but we are keeping consitent. # if wait: # cmd.append('-w' + _get_wait_action(wait).value) # if timeout > 0: # cmd.extend(['-T{}'.format(timeout)]) action_str = '-' for action in utils.get_iterable(actions): action_str += action.value cmd.append(action_str) cmd.append(service_dir) try: subproc.check_call(cmd) # XXX: Remove below when above bug is fixed. if wait is not None: wait_service(service_dir, wait, timeout=timeout) except subproc.CalledProcessError as err: if err.returncode == ERR_TIMEOUT: return False else: raise return True
def host_in_proid_group(self, proid): """Checks that the current host is a member of the proid group. """ conn = servers.create_ldap_connection(self._dc) conn.search(search_base=self._config.group_ou, search_filter='(cn={})'.format( self._config.get_group_name(proid)), attributes=['member']) if not _check_ldap3_operation(conn): _LOGGER.error('Failed to get groups from AD') return False entry = conn.response[0] if 'member' in entry['attributes']: for member in utils.get_iterable(entry['attributes']['member']): if member.lower() == self._dn: return True return False
def _interpolate_service_conf(resource_path, service_conf, name, params): """Interpolates the service config. """ params['name'] = name new_service_conf = {'name': name} if 'command' not in service_conf: raise Exception('Service def did not include command: %s' % resource_path) new_service_conf['command'] = _interpolate_scalar( service_conf.get('command'), params) monitor_policy = service_conf.get('monitor_policy', None) if monitor_policy is not None: monitor_policy = _interpolate_dict(monitor_policy, params) if 'tombstone' not in monitor_policy or \ 'path' not in monitor_policy['tombstone']: raise Exception('Service def ombstone path missing: %s' % resource_path) tombstone_path = monitor_policy['tombstone']['path'] tombstone_path = _interpolate_scalar(tombstone_path, params) tombstone_id = monitor_policy['tombstone'].get('id', name) tombstone_id = _interpolate_scalar(tombstone_id, params) new_policy = { 'limit': int(monitor_policy.get('limit', 0)), 'interval': int(monitor_policy.get('interval', 60)), 'tombstone': { 'uds': False, 'path': tombstone_path, 'id': tombstone_id, 'no_exit_info': monitor_policy['tombstone'].get('no_exit_info', False) } } monitor_policy = new_policy new_service_conf['monitor_policy'] = monitor_policy new_service_conf['userid'] = _interpolate_scalar( service_conf.get('user', 'root'), params) new_service_conf['downed'] = service_conf.get('downed', False) new_service_conf['environ_dir'] = _interpolate_scalar( service_conf.get('environ_dir', None), params) new_service_conf['environ'] = _interpolate( service_conf.get('environ', None), params) new_service_conf['notification_fd'] = service_conf.get( 'notification_fd', None) new_service_conf['call_before_run'] = _interpolate( service_conf.get('call_before_run', None), params) new_service_conf['call_before_finish'] = _interpolate( service_conf.get('call_before_finish', None), params) new_service_conf['logger_args'] = service_conf.get('logger_args', None) files = [] data_dir = service_conf.get('data_dir', None) if data_dir is not None: for item in utils.get_iterable(data_dir): if 'path' not in item: continue file = {'path': item['path']} content = '' if 'content' in item: content = _interpolate_scalar(item['content'], params) file['content'] = content file['executable'] = item.get('executable', False) files.append(file) new_service_conf['data_dir'] = files del params['name'] _LOGGER.debug('Service config for %s: %r', name, new_service_conf) return new_service_conf