Exemple #1
0
def check_config_file(ip_address,file_path=".artemisrc"):
    '''
    Makes sure all required fields are present in ~./artemisrc.
    Also performs test for the different options if applicable
    :param ip_address: The section to look for. Remote ip is assumed. Makes no sense for local ip.
    :return:
    '''
    mandatory_options = ["username","python"]
    artemisrc_path = os.path.expanduser("~/%s"%file_path)
    for option in mandatory_options:
        try:
            get_artemis_config_value(section=ip_address,option=option)
        except NoSectionError:
            print("Section %s could not be found in %s. Please provide it." %(ip_address, artemisrc_path))
            raise
        except NoOptionError:
            print("Section %s does not contain option %s. Please provide it in %s" %(ip_address, option, artemisrc_path))
            raise

    # optional_options = ["private_key"]
    try:
        private_key_path = get_artemis_config_value(section=ip_address,option="private_key")
        assert os.path.isfile(private_key_path), "The path to the private_key for %s you specified in %s is not valid. You provided %s" %(ip_address, artemisrc_path, private_key_path)
    except NoOptionError:
        pass
    # username & private key setup tests:
    try:
        get_ssh_connection(ip_address)
    except paramiko.ssh_exception.AuthenticationException as e:
        if "Authentication failed" in e.message:
            print("An AuthenticationException is being raised. Make sure you have your private key set up correctly")
        else:
            print("An AuthenticationException is being raised. Did you specify the correct username for %s in %s? You provided the username %s"% (ip_address, artemisrc_path, get_artemis_config_value(section=ip_address,option="username")))
        raise
    except paramiko.ssh_exception.SSHException:
        try:
            private_key_path = get_artemis_config_value(section=ip_address,option="private_key")
            print ("Something is wrong with the private_key you specified in %s for %s . You provided %s" % (artemisrc_path, ip_address, private_key_path))
            raise
        except NoOptionError:
            private_key_path = os.path.join(os.path.expanduser("~"),".ssh/id_rsa")
            print("You did not provide a private_key path in %s. The default path %s appears to be wrongly set up. "
                  "Please make sure you have correctly set up your private key for %s " %(artemisrc_path,private_key_path,ip_address))


    #python tests:
    python_path = get_artemis_config_value(section=ip_address,option="python")

    command = "python -c 'import os; print(os.path.isfile(os.path.expanduser(\"%s\")))'"%python_path
    ssh_conn = get_ssh_connection(ip_address)
    _,stdout,stderr = ssh_conn.exec_command(command)
    assert stdout.read().strip()=="True", "The provided path to the remote python installation on %s does not exist. You provided %s" %(ip_address, python_path)

    command = "%s -c 'print(\"Success\")'" % python_path
    _,stdout,stderr = ssh_conn.exec_command(command)
    err = stderr.read().strip()
    assert stdout.read().strip()=="Success" and not err, "The provided python path on %s does not seem to point to a python executable. " \
                                                         "You provided %s, which resulted in the following error on the remote machine: " %(ip_address, python_path, err)
Exemple #2
0
 def execute_child_process(self):
     '''
     Executes ChildProcess in a non-blocking manner. This returns immediately.
     This method returns a tuple (stdin, stdout, stderr) of the child process
     :return:
     '''
     if not self.is_local():
         self.ssh_conn = get_ssh_connection(self.ip_address)
     command = self.prepare_command(self.command)
     pid, stdin, stdout, stderr = self._run_command(command,get_pty=True)
     self._assign_pid(pid)
     self.cp_started = True
     return (stdin, stdout, stderr)
Exemple #3
0
 def execute_child_process(self):
     '''
     Executes ChildProcess in a non-blocking manner. This returns immediately.
     This method returns a tuple (stdin, stdout, stderr) of the child process
     :return:
     '''
     if not self.is_local():
         self.ssh_conn = get_ssh_connection(self.ip_address)
     command = self.prepare_command(self.command)
     pid, stdin, stdout, stderr = self._run_command(command, get_pty=True)
     self._assign_pid(pid)
     self.cp_started = True
     return (stdin, stdout, stderr)
Exemple #4
0
def get_remote_installed_packages(ip_address):
    '''
    This method queries a remote python installation about the installed packages.
    All necessary information is extracted from ~/.artemisrc
    :param address: Ip address of remote server
    :return:
    '''
    python_executable = get_artemis_config_value(section=ip_address,
                                                 option="python")
    function = "%s -c 'import pip; import json; print json.dumps({i.key: i.version  for i in pip.get_installed_distributions() })' " % python_executable

    ssh_conn = get_ssh_connection(ip_address)
    stdin, stdout, stderr = ssh_conn.exec_command(function)
    err = stderr.read()
    if err:
        msg="Quering %s python installation at %s sent a message on stderr. If you are confident that the error can be ignored, catch this RuntimeError" \
            "accordingly. The error is: %s"%(ip_address, python_executable, err)
        raise RuntimeError(msg)

    installed_packages = json.loads(stdout.read())
    ssh_conn.close()
    return installed_packages
