예제 #1
0
    def test_create_service_optional(self):
        """Checks optional components of create service.
        """
        pwd.getpwnam.return_value = self.mock_pwrow('test_shell', 'test_home')
        svc_dir = supervisor.create_scan_dir(self.root, 5000)

        supervisor.create_service(svc_dir,
                                  'xx',
                                  'ls -al',
                                  userid='proid1',
                                  monitor_policy={
                                      'limit': 5,
                                      'interval': 60,
                                      'tombstone': {
                                          'uds': True,
                                          'path': '/run/tm_ctl/tombstone',
                                          'id': 'xx'
                                      }
                                  },
                                  environ={'b': 'test2'},
                                  trace={
                                      'instanceid': 'xx',
                                      'uniqueid': 'ID1234',
                                      'service': 'xx',
                                      'path': '/run/tm_ctl/appevents'
                                  })
        service_dir = os.path.join(self.root, 'xx')
        self.assertTrue(os.path.isdir(service_dir))
        data_dir = os.path.join(service_dir, 'data')
        self.assertTrue(os.path.isfile(os.path.join(data_dir, 'app_start')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'run')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'finish')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'env/b')))
예제 #2
0
    def test_create_service(self):
        """Checks various options when creating the service.
        """
        pwd.getpwnam.return_value = self.mock_pwrow('test_shell', 'test_home')

        supervisor.create_service(self.root,
                                  'xx',
                                  'ls -al',
                                  userid='proid1',
                                  downed=True)
        service_dir = os.path.join(self.root, 'xx')
        self.assertTrue(os.path.isdir(service_dir))
        data_dir = os.path.join(service_dir, 'data')
        self.assertTrue(os.path.isfile(os.path.join(data_dir, 'app_start')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'run')))
        self.assertFalse(os.path.isfile(os.path.join(service_dir, 'finish')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'down')))

        # Do not create down file.
        supervisor.create_service(self.root,
                                  'bar',
                                  'proid1',
                                  'ls -al',
                                  downed=False)
        service_dir = os.path.join(self.root, 'bar')
        self.assertFalse(os.path.exists(os.path.join(service_dir, 'down')))
예제 #3
0
def _configure_locker(tkt_spool_dir, scandir, cell, celluser):
    """Configure ticket forwarding service."""
    if os.path.exists(os.path.join(scandir, cell)):
        return

    _LOGGER.info('Configuring ticket locker: %s/%s', scandir, cell)
    name = cell
    realms = krb5.get_host_realm(sysinfo.hostname())
    krb5ccname = 'FILE:{tkt_spool_dir}/{celluser}@{realm}'.format(
        tkt_spool_dir=tkt_spool_dir,
        celluser=celluser,
        realm=realms[0],
    )
    supervisor.create_service(
        scandir,
        name=name,
        app_run_script=(
            '{treadmill}/bin/treadmill sproc '
            'tickets locker --tkt-spool-dir {tkt_spool_dir}'.format(
                treadmill=subproc.resolve('treadmill'),
                tkt_spool_dir=tkt_spool_dir)),
        userid='root',
        environ_dir=os.path.join(scandir, name, 'env'),
        environ={
            'KRB5CCNAME': krb5ccname,
            'TREADMILL_CELL': cell,
        },
        downed=False,
        trace=None,
        monitor_policy=None)
