def execute(self, data): """Put the container into the down state which will trigger cleanup. """ _LOGGER.critical('Container down: %r', data) unique_name, service_name = data['id'].split(',') container_dir = os.path.join(self._tm_env.apps_dir, unique_name) container_svc = supervisor.open_service(container_dir) data_dir = container_svc.data_dir exitinfo_file = os.path.join(os.path.join(data_dir, EXIT_INFO)) try: with io.open(exitinfo_file, 'x') as f: _LOGGER.info('Creating exitinfo file: %s', exitinfo_file) if os.name == 'posix': os.fchmod(f.fileno(), 0o644) f.writelines( utils.json_genencode({ 'service': service_name, 'return_code': data['return_code'], 'signal': data['signal'], 'timestamp': data['timestamp'] })) except FileExistsError as err: _LOGGER.info('exitinfo file already exists: %s', exitinfo_file) try: supervisor.control_service(container_svc.directory, supervisor.ServiceControlAction.down) except subproc.CalledProcessError as err: _LOGGER.warning('Failed to bring down container: %s', unique_name) return True
def _add_service(self, new_service_dir): # Add the new service try: service = supervisor.open_service(new_service_dir) except (ValueError, IOError): _LOGGER.exception('Unable to read service directory %r', new_service_dir) return policy = self._policy_impl() new_watch = policy.register(service) if new_watch is None: _LOGGER.info('Service %r is not configured for monitoring', service) return # Add the new service directory to the policy watcher try: self._dirwatcher.add_dir(new_watch) except OSError: _LOGGER.exception('Unable to add dir to watcher %r', new_watch) return self._service_policies[new_watch] = policy # Immediately ensure we start within policy. self._process(policy)
def execute(self, data): """Pass a container to the cleanup service. """ _LOGGER.critical('Monitor container cleanup: %r', data) running = os.path.join(self._tm_env.running_dir, data['id']) data_dir = supervisor.open_service(running, existing=False).data_dir cleanup = os.path.join(self._tm_env.cleanup_dir, data['id']) # pid1 will SIGABRT(6) when there is an issue if int(data['signal']) == 6: app_abort.flag_aborted(data_dir, why=app_abort.AbortedReason.PID1) try: _LOGGER.info('Moving %r -> %r', running, cleanup) fs.replace(running, cleanup) except OSError as err: if err.errno == errno.ENOENT: pass else: raise try: supervisor.control_svscan(self._tm_env.running_dir, [ supervisor.SvscanControlAction.alarm, supervisor.SvscanControlAction.nuke ]) except subproc.CalledProcessError as err: _LOGGER.warning('Failed to nuke svscan: %r', self._tm_env.running_dir) return True
def execute(self, data): """Put the container into the down state which will trigger cleanup. """ unique_name, service_name = data['id'].split(',') container_dir = os.path.join(self._tm_env.apps_dir, unique_name) container_svc = supervisor.open_service(container_dir) _LOGGER.critical('Container down: %r', data) data_dir = container_svc.data_dir fs.write_safe( os.path.join(data_dir, EXIT_INFO), lambda f: f.writelines( utils.json_genencode({ 'service': service_name, 'return_code': data['return_code'], 'signal': data['signal'], 'timestamp': data['timestamp'] })), mode='w', prefix='.tmp', permission=0o644) try: supervisor.control_service(container_svc.directory, supervisor.ServiceControlAction.down) except subproc.CalledProcessError as err: _LOGGER.warning('Failed to bring down container: %r', unique_name) return True
def _add_service(self, new_service_dir): # Add the new service try: service = supervisor.open_service(new_service_dir) except (ValueError, IOError): _LOGGER.exception('Unable to read service directory %r', new_service_dir) return policy = self._policy_impl() new_watch = policy.register(service) self._service_policies[new_watch] = policy # Add the new service directory to the policy watcher self._dirwatcher.add_dir(new_watch) # Immediately ensure we start within policy. if not policy.process(): self._down_reason = policy.fail_reason
def run(approot, runtime, container_dir, runtime_param=None): """Runs container given a container dir.""" # Make sure container_dir is a fully resolved path. container_dir = os.path.realpath(container_dir) service = supervisor.open_service(container_dir) _LOGGER.info('run %r %r', approot, container_dir) tm_env = appenv.AppEnvironment(approot) param = utils.equals_list2dict(runtime_param or []) try: app_runtime.get_runtime( runtime, tm_env, service, param ).run() except exc.ContainerSetupError as err: _LOGGER.exception('Failed to start, app will be aborted.') app_abort.flag_aborted(service.data_dir, why=err.reason, payload=traceback.format_exc()) except Exception as err: # pylint: disable=W0703 _LOGGER.exception('Failed to start, app will be aborted.') app_abort.flag_aborted(service.data_dir, why=app_abort.AbortedReason.UNKNOWN, payload=traceback.format_exc())
def __init__(self, tm_env, container_dir, param=None): self._tm_env = tm_env self._param = {} if param is None else param self._service = supervisor.open_service(container_dir)
def add_linux_system_services(tm_env, manifest): """Configure linux system services.""" unique_name = appcfg.manifest_unique_name(manifest) container_svcdir = supervisor.open_service(os.path.join( tm_env.apps_dir, unique_name), existing=False) container_data_dir = container_svcdir.data_dir if 'vring' in manifest: # Add the Vring daemon services for cell in manifest['vring']['cells']: vring = { 'name': 'vring.%s' % cell, 'proid': 'root', 'restart': { 'limit': 5, 'interval': 60, }, 'command': ('exec {treadmill}/bin/treadmill sproc' ' --zookeeper {zkurl}' ' --cell {cell}' ' vring' ' --approot {tm_root}' ' {manifest}').format(treadmill=subproc.resolve('treadmill'), zkurl=manifest['zookeeper'], cell=cell, tm_root=tm_env.root, manifest=os.path.join( container_data_dir, 'state.json')), 'environ': [ { 'name': 'KRB5CCNAME', 'value': os.path.expandvars('FILE:${TREADMILL_HOST_TICKET}'), }, ], 'config': None, 'downed': False, 'trace': False, } manifest['system_services'].append(vring) # Create ticket refresh and container/endpoint presence service register_presence = { 'name': 'register', 'proid': 'root', 'restart': { 'limit': 5, 'interval': 60, }, 'command': ('exec {treadmill}/bin/treadmill sproc' ' --zookeeper {zkurl}' ' --cell {cell}' ' presence register' ' {manifest} {container_dir}').format( treadmill=subproc.resolve('treadmill'), zkurl=manifest['zookeeper'], cell=manifest['cell'], manifest=os.path.join(container_data_dir, 'state.json'), container_dir=container_data_dir), 'environ': [ { 'name': 'KRB5CCNAME', 'value': os.path.expandvars('FILE:${TREADMILL_HOST_TICKET}'), }, { 'name': 'TREADMILL_ALIASES_PATH', 'value': os.getenv('TREADMILL_ALIASES_PATH'), }, ], 'config': None, 'downed': False, 'trace': False, } manifest['system_services'].append(register_presence) # Create container /etc/hosts manager service run_overlay = os.path.join(container_data_dir, 'overlay', 'run') etc_overlay = os.path.join(container_data_dir, 'overlay', 'etc') hostaliases = { 'name': 'hostaliases', 'proid': 'root', 'restart': { 'limit': 5, 'interval': 60, }, 'command': ('exec {treadmill}/bin/treadmill sproc' ' --cell {cell}' ' host-aliases' ' --aliases-dir {aliases_dir}' ' {hosts_original} {hosts_container}').format( treadmill=subproc.resolve('treadmill'), cell=manifest['cell'], aliases_dir=os.path.join( run_overlay, 'host-aliases', ), hosts_original=os.path.join('/', 'etc', 'hosts'), hosts_container=os.path.join(etc_overlay, 'hosts'), ), 'environ': [], 'downed': False, 'trace': False, } manifest['system_services'].append(hostaliases) # Create the user app top level supervisor # # Reset environment variables set by treadmill to default values. start_container = { 'name': 'start_container', 'proid': 'root', 'restart': { 'limit': 0, 'interval': 60, }, 'command': ('exec' ' {pid1} -i -m -p' ' --propagation slave' ' {treadmill}/bin/treadmill sproc' ' --cgroup /apps/{unique_name}/services' ' --cell {cell}' ' start-container' ' --container-root {container_dir}/root' ' {manifest}').format( treadmill=subproc.resolve('treadmill'), unique_name=unique_name, cell=manifest['cell'], pid1=subproc.resolve('pid1'), container_dir=container_data_dir, manifest=os.path.join(container_data_dir, 'state.json'), ), 'environ': [], 'config': None, 'downed': True, 'trace': False, } manifest['system_services'].append(start_container)
def _add_linux_system_services(tm_env, manifest): """Configure linux system services.""" container_svcdir = supervisor.open_service(os.path.join( tm_env.apps_dir, appcfg.manifest_unique_name(manifest)), existing=False) container_data_dir = container_svcdir.data_dir if 'vring' in manifest: # Add the Vring daemon services for cell in manifest['vring']['cells']: vring = { 'name': 'vring.%s' % cell, 'proid': 'root', 'restart': { 'limit': 5, 'interval': 60, }, 'command': ('exec {tm} sproc' ' --zookeeper {zkurl}' ' --cell {cell}' ' vring' ' --approot {tm_root}' ' {manifest}').format(tm=dist.TREADMILL_BIN, zkurl=manifest['zookeeper'], cell=cell, tm_root=tm_env.root, manifest=os.path.join( container_data_dir, 'state.json')), 'environ': [ { 'name': 'KRB5CCNAME', 'value': os.path.expandvars('FILE:${TREADMILL_HOST_TICKET}'), }, ], 'config': None, 'downed': False, 'trace': False, } manifest['system_services'].append(vring) # Create ticket refresh and container/endpoint presence service register_presence = { 'name': 'register', 'proid': 'root', 'restart': { 'limit': 5, 'interval': 60, }, 'command': ('exec {tm} sproc' ' --zookeeper {zkurl}' ' --cell {cell}' ' presence register' ' --approot {tm_root}' ' {manifest} {container_dir}').format( tm=dist.TREADMILL_BIN, zkurl=manifest['zookeeper'], cell=manifest['cell'], tm_root=tm_env.root, manifest=os.path.join(container_data_dir, 'state.json'), container_dir=container_data_dir), 'environ': [ { 'name': 'KRB5CCNAME', 'value': os.path.expandvars('FILE:${TREADMILL_HOST_TICKET}'), }, { 'name': 'TREADMILL_ALIASES_PATH', 'value': os.getenv('TREADMILL_ALIASES_PATH'), }, ], 'config': None, 'downed': False, 'trace': False, } manifest['system_services'].append(register_presence) # Create container /etc/hosts manager service run_overlay = os.path.join(container_data_dir, 'overlay', 'run') etc_overlay = os.path.join(container_data_dir, 'overlay', 'etc') hostaliases = { 'name': 'hostaliases', 'proid': 'root', 'restart': { 'limit': 5, 'interval': 60, }, 'command': ('exec {tm} sproc' ' --cell {cell}' ' host-aliases' ' --aliases-dir {aliases_dir}' ' {hosts_original} {hosts_container}').format( tm=dist.TREADMILL_BIN, cell=manifest['cell'], aliases_dir=os.path.join( run_overlay, 'host-aliases', ), hosts_original=os.path.join('/', 'etc', 'hosts'), hosts_container=os.path.join(etc_overlay, 'hosts'), ), 'environ': [], 'downed': False, 'trace': False, } manifest['system_services'].append(hostaliases) # Create the user app top level supervisor start_container = { 'name': 'start_container', 'proid': 'root', 'restart': { 'limit': 0, 'interval': 60, }, 'command': ('exec {chroot} {container_dir}/root' ' {pid1} -m -p -i' ' {svscan} -s /services').format( chroot=subproc.resolve('chroot'), container_dir=container_data_dir, pid1=subproc.resolve('pid1'), svscan=subproc.resolve('s6_svscan'), ), 'environ': [], 'config': None, 'downed': True, 'trace': False, } manifest['system_services'].append(start_container) # Create the services monitor service monitor = { 'name': 'monitor', 'proid': 'root', 'restart': None, # Monitor should not be monitored 'command': ('exec {tm} sproc' ' --cell {cell}' ' monitor services' ' --approot {tm_root}' ' -c {container_dir}' ' -s {services_opts}').format( tm=dist.TREADMILL_BIN, cell=manifest['cell'], tm_root=tm_env.root, container_dir=container_svcdir.directory, # This adds all services beside monitor itself services_opts=' -s'.join([ os.path.join(container_data_dir, 'sys', s['name']) for s in manifest['system_services'] ] + [ os.path.join(container_data_dir, 'services', s['name']) for s in manifest['services'] ])), 'environ': [ { 'name': 'KRB5CCNAME', 'value': os.path.expandvars('FILE:${TREADMILL_HOST_TICKET}'), }, { 'name': 'TREADMILL_ALIASES_PATH', 'value': os.getenv('TREADMILL_ALIASES_PATH'), }, ], 'config': None, 'downed': False, 'trace': False, } manifest['system_services'].append(monitor)
def __init__(self, container_dir): self._container_svc = supervisor.open_service(container_dir)