Exemple #5
0
def execute_command(ip_address, command, blocking=True):
    '''
    This method spawns a child-process (either locally or remote, depending on the ip_address). Then it executes the given command and handles communication.
    If blocking is True, then this call does not return before the child process returns. It then prints stdout to console, followed by stderr.
    If blocking is False, then this call returns immediately and asynchronously forwards stdout and stderr to the console in separate threads.
    If ip_address is local, then the command will be split using shlex.split() and must be formatted accordingly. The subprocess call is executed with shell=False
    for all the right reasons.
    :param ip_address:
    :param command: String. command to execute
    :param blocking:
    :return:
    '''
    #TODO: Reformat this to work with the Nanny. Let it manage the communication
    if ip_address in get_local_ips():
        sub = subprocess.Popen(shlex.split(command),stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
        stdout_pipe = sub.stdout
        stderr_pipe = sub.stderr

    else:
        ssh_conn = get_ssh_connection(ip_address)
        transport = ssh_conn.get_transport()
        channel = transport.open_session()
        channel.exec_command(command)#
        bufsize=-1
        stdout_pipe = channel.makefile('r', bufsize)
        stderr_pipe = channel.makefile_stderr('r',bufsize)

    #stdout
    t1 = ParamikoPrintThread(source_pipe=stdout_pipe, target_pipe=sys.stdout)
    t1.start()
    # stderr
    t2 = ParamikoPrintThread(source_pipe=stderr_pipe, target_pipe=sys.stderr)
    t2.start()
    if blocking:
        t1.join()
        t2.join()
Exemple #6
0
def install_packages_on_remote_virtualenv(ip_address, packages):
    '''
    This function installs every package in packages on the remote virtual environment specified by the ip_address in ~/.artemisrc.
    In case the remote pip install -U command returns anything that is not "Successfully installed" or "Requirement already up-to-date" on stdout,
    the user is informed and an error that is not a SNIMissingWarning or InsecurePlatformWarning is printed.
    :param ip_address: ip_address, whose virtualenv is being modified
    :param packages: a dict {key:version} of package name and associated version
    :return:
    '''
    if len(packages) == 0:
        return
    print("installing/upgrading remote packages ...")
    python_path = get_artemis_config_value(ip_address, "python")
    activate_path = os.path.join(
        os.path.dirname(python_path),
        "activate")  # TODO: Make this work without the user using virtualenv
    activate_command = "source %s" % activate_path
    ssh_conn = get_ssh_connection(ip_address)
    for key, version in packages.items():
        install_command = "pip install -U %s==%s" % (key, version)
        function = "; ".join([activate_command, install_command])
        stdin, stdout, stderr = ssh_conn.exec_command(function)
        out = stdout.read()
        if "Successfully installed" in out or "Requirement already up-to-date" in out:
            pass
        else:
            print(("Error in installing %s==%s:" % (key, version)))
            err = stderr.read()
            err = "\n".join([
                s for s in err.strip().split("\n")
                if "SNIMissingWarning" not in s
                and "InsecurePlatformWarning" not in s
            ])
            print(err)
    ssh_conn.close()
    print("... Done")
Exemple #7
0
def check_config_file(ip_address, file_path=".artemisrc"):
    '''
    Makes sure all required fields are present in ~./artemisrc.
    Also performs test for the different options if applicable
    :param ip_address: The section to look for. Remote ip is assumed. Makes no sense for local ip.
    :return:
    '''
    mandatory_options = ["username", "python"]
    artemisrc_path = os.path.expanduser("~/%s" % file_path)
    for option in mandatory_options:
        try:
            get_artemis_config_value(section=ip_address, option=option)
        except NoSectionError:
            print("Section %s could not be found in %s. Please provide it." %
                  (ip_address, artemisrc_path))
            raise
        except NoOptionError:
            print(
                "Section %s does not contain option %s. Please provide it in %s"
                % (ip_address, option, artemisrc_path))
            raise

    # optional_options = ["private_key"]
    try:
        private_key_path = get_artemis_config_value(section=ip_address,
                                                    option="private_key")
        assert os.path.isfile(
            private_key_path
        ), "The path to the private_key for %s you specified in %s is not valid. You provided %s" % (
            ip_address, artemisrc_path, private_key_path)
    except NoOptionError:
        pass
    # username & private key setup tests:
    try:
        get_ssh_connection(ip_address)
    except paramiko.ssh_exception.AuthenticationException as e:
        if "Authentication failed" in e.message:
            print(
                "An AuthenticationException is being raised. Make sure you have your private key set up correctly"
            )
        else:
            print(
                "An AuthenticationException is being raised. Did you specify the correct username for %s in %s? You provided the username %s"
                % (ip_address, artemisrc_path,
                   get_artemis_config_value(section=ip_address,
                                            option="username")))
        raise
    except paramiko.ssh_exception.SSHException:
        try:
            private_key_path = get_artemis_config_value(section=ip_address,
                                                        option="private_key")
            print(
                "Something is wrong with the private_key you specified in %s for %s . You provided %s"
                % (artemisrc_path, ip_address, private_key_path))
            raise
        except NoOptionError:
            private_key_path = os.path.join(os.path.expanduser("~"),
                                            ".ssh/id_rsa")
            print(
                "You did not provide a private_key path in %s. The default path %s appears to be wrongly set up. "
                "Please make sure you have correctly set up your private key for %s "
                % (artemisrc_path, private_key_path, ip_address))

    #python tests:
    python_path = get_artemis_config_value(section=ip_address, option="python")

    command = "python -c 'import os; print(os.path.isfile(os.path.expanduser(\"%s\")))'" % python_path
    ssh_conn = get_ssh_connection(ip_address)
    _, stdout, stderr = ssh_conn.exec_command(command)
    assert stdout.read().strip(
    ) == "True", "The provided path to the remote python installation on %s does not exist. You provided %s" % (
        ip_address, python_path)

    command = "%s -c 'print(\"Success\")'" % python_path
    _, stdout, stderr = ssh_conn.exec_command(command)
    err = stderr.read().strip()
    assert stdout.read().strip()=="Success" and not err, "The provided python path on %s does not seem to point to a python executable. " \
                                                         "You provided %s, which resulted in the following error on the remote machine: " %(ip_address, python_path, err)