예제 #4
0
    def _add_cleanup_app(self, path):
        """Configure a new 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)
        if os.path.islink(cleaning_link):
            _LOGGER.warning('Cleaning app already configured %s', name)
            return

        cleanup_link = os.path.join(self.tm_env.cleanup_dir, name)
        if not os.path.islink(cleanup_link):
            _LOGGER.info('Ignore - not a link: %s', cleanup_link)
            return

        _LOGGER.info('Configure cleaning app: %s', name)

        bin_name = 'scripts' if os.name == 'nt' else 'bin'
        command = ('{treadmill}/{bin}/treadmill sproc cleanup instance'
                   ' --approot {tm_root}'
                   ' {instance}').format(
                       treadmill=subproc.resolve('treadmill'),
                       bin=bin_name,
                       tm_root=self.tm_env.root,
                       instance=name)

        if os.name == 'posix':
            command = 'exec ' + command

        supervisor.create_service(
            self.tm_env.cleanup_apps_dir,
            name=name,
            app_run_script=command,
            userid='root',
            monitor_policy={
                'limit': 5,
                'interval': 60,
                'tombstone': {
                    'path': self.tm_env.cleanup_tombstone_dir,
                    'id': name,
                },
                'skip_path': os.path.join(self.tm_env.cleanup_dir, name)
            },
            log_run_script=None,
        )

        fs.symlink_safe(cleaning_link,
                        os.path.join(self.tm_env.cleanup_apps_dir, name))

        _LOGGER.debug('Cleanup app %s ready', name)

        self._refresh_supervisor()
예제 #5
0
    def test_create_service_optional(self):
        """Checks optional components of create service.
        """
        pwd.getpwnam.return_value = self.mock_pwrow('test_shell', 'test_home')
        svc_dir = supervisor.create_scan_dir(self.root, 5000)

        supervisor.create_service(svc_dir,
                                  'xx',
                                  'proid1',
                                  'ls -al',
                                  monitor_policy={'a': 'test1'},
                                  environ={'b': 'test2'},
                                  trace={'c': 'test3'})
        service_dir = os.path.join(self.root, 'xx')
        self.assertTrue(os.path.isdir(service_dir))
        data_dir = os.path.join(service_dir, 'data')
        self.assertTrue(os.path.isfile(os.path.join(data_dir, 'app_start')))
        self.assertTrue(os.path.isfile(os.path.join(data_dir, 'trace')))
        self.assertTrue(os.path.isfile(os.path.join(data_dir, 'policy.json')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'run')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'finish')))
        self.assertTrue(os.path.isfile(os.path.join(service_dir, 'env/b')))
예제 #6
0
    def test_create_service(self):
        """Checks various options when creating the service."""
        supervisor.create_service(self.root,
                                  'proid1',
                                  'proid1_home',
                                  'proid1_shell',
                                  'xx',
                                  'ls -al',
                                  env='dev')
        service_dir = os.path.join(self.root, 'xx')
        self.assertTrue(os.path.isdir(service_dir))
        self.assertTrue(os.path.isfile(service_dir + '/app_start'))
        self.assertTrue(os.path.isfile(service_dir + '/run'))
        self.assertTrue(os.path.isfile(service_dir + '/finish'))
        self.assertTrue(os.path.isfile(service_dir + '/down'))

        # as_root False, proid is None => Use current UID
        supervisor.create_service(self.root,
                                  None,
                                  'home',
                                  'shell',
                                  'bla',
                                  'ls -al',
                                  env='dev',
                                  as_root=False)
        service_dir = os.path.join(self.root, 'bla')

        # Do not create down file.
        supervisor.create_service(self.root,
                                  'proid1',
                                  'proid1_home',
                                  'proid1_shell',
                                  'bar',
                                  'ls -al',
                                  env='dev',
                                  down=False)
        service_dir = os.path.join(self.root, 'bar')
        self.assertFalse(os.path.exists(service_dir + '/down'))
예제 #7
0
def create_supervision_tree(container_dir, app):
    """Creates s6 supervision tree."""
    # Disable R0915: Too many statements
    # pylint: disable=R0915
    root_dir = os.path.join(container_dir, 'root')

    # Services and sys directories will be restored when container restarts
    # with data retention on existing volume.
    #
    # Sys directories will be removed. Services directory will stay, which
    # present a danger of accumulating restart counters in finished files.
    #
    # TODO:
    #
    # It is rather arbitrary how restart counts should work when data is
    # restored, but most likely services are "restart always" policy, so it
    # will not affect them.
    services_dir = os.path.join(container_dir, 'services')
    sys_dir = os.path.join(container_dir, 'sys')
    if os.path.exists(sys_dir):
        _LOGGER.info('Deleting existing sys dir: %s', sys_dir)
        shutil.rmtree(sys_dir)

    app_json = os.path.join(root_dir, 'app.json')

    # Create /services directory for the supervisor
    svcdir = os.path.join(root_dir, 'services')
    fs.mkdir_safe(svcdir)

    fs.mkdir_safe(services_dir)
    fs.mount_bind(root_dir, '/services', services_dir)

    root_pw = pwd.getpwnam('root')
    proid_pw = pwd.getpwnam(app.proid)

    # Create .s6-svscan directories for svscan finish
    sys_svscandir = os.path.join(sys_dir, '.s6-svscan')
    fs.mkdir_safe(sys_svscandir)

    svc_svscandir = os.path.join(services_dir, '.s6-svscan')
    fs.mkdir_safe(svc_svscandir)

    # svscan finish scripts to wait on all services
    utils.create_script(os.path.join(sys_svscandir, 'finish'),
                        'svscan.finish',
                        timeout=6000)

    utils.create_script(os.path.join(svc_svscandir, 'finish'),
                        'svscan.finish',
                        timeout=5000)

    for svc in app.services:
        if getattr(svc, 'root', False):
            svc_user = '******'
            svc_home = root_pw.pw_dir
            svc_shell = root_pw.pw_shell
        else:
            svc_user = app.proid
            svc_home = proid_pw.pw_dir
            svc_shell = proid_pw.pw_shell

        supervisor.create_service(
            services_dir,
            svc_user,
            svc_home,
            svc_shell,
            svc.name,
            svc.command,
            env=app.environment,
            down=True,
            envdirs=['/environ/app', '/environ/sys'],
            as_root=True,
        )
        _create_logrun(os.path.join(services_dir, svc.name))

    for svc in app.system_services:
        supervisor.create_service(
            services_dir,
            'root',
            root_pw.pw_dir,
            root_pw.pw_shell,
            svc.name,
            svc.command,
            env=app.environment,
            down=False,
            envdirs=['/environ/sys'],
            as_root=True,
        )
        _create_logrun(os.path.join(services_dir, svc.name))

    # Vring services
    for cell in app.vring.cells:
        fs.mkdir_safe(os.path.join(sys_dir, 'vring.%s' % cell))
        cmd = '%s sproc --zookeeper - --cell %s vring %s' % (
            treadmill.TREADMILL_BIN, cell, app_json)
        utils.create_script(os.path.join(sys_dir, 'vring.%s' % cell, 'run'),
                            'supervisor.run_sys',
                            cmd=cmd)
        _create_logrun(os.path.join(sys_dir, 'vring.%s' % cell))

    # Create endpoint presence service
    presence_monitor_cmd = '%s sproc presence monitor %s %s' % (
        treadmill.TREADMILL_BIN, app_json, container_dir)
    presence_register_cmd = '%s sproc presence register %s %s' % (
        treadmill.TREADMILL_BIN, app_json, container_dir)
    shadow_etc = os.path.join(container_dir, 'overlay', 'etc')
    host_aliases_cmd = '%s sproc host-aliases --aliases-dir %s %s %s' % (
        treadmill.TREADMILL_BIN,
        os.path.join(shadow_etc, 'host-aliases'),
        os.path.join(shadow_etc, 'hosts.original'),
        os.path.join(shadow_etc, 'hosts'),
    )

    _create_sysrun(sys_dir, 'monitor', presence_monitor_cmd)
    _create_sysrun(sys_dir, 'register', presence_register_cmd)
    _create_sysrun(sys_dir, 'hostaliases', host_aliases_cmd)

    cmd = None
    args = None

    if hasattr(app, 'command'):
        cmd = app.command

    if hasattr(app, 'args'):
        args = app.args

    if not cmd:
        cmd = subproc.resolve('s6_svscan')
        if not args:
            args = ['/services']

    _create_sysrun(sys_dir,
                   'start_container',
                   '%s %s %s -m -p -i %s %s' %
                   (subproc.resolve('chroot'), root_dir,
                    subproc.resolve('pid1'), cmd, ' '.join(args)),
                   down=True)
예제 #8
0
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)
예제 #9
0
def _install_services(scan_dir, package, src_dir, dst_dir, params, prefix_len,
                      rec=None):
    """Expand services in scan directory and install.
    """
    package_name = package.__name__
    contents = pkg_resources.resource_listdir(package_name, src_dir)

    for item in contents:
        if item in (_CONTROL_DIR_NAME, _CONTROL_DIR_FILE):
            continue

        resource_path = os.path.join(src_dir, item)
        if pkg_resources.resource_isdir(package_name,
                                        os.path.join(src_dir, item)):
            dst_path = os.path.join(dst_dir, resource_path[prefix_len:])

            fs.mkdir_safe(dst_path)
            if rec:
                rec.write('%s\n' % os.path.join(dst_path, ''))

            _install(
                package,
                os.path.join(src_dir, item),
                dst_dir,
                params,
                prefix_len=prefix_len,
                rec=rec
            )
        elif resource_path.endswith('.yml'):
            dst_path = os.path.join(dst_dir, resource_path[prefix_len:-4])
            name = os.path.basename(dst_path)

            _LOGGER.info('Expand service (%s): %s => %s', name, resource_path,
                         dst_path)

            fs.mkdir_safe(dst_path)
            if rec:
                rec.write('%s\n' % os.path.join(dst_path, ''))

            service_conf_file = pkg_resources.resource_string(
                package_name,
                resource_path
            )

            if not service_conf_file:
                _LOGGER.warning('Service def was empty: %s', resource_path)
                continue

            service_conf = yaml.load(service_conf_file.decode('utf8'))
            service_conf = bootstrap.interpolate_service_conf(
                resource_path, service_conf, name, params)

            svc = supervisor.create_service(
                scan_dir,
                service_conf['name'],
                service_conf['command'],
                userid=service_conf['userid'],
                downed=service_conf['downed'],
                environ_dir=service_conf['environ_dir'],
                environ=service_conf['environ'],
                monitor_policy=service_conf['monitor_policy'],
                notification_fd=service_conf['notification_fd'],
                call_before_run=service_conf['call_before_run'],
                call_before_finish=service_conf['call_before_finish'],
                logger_args=service_conf['logger_args'],
                ionice_prio=0,
            )

            for file in service_conf['data_dir']:
                permission = 0o644
                if file['executable']:
                    permission = 0o755
                fs.write_safe(
                    os.path.join(svc.data_dir, file['path']),
                    lambda f, file=file: f.write(
                        file['content']
                    ),
                    mode='w',
                    permission=permission
                )
예제 #10
0
def configure(tm_env, event, runtime):
    """Creates directory necessary for starting the application.

    This operation is idem-potent (it can be repeated).

    The directory layout is::

        - (treadmill root)/
          - apps/
            - (app unique name)/
              - data/
                - app_start
                - app.json
                - manifest.yml
                env/
                - TREADMILL_*
                run
                finish
                log/
                - run

    The 'run' script is responsible for creating container environment
    and starting the container.

    The 'finish' script is invoked when container terminates and will
    deallocate any resources (NAT rules, etc) that were allocated for the
    container.
    """
    # Load the app from the event
    try:
        manifest_data = load_runtime_manifest(tm_env, event, runtime)
    except IOError:
        # File is gone. Nothing to do.
        _LOGGER.exception('No event to load: %r', event)
        return None

    # Freeze the app data into a namedtuple object
    app = utils.to_obj(manifest_data)

    # Generate a unique name for the app
    uniq_name = appcfg.app_unique_name(app)

    # Write the actual container start script
    if os.name == 'nt':
        run_script = '{treadmill}/scripts/treadmill sproc run .'.format(
            treadmill=subproc.resolve('treadmill'),
        )
    else:
        run_script = 'exec {treadmill}/bin/treadmill sproc run ../'.format(
            treadmill=subproc.resolve('treadmill'),
        )

    # Create the service for that container
    container_svc = supervisor.create_service(
        tm_env.apps_dir,
        name=uniq_name,
        app_run_script=run_script,
        userid='root',
        downed=False,
        monitor_policy={
            'limit': 0,
            'interval': 60,
            'tombstone': {
                'uds': False,
                'path': tm_env.running_tombstone_dir,
                'id': app.name
            }
        },
        environ={},
        environment=app.environment
    )
    data_dir = container_svc.data_dir

    # Copy the original event as 'manifest.yml' in the container dir
    try:
        shutil.copyfile(
            event,
            os.path.join(data_dir, 'manifest.yml')
        )
    except IOError as err:
        # File is gone, cleanup.
        if err.errno == errno.ENOENT:
            shutil.rmtree(container_svc.directory)
            _LOGGER.exception('Event gone: %r', event)
            return None
        else:
            raise

    # Store the app.json in the container directory
    fs.write_safe(
        os.path.join(data_dir, appcfg.APP_JSON),
        lambda f: f.writelines(
            utils.json_genencode(manifest_data)
        ),
        mode='w',
        permission=0o644
    )

    appevents.post(
        tm_env.app_events_dir,
        events.ConfiguredTraceEvent(
            instanceid=app.name,
            uniqueid=app.uniqueid
        )
    )

    return container_svc.directory
예제 #11
0
    def _add_cleanup_app(self, path):
        """Configure a new 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)
        if os.path.islink(cleaning_link):
            _LOGGER.warning('Cleaning app already configured %s', name)
            return

        cleanup_link = os.path.join(self.tm_env.cleanup_dir, name)
        if not os.path.islink(cleanup_link):
            _LOGGER.info('Ignore - not a link: %s', cleanup_link)
            return

        _LOGGER.info('Configure cleaning app: %s', name)

        if os.name == 'posix':
            command = (
                'exec {tm} sproc cleanup instance'
                ' --approot {tm_root}'
                ' {instance}'
            ).format(
                tm=dist.TREADMILL_BIN,
                tm_root=self.tm_env.root,
                instance=name
            )
        else:
            command = (
                '{python} -m treadmill.ms sproc cleanup instance'
                ' --approot {tm_root}'
                ' {instance}'
            ).format(
                python=sys.executable,
                tm_root=self.tm_env.root,
                instance=name
            )

        supervisor.create_service(
            self.tm_env.cleanup_apps_dir,
            name=name,
            app_run_script=command,
            userid='root',
            monitor_policy={
                'limit': 5,
                'interval': 60,
            },
            log_run_script=None,
        )

        fs.symlink_safe(
            cleaning_link,
            os.path.join(self.tm_env.cleanup_apps_dir, name)
        )

        _LOGGER.debug('Cleanup app %s ready', name)

        self._refresh_supervisor()
