def on_active(self, task_update): log.debug('Task on_active(%s)' % task_update) self._runner._plan = self._runner._regular_plan if self._runner._recovery: return TaskRunnerHelper.initialize_task(self._pathspec, ThermosTaskWrapper(self._runner._task).to_json())
def simplerun(args, options): """Run a simple command line as a thermos task. Usage: thermos simplerun [options] [--] commandline """ try: cutoff = args.index('--') cmdline = ' '.join(args[cutoff + 1:]) except ValueError: cmdline = ' '.join(args) print("Running command: '%s'" % cmdline) thermos_task = ThermosTaskWrapper(Task( name=options.name, resources=Resources(cpu=1.0, ram=256 * 1024 * 1024, disk=0), processes=[Process(name=options.name, cmdline=cmdline)])) really_run(thermos_task, options.root, tempfile.mkdtemp(), task_id=options.task_id, user=options.user, prebound_ports=options.prebound_ports, chroot=False, daemon=options.daemon)
def __init__(self, runner_pex, task_id, task, role, portmap, sandbox, checkpoint_root, artifact_dir=None, clock=time, hostname=None, process_logger_destination=None, process_logger_mode=None, rotate_log_size_mb=None, rotate_log_backups=None, preserve_env=False): """ runner_pex location of the thermos_runner pex that this task runner should use task_id task_id assigned by scheduler task thermos pystachio Task object role role to run the task under portmap { name => port } dictionary sandbox the sandbox object checkpoint_root the checkpoint root for the thermos runner artifact_dir scratch space for the thermos runner (basically cwd of thermos.pex) clock clock preserve_env """ self._runner_pex = runner_pex self._task_id = task_id self._task = task self._popen, self._popen_signal, self._popen_rc = None, None, None self._monitor = None self._status = None self._ports = portmap self._root = sandbox.root self._checkpoint_root = checkpoint_root self._enable_chroot = sandbox.chrooted self._preserve_env = preserve_env self._role = role self._clock = clock self._artifact_dir = artifact_dir or safe_mkdtemp() self._hostname = hostname or socket.gethostname() self._process_logger_destination = process_logger_destination self._process_logger_mode = process_logger_mode self._rotate_log_size_mb = rotate_log_size_mb self._rotate_log_backups = rotate_log_backups # wait events self._dead = threading.Event() self._kill_signal = threading.Event() self.forking = threading.Event() self.forked = threading.Event() try: with open(os.path.join(self._artifact_dir, 'task.json'), 'w') as fp: self._task_filename = fp.name ThermosTaskWrapper(self._task).to_file(self._task_filename) except ThermosTaskWrapper.InvalidTask as e: raise TaskError('Failed to load task: %s' % e)
def __init__(self, runner_pex, task_id, task, role, portmap, sandbox, checkpoint_root=None, artifact_dir=None, clock=time): """ runner_pex location of the thermos_runner pex that this task runner should use task_id task_id assigned by scheduler task thermos pystachio Task object role role to run the task under portmap { name => port } dictionary sandbox the sandbox object checkpoint_root the checkpoint root for the thermos runner artifact_dir scratch space for the thermos runner (basically cwd of thermos.pex) clock clock """ self._runner_pex = runner_pex self._task_id = task_id self._task = task self._popen = None self._monitor = None self._status = None self._ports = portmap self._root = sandbox.root self._checkpoint_root = checkpoint_root or TaskPath.DEFAULT_CHECKPOINT_ROOT self._enable_chroot = sandbox.chrooted self._role = role self._clock = clock self._artifact_dir = artifact_dir or safe_mkdtemp() # wait events self._dead = threading.Event() self._kill_signal = threading.Event() self.forking = threading.Event() self.forked = threading.Event() try: with open(os.path.join(self._artifact_dir, 'task.json'), 'w') as fp: self._task_filename = fp.name ThermosTaskWrapper(self._task).to_file(self._task_filename) except ThermosTaskWrapper.InvalidTask as e: raise TaskError('Failed to load task: %s' % e)
def _read_task(self, memoized={}): """Read the corresponding task from disk and return a ThermosTask. Memoizes already-read tasks. """ if self._task_id not in memoized: path = self._pathspec.given(task_id=self._task_id, state=self.type).getpath('task_path') if os.path.exists(path): task = ThermosTaskWrapper.from_file(path) if task is None: log.error('Error reading ThermosTask from %s in observer.' % path) else: context = self.context(self._task_id) if not context: log.warning('Task not yet available: %s' % self._task_id) task = task.task() % Environment(thermos=context) memoized[self._task_id] = task return memoized.get(self._task_id, None)
def ports(self): """Return the list of ports that need to be allocated by the scheduler.""" # Strictly speaking this is wrong -- it is possible to do things like # {{thermos.ports[instance_{{mesos.instance}}]}} # which can only be extracted post-unwrapping. This means that validating # the state of the announce configuration could be problematic if people # try to do complicated things. referenced_ports = ThermosTaskWrapper(self._job.task(), strict=False).ports() resolved_portmap = PortResolver.resolve(self._job.announce().portmap().get() if self._job.has_announce() else {}) # values of the portmap that are not integers => unallocated unallocated = set(port for port in resolved_portmap.values() if not isinstance(port, int)) # find referenced {{thermos.portmap[ports]}} that are not resolved by the portmap unresolved_references = set( port for port in (resolved_portmap.get(port_ref, port_ref) for port_ref in referenced_ports) if not isinstance(port, int)) return unallocated | unresolved_references
def __init__(self, task, success_rate=100, random_seed=31337, **extra_task_runner_args): """ task = Thermos task portmap = port map success_rate = success rate of writing checkpoint to disk """ self.task = task with temporary_file(cleanup=False) as fp: self.job_filename = fp.name fp.write(ThermosTaskWrapper(task).to_json()) self.state_filename = tempfile.mktemp() self.tempdir = tempfile.mkdtemp() self.task_id = '%s-runner-base' % int(time.time() * 1000000) self.sandbox = os.path.join(self.tempdir, 'sandbox') self.extra_task_runner_args = extra_task_runner_args self.cleaned = False self.pathspec = TaskPath(root=self.tempdir, task_id=self.task_id) self.script_filename = None self.success_rate = success_rate self.random_seed = random_seed self._run_count = 0
def simplerun(args, options): """Run a simple command line as a thermos task. Usage: thermos simplerun [options] [--] commandline Options: --user=USER run as this user. if not $USER, must have setuid privilege. --name=STRING the name to give this task. ('simple' by default) --task_id=STRING the id to which this task should be bound, synthesized from the task name if none provided. -P/--port=NAME:PORT bind the named port NAME to port number PORT (may be specified multiple times to bind multiple names.) -E/--environment=NAME=VALUE bind the configuration environment variable NAME to VALUE. --daemon Fork and daemonize the task. """ try: cutoff = args.index('--') cmdline = ' '.join(args[cutoff + 1:]) except ValueError: cmdline = ' '.join(args) print("Running command: '%s'" % cmdline) thermos_task = ThermosTaskWrapper(Task( name=options.name, resources=Resources(cpu=1.0, ram=256 * 1024 * 1024, disk=0), processes=[Process(name=options.name, cmdline=cmdline)])) _really_run(thermos_task, options.root, None, task_id=options.task_id, user=options.user, prebound_ports=options.prebound_ports, chroot=False, daemon=options.daemon)
def has_health_port(self): return "health" in ThermosTaskWrapper(self._job.task(), strict=False).ports()