def __init__(self, master, config, task_id): # Get the task and make sure its container was launched by the UCR. # Since task's containers are launched by the UCR by default, we want # to allow most tasks to pass through unchecked. The only exception is # when a task has an explicit container specified and it is not of type # "MESOS". Having a type of "MESOS" implies that it was launched by the # UCR -- all other types imply it was not. try: tasks = get_tasks(master, config, query={'task_id': task_id}) except Exception as exception: raise CLIException("Unable to get task with ID {task_id}" " from leading master '{master}': {error}" .format(task_id=task_id, master=master, error=exception)) running_tasks = [t for t in tasks if t["state"] == "TASK_RUNNING"] matching_tasks = [t for t in running_tasks if t["id"] == task_id] if not matching_tasks: raise CLIException("Unable to find running task '{task_id}'" " from leading master '{master}'" .format(task_id=task_id, master=master)) if len(matching_tasks) > 1: raise CLIException("More than one task matching id '{id}'" .format(id=task_id)) task_obj = matching_tasks[0] if "container" in task_obj: if "type" in task_obj["container"]: if task_obj["container"]["type"] != "MESOS": raise CLIException( "This command is only supported for tasks" " launched by the Universal Container Runtime (UCR).") # Get the scheme of the agent scheme = "https://" if config.agent_ssl() else "http://" # Get the URL to the agent running the task. agent_addr = util.sanitize_address( scheme + get_agent_address(task_obj["slave_id"], master, config)) self.agent_url = mesos.http.simple_urljoin(agent_addr, "api/v1") # Get the agent's task path by checking the `state` endpoint. try: self.container_id = get_container_id(task_obj) except CLIException as exception: raise CLIException("Could not get container ID of task '{id}'" " from agent '{addr}': {error}" .format(id=task_id, addr=agent_addr, error=exception)) # Set up a recordio encoder and decoder # for any incoming and outgoing messages. self.encoder = recordio.Encoder( lambda s: bytes(json.dumps(s, ensure_ascii=False), "UTF-8")) self.decoder = recordio.Decoder( lambda s: json.loads(s.decode("UTF-8"))) # Set up queues to send messages between threads used for # reading/writing to STDIN/STDOUT/STDERR and threads # sending/receiving data over the network. self.input_queue = Queue() self.output_queue = Queue() # Set up an event to block attaching # input until attaching output is complete. self.attach_input_event = threading.Event() self.attach_input_event.clear() # Set up an event to block printing the output # until an attach input event has successfully # been established. self.print_output_event = threading.Event() self.print_output_event.clear() # Set up an event to block the main thread # from exiting until signaled to do so. self.exit_event = threading.Event() self.exit_event.clear() # Use a class variable to store exceptions thrown on # other threads and raise them on the main thread before # exiting. self.exception = None # Default values for the TaskIO. self.cmd = None self.args = None self.interactive = False self.tty = False self.output_thread_entry_point = None self.config = config # Allow an exit sequence to be used to break the CLIs attachment to # the remote task. Depending on the call, this may be disabled, or # the exit sequence to be used may be overwritten. self.supports_exit_sequence = False self.exit_sequence = b'\x10\x11' # Ctrl-p, Ctrl-q self.exit_sequence_detected = False
def __init__(self, master, task_id): # Get the task and make sure its container was launched by the UCR. # Since task's containers are launched by the UCR by default, we want # to allow most tasks to pass through unchecked. The only exception is # when a task has an explicit container specified and it is not of type # "MESOS". Having a type of "MESOS" implies that it was launched by the # UCR -- all other types imply it was not. try: tasks = get_tasks(master) except Exception as exception: raise CLIException("Unable to get tasks from leading" " master '{master}': {error}" .format(master=master, error=exception)) running_tasks = [t for t in tasks if t["state"] == "TASK_RUNNING"] matching_tasks = [t for t in running_tasks if t["id"] == task_id] if not matching_tasks: raise CLIException("Unable to find running task '{task_id}'" " from leading master '{master}'" .format(task_id=task_id, master=master)) if len(matching_tasks) > 1: raise CLIException("More than one task matching id '{id}'" .format(id=task_id)) task_obj = matching_tasks[0] if "container" in task_obj: if "type" in task_obj["container"]: if task_obj["container"]["type"] != "MESOS": raise CLIException( "This command is only supported for tasks" " launched by the Universal Container Runtime (UCR).") # Get the URL to the agent running the task. agent_addr = util.sanitize_address( get_agent_address(task_obj["slave_id"], master)) self.agent_url = mesos.http.simple_urljoin(agent_addr, "api/v1") # Get the agent's task path by checking the `state` endpoint. try: self.container_id = get_container_id(task_obj) except CLIException as exception: raise CLIException("Could not get container ID of task '{id}'" " from agent '{addr}': {error}" .format(id=task_id, addr=agent_addr, error=exception)) # Set up a recordio encoder and decoder # for any incoming and outgoing messages. self.encoder = recordio.Encoder( lambda s: bytes(json.dumps(s, ensure_ascii=False), "UTF-8")) self.decoder = recordio.Decoder( lambda s: json.loads(s.decode("UTF-8"))) # Set up queues to send messages between threads used for # reading/writing to STDIN/STDOUT/STDERR and threads # sending/receiving data over the network. self.input_queue = Queue() self.output_queue = Queue() # Set up an event to block attaching # input until attaching output is complete. self.attach_input_event = threading.Event() self.attach_input_event.clear() # Set up an event to block printing the output # until an attach input event has successfully # been established. self.print_output_event = threading.Event() self.print_output_event.clear() # Set up an event to block the main thread # from exiting until signaled to do so. self.exit_event = threading.Event() self.exit_event.clear() # Use a class variable to store exceptions thrown on # other threads and raise them on the main thread before # exiting. self.exception = None # Default values for the TaskIO. self.cmd = None self.args = None self.interactive = False self.tty = False self.output_thread_entry_point = None # Allow an exit sequence to be used to break the CLIs attachment to # the remote task. Depending on the call, this may be disabled, or # the exit sequence to be used may be overwritten. self.supports_exit_sequence = False self.exit_sequence = b'\x10\x11' # Ctrl-p, Ctrl-q self.exit_sequence_detected = False