예제 #12
0
def create_supervision_tree(container_dir, root_dir, app, cgroups_path):
    """Creates s6 supervision tree."""
    sys_dir = os.path.join(container_dir, 'sys')
    sys_scandir = supervisor.create_scan_dir(
        sys_dir,
        finish_timeout=6000,
        monitor_service='monitor',
        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,
            }
        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)

    trace = {'instanceid': app.name, 'uniqueid': app.uniqueid}
    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,
            }
        else:
            monitor_policy = None

        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=False,
            trace=trace if svc_def.trace else None,
            log_run_script='s6.app-logger.run',
            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)
예제 #13
0
def configure(tm_env, event, runtime):
    """Creates directory necessary for starting the application.

    This operation is idem-potent (it can be repeated).

    The directory layout is::

        - (treadmill root)/
          - apps/
            - (app unique name)/
              - data/
                - app_start
                - app.json
                - manifest.yml
                - policy.json
                env/
                - TREADMILL_*
                run
                finish
                log/
                - run

    The 'run' script is responsible for creating container environment
    and starting the container.

    The 'finish' script is invoked when container terminates and will
    deallocate any resources (NAT rules, etc) that were allocated for the
    container.
    """
    # Load the app from the event
    try:
        manifest_data = app_manifest.load(tm_env, event, runtime)
    except IOError:
        # File is gone. Nothing to do.
        _LOGGER.exception('No event to load: %r', event)
        return

    # Freeze the app data into a namedtuple object
    app = utils.to_obj(manifest_data)

    # Generate a unique name for the app
    uniq_name = appcfg.app_unique_name(app)

    # Write the actual container start script
    if os.name == 'nt':
        run_script = ' '.join(
            [sys.executable, '-m', 'treadmill.ms', 'sproc', 'run', '.'])
    else:
        run_script = ' '.join(
            ['exec', dist.TREADMILL_BIN, 'sproc', 'run', '../'])

    # Create the service for that container
    container_svc = supervisor.create_service(tm_env.apps_dir,
                                              name=uniq_name,
                                              app_run_script=run_script,
                                              userid='root',
                                              downed=False,
                                              monitor_policy={
                                                  'limit': 0,
                                                  'interval': 60
                                              },
                                              environ={},
                                              environment=app.environment)
    data_dir = container_svc.data_dir

    # Copy the original event as 'manifest.yml' in the container dir
    shutil.copyfile(event, os.path.join(data_dir, 'manifest.yml'))

    # Store the app.json in the container directory
    fs.write_safe(os.path.join(data_dir, appcfg.APP_JSON),
                  lambda f: f.writelines(utils.json_genencode(manifest_data)),
                  mode='w',
                  permission=0o644)

    appevents.post(
        tm_env.app_events_dir,
        events.ConfiguredTraceEvent(instanceid=app.name,
                                    uniqueid=app.uniqueid))

    return container_svc.directory