Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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())
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
 def __init__(self, container_dir):
     self._container_svc = supervisor.open_service(container_dir)