def _remove_cleanup_app(self, path): """Stop and remove a cleanup app. """ name = os.path.basename(path) if name.startswith('.'): _LOGGER.warning('Ignore %s', name) return cleaning_link = os.path.join(self.tm_env.cleaning_dir, name) app_path = os.path.join(self.tm_env.cleanup_apps_dir, name) _LOGGER.info('Removing cleanup app %s -> %s', cleaning_link, app_path) if os.path.exists(cleaning_link): _LOGGER.debug('Removing cleanup link %s', cleaning_link) fs.rm_safe(cleaning_link) self._refresh_supervisor() _LOGGER.debug('Waiting on %s not being supervised', app_path) supervisor.ensure_not_supervised(app_path) else: _LOGGER.debug('Cleanup link %s does not exist', cleaning_link) _LOGGER.debug('Removing app directory %s', app_path) fs.rmtree_safe(app_path)
def validate_as_file(encoded_keytabs, basedir): """ validate keytab by given encoded data return keytab files validated """ temp_dir = tempfile.mkdtemp(dir=basedir) try: for encoded in encoded_keytabs: test_file = os.path.join(temp_dir, _NAME) keytabs2.write_keytab( test_file, encoded, ) try: subproc.check_call( ['kt_split', '--dir={}'.format(basedir), test_file]) except subproc.CalledProcessError: raise keytabs2.KeytabLockerError( 'wrong keytab data: {}'.format(encoded)) for kt_file in os.listdir(basedir): full_path = os.path.join(basedir, kt_file) # we ignore temp_dir in basedir if os.path.isdir(full_path): continue yield full_path finally: fs.rmtree_safe(temp_dir)
def put(self, rsrc_id, rsrc_data): """Request creation/update of a resource. :param `str` rsrc_id: Unique identifier for the requested resource. :param `str` rsrc_data: (New) Parameters for the requested resource. """ req_dir = self._req_dirname(rsrc_id) fs.mkdir_safe(req_dir) with io.open(os.path.join(req_dir, REQ_FILE), 'w') as f: if os.name == 'posix': os.fchmod(f.fileno(), 0o644) yaml.dump(rsrc_data, explicit_start=True, explicit_end=True, default_flow_style=False, stream=f) req_uuid_file = os.path.join(req_dir, self._REQ_UID_FILE) try: with io.open(req_uuid_file) as f: svc_req_uuid = f.read().strip() except IOError as err: if err.errno == errno.ENOENT: svc_req_uuid = None else: raise with lc.LogContext(_LOGGER, rsrc_id): if svc_req_uuid is None: try: # New request svc_req_uuid = self._serviceinst.clt_new_request( rsrc_id, req_dir) # Write down the UUID with io.open(req_uuid_file, 'w') as f: f.write(svc_req_uuid) os.fchmod(f.fileno(), 0o644) except OSError: # Error registration failed, delete the request. _LOGGER.exception('Unable to submit request') fs.rmtree_safe(req_dir) else: self._serviceinst.clt_update_request(svc_req_uuid)
def start(self): """Start watchdog.""" _LOGGER.info('Setting up kernel watchdog at %s', self.root) # set up clean base directory fs.rmtree_safe(self.root) fs.mkdir_safe(self.root) fs.mkdir_safe(self.script_directory) fs.mkdir_safe(self.test_directory) # set up configuration config = _JINJA2_ENV.get_template( 'kernel-watchdog-conf' ).render( test_directory=self.test_directory ) with io.open(self.config_file, 'w') as fd: fd.write(config) # set up custom tests for name in self.tests: test_script = os.path.join(self.script_directory, name) # test script with io.open(test_script, 'w') as fd: fd.write(self.tests[name]) os.fchmod(fd.fileno(), 0o755) # custom test custom_test = _JINJA2_ENV.get_template( 'kernel-watchdog-test' ).render( name=name, command=test_script, reboot=self.reboot_script ) with io.open( os.path.join(self.test_directory, name), 'w' ) as fd: fd.write(custom_test) os.fchmod(fd.fileno(), 0o755) _LOGGER.info('Starting up kernel watchdog') subproc.exec_fghack(self.start_command)
def create_supervision_tree(tm_env, container_dir, root_dir, app, cgroups_path): """Creates s6 supervision tree.""" uniq_name = appcfg.app_unique_name(app) ctl_uds = os.path.join(os.sep, 'run', 'tm_ctl') tombstone_ctl_uds = os.path.join(ctl_uds, 'tombstone') sys_dir = os.path.join(container_dir, 'sys') try: old_system_services = [ svc_name for svc_name in os.listdir(sys_dir) if (not svc_name.startswith('.') and os.path.isdir(os.path.join(sys_dir, svc_name))) ] except FileNotFoundError: old_system_services = [] new_system_services = [svc_def.name for svc_def in app.system_services] for svc_name in set(old_system_services) - set(new_system_services): _LOGGER.info('Removing old system service: %s', svc_name) fs.rmtree_safe(os.path.join(sys_dir, svc_name)) sys_scandir = supervisor.create_scan_dir( sys_dir, finish_timeout=6000, wait_cgroups=cgroups_path, ) for svc_def in app.system_services: if svc_def.restart is not None: monitor_policy = { 'limit': svc_def.restart.limit, 'interval': svc_def.restart.interval, 'tombstone': { 'uds': False, 'path': tm_env.services_tombstone_dir, 'id': '{},{}'.format(uniq_name, svc_def.name) } } else: monitor_policy = None supervisor.create_service( sys_scandir, name=svc_def.name, app_run_script=svc_def.command, userid='root', environ_dir=os.path.join(container_dir, _CONTAINER_ENV_DIR), environ={envvar.name: envvar.value for envvar in svc_def.environ}, environment=app.environment, downed=svc_def.downed, trace=None, monitor_policy=monitor_policy) sys_scandir.write() services_dir = os.path.join(container_dir, 'services') services_scandir = supervisor.create_scan_dir(services_dir, finish_timeout=5000) for svc_def in app.services: if svc_def.restart is not None: monitor_policy = { 'limit': svc_def.restart.limit, 'interval': svc_def.restart.interval, 'tombstone': { 'uds': True, 'path': tombstone_ctl_uds, 'id': '{},{}'.format(uniq_name, svc_def.name) } } else: monitor_policy = None if svc_def.trace is not None: trace = { 'instanceid': app.name, 'uniqueid': app.uniqueid, 'service': svc_def.name, 'path': os.path.join(ctl_uds, 'appevents') } else: trace = None logger_template = getattr(svc_def, 'logger', 's6.app-logger.run') _LOGGER.info('Using logger: %s', logger_template) supervisor.create_service( services_scandir, name=svc_def.name, app_run_script=svc_def.command, userid=svc_def.proid, environ_dir='/' + _CONTAINER_ENV_DIR, environ={envvar.name: envvar.value for envvar in svc_def.environ}, environment=app.environment, downed=svc_def.downed, trace=trace if svc_def.trace else None, log_run_script=logger_template, monitor_policy=monitor_policy) services_scandir.write() # Bind the service directory in the container volume fs.mkdir_safe(os.path.join(root_dir, 'services')) fs_linux.mount_bind(root_dir, os.path.join(os.sep, 'services'), source=os.path.join(container_dir, 'services'), recursive=False, read_only=False) # Bind the ctrl directory in the container volume which has all the # unix domain sockets to communicate outside the container to treadmill fs.mkdir_safe(os.path.join(root_dir, 'run', 'tm_ctl')) fs_linux.mount_bind(root_dir, os.path.join(os.sep, 'run', 'tm_ctl'), source=tm_env.ctl_dir, recursive=False, read_only=False)
def _on_created(self, impl, filepath): """Private handler for request creation events. """ # Avoid triggering on changes to the service directory itself. if filepath == self._rsrc_dir: return False req_id = os.path.basename(filepath) # Avoid triggerring on temporary files if req_id[0] == '.': return False req_file = os.path.join(filepath, REQ_FILE) rep_file = os.path.join(filepath, REP_FILE) try: with io.open(req_file) as f: req_data = yaml.load(stream=f) except IOError as err: if (err.errno == errno.ENOENT or err.errno == errno.ENOTDIR): _LOGGER.exception('Removing invalid request: %r', req_id) try: fs.rm_safe(filepath) except OSError as rm_err: if rm_err.errno == errno.EISDIR: fs.rmtree_safe(filepath) else: raise return False raise # TODO: We should also validate the req_id format with lc.LogContext(_LOGGER, req_id, adapter_cls=lc.ContainerAdapter) as log: log.debug('created %r: %r', req_id, req_data) try: # TODO: We should also validate the req_id format utils.validate(req_data, impl.PAYLOAD_SCHEMA) res = impl.on_create_request(req_id, req_data) except exc.InvalidInputError as err: log.error('Invalid request data: %r: %s', req_data, err) res = {'_error': {'input': req_data, 'why': str(err)}} except Exception as err: # pylint: disable=W0703 log.exception('Unable to process request: %r %r:', req_id, req_data) res = {'_error': {'input': req_data, 'why': str(err)}} if res is None: # Request was not actioned return False fs.write_safe( rep_file, lambda f: yaml.dump( res, explicit_start=True, explicit_end=True, default_flow_style=False, stream=f ), mode='w', permission=0o644 ) # Return True if there were no error return not bool(res.get('_error', False))