Beispiel #1
0
def kill_remote_ipcluster(hostname="hpc05",
                          username=None,
                          password=None,
                          env_path=None):
    """Kill your remote ipcluster and cleanup the files.

    This should do the same as the following bash function (recommended:
    add this in your `.bash_profile` / `.bashrc`):
    ```bash
    del() {
        qselect -u $USER | xargs qdel
        rm -f *.hpc05.hpc* ipengine* ipcontroller* pbs_*
        pkill -f hpc05_culler 2> /dev/null
        pkill -f ipcluster 2> /dev/null
        pkill -f ipengine 2> /dev/null
        pkill -f ipyparallel.controller 2> /dev/null
        pkill -f ipyparallel.engines 2> /dev/null
    }
    ```
    """
    if env_path is None:
        env_path = ""
        python_exec = "python"
    else:
        python_exec = os.path.join(env_path, "bin", "python")

    with setup_ssh(hostname, username, password) as ssh:
        cmd = f"import hpc05; hpc05.connect.kill_ipcluster()"
        cmd = f'{python_exec} -c "{cmd}"'
        stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
        with suppress(Exception):
            lines = stdout.readlines()
            for line in lines:
                print(line)
Beispiel #2
0
def get_remote_env(env=None):
    # XXX: improve this function and pass all argmuments!
    with setup_ssh() as ssh:
        cmd = "conda list --export"
        if env:
            cmd += f" -n {env}"
        stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
        remote_env = [
            l[:-1].rstrip("\r") for l in stdout.readlines()
            if not l.startswith("# ")
        ]
    return remote_env
Beispiel #3
0
def start_remote_ipcluster(
    n,
    profile="pbs",
    hostname="hpc05",
    username=None,
    password=None,
    env_path=None,
    timeout=300,
):
    """Starts an `ipcluster` over ssh on `hostname` and wait untill it's
    successfully started.

    Parameters
    ----------
    n : int
        Number of engines to be started.
    profile : str, default 'pbs'
        Profile name of IPython profile.
    hostname : str
        Hostname of machine where the ipcluster runs.
    username : str
        Username to log into `hostname`. If not provided, it tries to look it up in
        your `.ssh/config`.
    password : str
        Password for `ssh username@hostname`.
    env_path : str, default=None
        Path of the Python environment, '/path/to/ENV/' if Python is in `/path/to/ENV/bin/python`.
        Examples '~/miniconda3/envs/dev/', 'miniconda3/envs/dev', '~/miniconda3'.
        Defaults to the environment that is sourced in `.bashrc` or `.bash_profile`.
    timeout : int
        Time for which we try to connect to get all the engines.

    Returns
    -------
    None
    """
    if env_path is None:
        env_path = ""
        python_exec = "python"
    else:
        python_exec = os.path.join(env_path, "bin", "python")

    with setup_ssh(hostname, username, password) as ssh:
        cmd = f"import hpc05; hpc05.start_ipcluster({n}, '{profile}', '{env_path}', {timeout})"
        cmd = f'{python_exec} -c "{cmd}"'
        stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
        wait_for_succesful_start(stdout, timeout=timeout)
Beispiel #4
0
def _create_remote_profile(
    hostname="hpc05",
    username=None,
    password=None,
    profile="pbs",
    local_controller=False,
    custom_template=None,
    batch_type="pbs",
):
    assert batch_type in ("pbs", "slurm")
    if custom_template is not None:
        raise NotImplementedError(
            f"Use `create_local_{batch_type}_profile` on the"
            " cluster locally or implement this function.")
    with setup_ssh(hostname, username, password) as ssh:
        cmd = f'import hpc05; hpc05.create_local_{batch_type}_profile("{profile}", {local_controller})'
        cmd = f"python -c '{cmd}'"
        stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
        out, err = stdout.readlines(), stderr.readlines()

        for lines in [out, err]:
            for line in lines:
                print(line.rstrip("\n"))
Beispiel #5
0
    def __init__(
        self,
        profile="pbs",
        hostname="hpc05",
        username=None,
        password=None,
        culler=True,
        culler_args=None,
        env_path=None,
        local=False,
        *args,
        **kwargs,
    ):
        culler_cmd = get_culler_cmd(profile, env_path, culler_args=culler_args)

        if local or on_hostname(hostname):
            # Don't connect over ssh if this is run on hostname.
            if culler:
                subprocess.Popen(
                    culler_cmd,
                    shell=True,
                    stdout=open("/dev/null", "w"),
                    stderr=open("logfile.log", "a"),
                )
            super().__init__(profile=profile, *args, **kwargs)
        else:
            import pexpect

            json_file, self.json_filename = tempfile.mkstemp(
            )  # Create temporary file
            os.close(json_file)

            # Try to get the json 10 times.
            remote_json = (
                fr".ipython/profile_{profile}/security/ipcontroller-client.json"
            )
            print_same_line(f"Trying to copy over {remote_json}.")
            for i in range(10):
                print_same_line(
                    f"Trying to copy over {remote_json}. Attempt: {i}/10.")
                with setup_ssh(hostname, username, password) as ssh:
                    with suppress(FileNotFoundError), ssh.open_sftp() as sftp:
                        sftp.chdir(os.path.dirname(remote_json))
                        sftp.get(os.path.basename(remote_json),
                                 self.json_filename)
                        break
                if i == 9:
                    raise FileNotFoundError(
                        f'Could not copy the json file: "{remote_json}" of the pbs '
                        "cluster. This could have several reasons, most likely it is "
                        "because the `ipcluster` probably is not running or "
                        "you have no `profile_pbs`, create with "
                        "`hpc05.profile.create_remote_pbs_profile()`.")
                time.sleep(1)
            print_same_line(f"Copied over {remote_json} in {i+1} attempt.",
                            new_line_end=True)

            # Read the json file
            with open(self.json_filename) as json_file:
                json_data = json.load(json_file)

            keys = ("control", "iopub", "mux", "notification", "registration",
                    "task")

            local_json_data = json_data.copy()
            local_json_data["location"] = "localhost"

            # Select six random ports for the local machine
            local_ports = zmq.ssh.tunnel.select_random_ports(6)
            for port, key in zip(local_ports, keys):
                local_json_data[key] = port

            # Replace remote ports by local ports
            with open(self.json_filename, "w") as json_file:
                json.dump(local_json_data, json_file)

            ips = [
                "{}:{}:{} ".format(local_json_data[key], json_data["location"],
                                   json_data[key]) for key in keys
            ]
            ssh_forward_cmd = ("ssh -o ConnectTimeout=10 -N -L " +
                               "-L ".join(ips) + hostname)
            self.tunnel = pexpect.spawn(ssh_forward_cmd)
            self.tunnel.expect(
                [pexpect.TIMEOUT, pexpect.EOF, "[Pp]assword", "passphrase"],
                timeout=6)

            if culler:
                # Using `with setup_ssh` here results in the culler not being started.
                ssh = setup_ssh(hostname, username, password)
                ssh.exec_command(culler_cmd, get_pty=True)
            super().__init__(self.json_filename, *args, **kwargs)

        if not on_hostname(hostname):

            def __del__(self):
                if self.tunnel:
                    self.tunnel.close()