Beispiel #1
0
def slave_table(slaves, field_names=()):
    """Returns a PrettyTable representation of the provided DC/OS slaves

    :param slaves: slaves to render.  dicts from /mesos/state-summary
    :type slaves: [dict]
    :param field_names: Extra fields to add to the table
    :type slaves: [str]
    :rtype: PrettyTable
    """

    fields = OrderedDict([
        ('HOSTNAME', lambda s: s['hostname']),
        ('IP', lambda s: mesos.parse_pid(s['pid'])[1]),
        ('ID', lambda s: s['id'])
    ])

    for field_name in field_names:
        if field_name.upper() in fields:
            continue
        if ':' in field_name:
            heading, field_name = field_name.split(':', 1)
        else:
            heading = field_name
        fields[heading.upper()] = _dotted_itemgetter(field_name.lower())

    sortby = list(fields.keys())[0]
    tb = table(fields, slaves, sortby=sortby)
    return tb
Beispiel #2
0
def node_table(nodes, field_names=()):
    """Returns a PrettyTable representation of the provided DC/OS nodes

    :param nodes: nodes to render.
    :type nodes: [dict]
    :param field_names: Extra fields to add to the table
    :type nodes: [str]
    :rtype: PrettyTable
    """

    fields = OrderedDict([
        ('HOSTNAME', lambda s: s.get('host', s.get('hostname'))),
        ('IP', lambda s: s.get('ip') or mesos.parse_pid(s['pid'])[1]),
        ('ID', lambda s: s['id']),
        ('TYPE', lambda s: s['type']),
    ])

    for field_name in field_names:
        if field_name.upper() in fields:
            continue
        if ':' in field_name:
            heading, field_name = field_name.split(':', 1)
        else:
            heading = field_name
        fields[heading.upper()] = _dotted_itemgetter(field_name)

    sortby = list(fields.keys())[0]
    tb = table(fields, nodes, sortby=sortby)
    tb.align['TYPE'] = 'l'
    return tb
Beispiel #3
0
def node_table(nodes, field_names=()):
    """Returns a PrettyTable representation of the provided DC/OS nodes

    :param nodes: nodes to render.
    :type nodes: [dict]
    :param field_names: Extra fields to add to the table
    :type nodes: [str]
    :rtype: PrettyTable
    """

    fields = OrderedDict([
        ('HOSTNAME', lambda s: s.get('host', s.get('hostname'))),
        ('IP', lambda s: s.get('ip') or mesos.parse_pid(s['pid'])[1]),
        ('ID', lambda s: s['id']),
        ('TYPE', lambda s: s['type']),
        ('REGION', lambda s: s['region']),
        ('ZONE', lambda s: s['zone']),
    ])

    for field_name in field_names:
        if field_name.upper() in fields:
            continue
        if ':' in field_name:
            heading, field_name = field_name.split(':', 1)
        else:
            heading = field_name
        fields[heading.upper()] = _dotted_itemgetter(field_name)

    sortby = list(fields.keys())[0]
    tb = table(fields, nodes, sortby=sortby)
    tb.align['TYPE'] = 'l'
    return tb
Beispiel #4
0
def _ssh(leader, slave, option, config_file, user, master_proxy, proxy_ip,
         private_ip, command):
    """SSH into a DC/OS node using the IP addresses found in master's
       state.json

    :param leader: True if the user has opted to SSH into the leading
                   master
    :type leader: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :param master_proxy: If True, SSH-hop from a master
    :type master_proxy: bool | None
    :param proxy_ip: If set, SSH-hop from this IP address
    :type proxy_ip: str | None
    :param private_ip: The private IP address of the node we want to SSH to.
    :type private_ip: str | None
    :param command: Command to run on the node
    :type command: str | None
    :rtype: int
    :returns: process return code
    """

    dcos_client = mesos.DCOSClient()

    if leader:
        host = mesos.MesosDNSClient().leader()[0]['ip']
    elif private_ip:
        host = private_ip
    else:
        summary = dcos_client.get_state_summary()
        slave_obj = next(
            (slave_ for slave_ in summary['slaves'] if slave_['id'] == slave),
            None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    if command is None:
        command = ''

    ssh_options = ssh_util.get_ssh_options(config_file, option, user, proxy_ip,
                                           master_proxy)
    cmd = "ssh {0} {1} -- {2}".format(ssh_options, host, command)

    emitter.publish(DefaultError("Running `{}`".format(cmd)))
    if not master_proxy and not proxy_ip:
        emitter.publish(
            DefaultError("If you are running this command from a separate "
                         "network than DC/OS, consider using "
                         "`--master-proxy` or `--proxy-ip`"))

    return subprocess.Subproc().call(cmd, shell=True)
Beispiel #5
0
 def get_agents(self):
     _agents = self.dcos_client.get_state_summary()['slaves']
     for agent in agents:
         self.agents.append({
             "hostname": agent['hostname'],
             "ip": mesos.parse_pid(agent['pid'])[1],
             "id": agent['id']
         })
 def get_agents(self):
     _agents = self.dcos_client.get_state_summary()['slaves']
     for agent in agents:
         self.agents.append(
             {"hostname": agent['hostname'],
             "ip": mesos.parse_pid(agent['pid'])[1], "id": agent['id']
             }
         )
Beispiel #7
0
def public_windows_slaves_addresses():
    slaves = dcos_slaves()
    addresses = []
    for slave in slaves:
        if("public_ip" in slave["attributes"].keys() and
           "os" in slave["attributes"].keys() and
           slave["attributes"]["os"] == "Windows"):
            addresses.append(mesos.parse_pid(slave["pid"])[1])
    return addresses
Beispiel #8
0
def private_linux_slaves_addresses():
    slaves = dcos_slaves()
    addresses = []
    for slave in slaves:
        if("public_ip" not in slave["attributes"].keys() and
           "os" in slave["attributes"].keys() and
           slave["attributes"]["os"] == "Linux"):
            addresses.append(mesos.parse_pid(slave["pid"])[1])
    return addresses
Beispiel #9
0
def _ssh(master, slave, option, config_file, user):
    """SSH into a DCOS node.  Since only the masters are definitely
    publicly available, we first ssh into an arbitrary master, then
    hop to the desired node.

    :param master: True if the user has opted to SSH into the leading
                   master
    :type master: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :rtype: int
    :returns: process return code

    """
    if not os.environ.get('SSH_AUTH_SOCK'):
        raise DCOSException(
            "There is no SSH_AUTH_SOCK env variable, which likely means you " +
            "aren't running `ssh-agent`.  `dcos node ssh` depends on " +
            "`ssh-agent` so we can safely use your private key to hop " +
            "between nodes in your cluster.  Please run `ssh-agent`, " +
            "then add your private key with `ssh-add`.")

    master_public_ip = mesos.DCOSClient().metadata()['PUBLIC_IPV4']
    ssh_options = ' '.join('-o {}'.format(opt) for opt in option)

    if config_file:
        ssh_config = '-F {}'.format(config_file)
    else:
        ssh_config = ''

    if master:
        host = 'leader.mesos'
    else:
        summary = mesos.DCOSClient().get_state_summary()
        slave_obj = next((slave_ for slave_ in summary['slaves']
                          if slave_['id'] == slave),
                         None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    cmd = "ssh -A -t {0} {1} {2}@{3} ssh -A -t {2}@{4}".format(
        ssh_options,
        ssh_config,
        user,
        master_public_ip,
        host)

    return subprocess.call(cmd, shell=True)
Beispiel #10
0
def slave_table(slaves):
    """Returns a PrettyTable representation of the provided DC/OS slaves

    :param slaves: slaves to render.  dicts from /mesos/state-summary
    :type slaves: [dict]
    :rtype: PrettyTable
    """

    fields = OrderedDict([('HOSTNAME', lambda s: s['hostname']),
                          ('IP', lambda s: mesos.parse_pid(s['pid'])[1]),
                          ('ID', lambda s: s['id'])])

    tb = table(fields, slaves, sortby="HOSTNAME")
    return tb
Beispiel #11
0
def slave_table(slaves):
    """Returns a PrettyTable representation of the provided DC/OS slaves

    :param slaves: slaves to render.  dicts from /mesos/state-summary
    :type slaves: [dict]
    :rtype: PrettyTable
    """

    fields = OrderedDict([
        ('HOSTNAME', lambda s: s['hostname']),
        ('IP', lambda s: mesos.parse_pid(s['pid'])[1]),
        ('ID', lambda s: s['id'])
    ])

    tb = table(fields, slaves, sortby="HOSTNAME")
    return tb
Beispiel #12
0
def _ssh(master, slave, option, config_file, user):
    """SSH into a DCOS node.  Since only the masters are definitely
    publicly available, we first ssh into an arbitrary master, then
    hop to the desired node.

    :param master: True if the user has opted to SSH into the leading
                   master
    :type master: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :rtype: int
    :returns: process return code
    """

    ssh_options = util.get_ssh_options(config_file, option)

    if master:
        host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
    else:
        summary = mesos.DCOSClient().get_state_summary()
        slave_obj = next((slave_ for slave_ in summary['slaves']
                          if slave_['id'] == slave),
                         None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    cmd = "ssh -t {0}{1}@{2}".format(
        ssh_options,
        user,
        host)

    emitter.publish(DefaultError("Running `{}`".format(cmd)))

    return subprocess.call(cmd, shell=True)
Beispiel #13
0
def _ssh(master, slave, option, config_file, user):
    """SSH into a DCOS node using the IP addresses found in master's
       state.json

    :param master: True if the user has opted to SSH into the leading
                   master
    :type master: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :rtype: int
    :returns: process return code
    """

    ssh_options = util.get_ssh_options(config_file, option)

    if master:
        host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
    else:
        summary = mesos.DCOSClient().get_state_summary()
        slave_obj = next((slave_ for slave_ in summary['slaves']
                          if slave_['id'] == slave),
                         None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    cmd = "ssh -t {0}{1}@{2}".format(
        ssh_options,
        user,
        host)

    emitter.publish(DefaultError("Running `{}`".format(cmd)))

    return subprocess.call(cmd, shell=True)
Beispiel #14
0
def _ssh(master, slave, option, config_file, user):
    """SSH into a DCOS node using the IP addresses found in master's
       state.json

    :param master: True if the user has opted to SSH into the leading
                   master
    :type master: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :rtype: int
    :returns: process return code
    """

    ssh_options = util.get_ssh_options(config_file, option)

    if master:
        host = mesos.MesosDNSClient().hosts("leader.mesos.")[0]["ip"]
    else:
        summary = mesos.DCOSClient().get_state_summary()
        slave_obj = next((slave_ for slave_ in summary["slaves"] if slave_["id"] == slave), None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj["pid"])[1]
        else:
            raise DCOSException("No slave found with ID [{}]".format(slave))

    cmd = "ssh -t {0}{1}@{2}".format(ssh_options, user, host)

    emitter.publish(DefaultError("Running `{}`".format(cmd)))

    return subprocess.call(cmd, shell=True)
Beispiel #15
0
def _ssh(leader, slave, option, config_file, user, master_proxy, proxy_ip,
         command):
    """SSH into a DC/OS node using the IP addresses found in master's
       state.json

    :param leader: True if the user has opted to SSH into the leading
                   master
    :type leader: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :param master_proxy: If True, SSH-hop from a master
    :type master_proxy: bool | None
    :param proxy_ip: If set, SSH-hop from this IP address
    :type proxy_ip: str | None
    :param command: Command to run on the node
    :type command: str | None
    :rtype: int
    :returns: process return code
    """

    ssh_options = util.get_ssh_options(config_file, option)
    dcos_client = mesos.DCOSClient()

    if leader:
        host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
    else:
        summary = dcos_client.get_state_summary()
        slave_obj = next((slave_ for slave_ in summary['slaves']
                          if slave_['id'] == slave),
                         None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    if command is None:
        command = ''

    master_public_ip = dcos_client.metadata().get('PUBLIC_IPV4')

    if master_proxy:
        if not master_public_ip:
            raise DCOSException(("Cannot use --master-proxy.  Failed to find "
                                 "'PUBLIC_IPV4' at {}").format(
                                     dcos_client.get_dcos_url('metadata')))
        proxy_ip = master_public_ip

    if proxy_ip:
        if not os.environ.get('SSH_AUTH_SOCK'):
            raise DCOSException(
                "There is no SSH_AUTH_SOCK env variable, which likely means "
                "you aren't running `ssh-agent`.  `dcos node ssh "
                "--master-proxy/--proxy-ip` depends on `ssh-agent` to safely "
                "use your private key to hop between nodes in your cluster.  "
                "Please run `ssh-agent`, then add your private key with "
                "`ssh-add`.")
        cmd = "ssh -A -t {0}{1}@{2} ssh -A -t {0}{1}@{3} {4}".format(
            ssh_options,
            user,
            proxy_ip,
            host,
            command)
    else:
        cmd = "ssh -t {0}{1}@{2} {3}".format(
            ssh_options,
            user,
            host,
            command)

    emitter.publish(DefaultError("Running `{}`".format(cmd)))
    if (not master_proxy and not proxy_ip) and master_public_ip:
        emitter.publish(
            DefaultError("If you are running this command from a separate "
                         "network than DC/OS, consider using "
                         "`--master-proxy` or `--proxy-ip`"))

    return subprocess.Subproc().call(cmd, shell=True)
Beispiel #16
0
def _ssh(leader, slave, option, config_file, user, master_proxy, command,
         flag=[], print_command=True, short_circuit=False, output=False,
         output_dst=None, tty=True, raw=False):
    """SSH into a DCOS node using the IP addresses found in master's
       state.json

    :param leader: True if the user has opted to SSH into the leading
                   master
    :type leader: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :param master_proxy: If True, SSH-hop from a master
    :type master_proxy: bool | None
    :param command: Command to run on the node
    :type command: str | None
    :param flag: SSH flags
    :type flag: [str]
    :param print_command: If True, print the raw SSH command
    :type print_command: bool
    :param short_circuit: Only use the first SSH connection made
    :type short_circuit: bool
    :param output: If True, return the output of the ssh command
    :type output: boolean
    :param output_dst: Where to send the output of SSH
    :type output_dst: object | None
    :param tty: If True, have SSH allocate a TTY
    :type tty: boolean
    :param raw: If True, return a subprocess.Popen object
    :type raw: boolean
    :rtype: int
    :returns: process return code | str
    """

    ssh_options = util.get_ssh_options(config_file, option)
    dcos_client = mesos.DCOSClient()
    flagstr = " ".join(flag)

    if tty:
        flagstr += ' -t'
    else:
        flagstr += ' -T'

    if leader:
        host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
    else:
        summary = dcos_client.get_state_summary()
        slave_obj = next((slave_ for slave_ in summary['slaves']
                          if slave_['id'] == slave),
                         None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    if command is None:
        command = ''

    master_public_ip = dcos_client.metadata().get('PUBLIC_IPV4')
    if master_proxy:
        if not os.environ.get('SSH_AUTH_SOCK'):
            raise DCOSException(
                "There is no SSH_AUTH_SOCK env variable, which likely means "
                "you aren't running `ssh-agent`.  `dcos node ssh "
                "--master-proxy` depends on `ssh-agent` to safely use your "
                "private key to hop between nodes in your cluster.  Please "
                "run `ssh-agent`, then add your private key with `ssh-add`.")
        if not master_public_ip:
            raise DCOSException(("Cannot use --master-proxy.  Failed to find "
                                 "'PUBLIC_IPV4' at {}").format(
                                     dcos_client.get_dcos_url('metadata')))

        cmd = "ssh -A {0} {1}{2}@{3} ssh {0} {1}{2}@{4} {5}"
        if short_circuit:
            cmd = "ssh -A {0} {1}{2}@{3} {5}"
        cmd = cmd.format(
            flagstr,
            ssh_options,
            user,
            master_public_ip,
            host,
            command)
    else:
        cmd = "ssh {0} {1}{2}@{3} {4}".format(
            flagstr,
            ssh_options,
            user,
            host,
            command)

    if print_command:
        emitter.publish(DefaultError("Running `{}`".format(cmd)))
    if (not master_proxy) and master_public_ip:
        emitter.publish(
            DefaultError("If you are running this command from a separate "
                         "network than DC/OS, consider using "
                         "`--master-proxy`"))

    cmd = shlex.split(cmd)
    if output:
        return subprocess.check_output(cmd)
    if raw:
        if output_dst is not None:
            return subprocess.Popen(cmd, stderr=output_dst, stdout=output_dst)
        return subprocess.Popen(cmd)
    if output_dst is not None:
        return subprocess.call(cmd, stderr=output_dst, stdout=output_dst)
    return subprocess.call(cmd)
Beispiel #17
0
def _ssh(leader,
         slave,
         option,
         config_file,
         user,
         master_proxy,
         command,
         flag=[],
         print_command=True,
         short_circuit=False,
         output=False,
         output_dst=None,
         tty=True,
         raw=False):
    """SSH into a DCOS node using the IP addresses found in master's
       state.json

    :param leader: True if the user has opted to SSH into the leading
                   master
    :type leader: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :param master_proxy: If True, SSH-hop from a master
    :type master_proxy: bool | None
    :param command: Command to run on the node
    :type command: str | None
    :param flag: SSH flags
    :type flag: [str]
    :param print_command: If True, print the raw SSH command
    :type print_command: bool
    :param short_circuit: Only use the first SSH connection made
    :type short_circuit: bool
    :param output: If True, return the output of the ssh command
    :type output: boolean
    :param output_dst: Where to send the output of SSH
    :type output_dst: object | None
    :param tty: If True, have SSH allocate a TTY
    :type tty: boolean
    :param raw: If True, return a subprocess.Popen object
    :type raw: boolean
    :rtype: int
    :returns: process return code | str
    """

    ssh_options = util.get_ssh_options(config_file, option)
    dcos_client = mesos.DCOSClient()
    flagstr = " ".join(flag)

    if tty:
        flagstr += ' -t'
    else:
        flagstr += ' -T'

    if leader:
        host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
    else:
        summary = dcos_client.get_state_summary()
        slave_obj = next(
            (slave_ for slave_ in summary['slaves'] if slave_['id'] == slave),
            None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    if command is None:
        command = ''

    master_public_ip = dcos_client.metadata().get('PUBLIC_IPV4')
    if master_proxy:
        if not os.environ.get('SSH_AUTH_SOCK'):
            raise DCOSException(
                "There is no SSH_AUTH_SOCK env variable, which likely means "
                "you aren't running `ssh-agent`.  `dcos node ssh "
                "--master-proxy` depends on `ssh-agent` to safely use your "
                "private key to hop between nodes in your cluster.  Please "
                "run `ssh-agent`, then add your private key with `ssh-add`.")
        if not master_public_ip:
            raise DCOSException(("Cannot use --master-proxy.  Failed to find "
                                 "'PUBLIC_IPV4' at {}").format(
                                     dcos_client.get_dcos_url('metadata')))

        cmd = "ssh -A {0} {1}{2}@{3} ssh {0} {1}{2}@{4} {5}"
        if short_circuit:
            cmd = "ssh -A {0} {1}{2}@{3} {5}"
        cmd = cmd.format(flagstr, ssh_options, user, master_public_ip, host,
                         command)
    else:
        cmd = "ssh {0} {1}{2}@{3} {4}".format(flagstr, ssh_options, user, host,
                                              command)

    if print_command:
        emitter.publish(DefaultError("Running `{}`".format(cmd)))
    if (not master_proxy) and master_public_ip:
        emitter.publish(
            DefaultError("If you are running this command from a separate "
                         "network than DC/OS, consider using "
                         "`--master-proxy`"))

    cmd = shlex.split(cmd)
    if output:
        return subprocess.check_output(cmd)
    if raw:
        if output_dst is not None:
            return subprocess.Popen(cmd, stderr=output_dst, stdout=output_dst)
        return subprocess.Popen(cmd)
    if output_dst is not None:
        return subprocess.call(cmd, stderr=output_dst, stdout=output_dst)
    return subprocess.call(cmd)
Beispiel #18
0
def _ssh(leader, slave, option, config_file, user, master_proxy, command):
    """SSH into a DC/OS node using the IP addresses found in master's
       state.json

    :param leader: True if the user has opted to SSH into the leading
                   master
    :type leader: bool | None
    :param slave: The slave ID if the user has opted to SSH into a slave
    :type slave: str | None
    :param option: SSH option
    :type option: [str]
    :param config_file: SSH config file
    :type config_file: str | None
    :param user: SSH user
    :type user: str | None
    :param master_proxy: If True, SSH-hop from a master
    :type master_proxy: bool | None
    :param command: Command to run on the node
    :type command: str | None
    :rtype: int
    :returns: process return code
    """

    ssh_options = util.get_ssh_options(config_file, option)
    dcos_client = mesos.DCOSClient()

    if leader:
        host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
    else:
        summary = dcos_client.get_state_summary()
        slave_obj = next((slave_ for slave_ in summary['slaves']
                          if slave_['id'] == slave),
                         None)
        if slave_obj:
            host = mesos.parse_pid(slave_obj['pid'])[1]
        else:
            raise DCOSException('No slave found with ID [{}]'.format(slave))

    if command is None:
        command = ''

    master_public_ip = dcos_client.metadata().get('PUBLIC_IPV4')
    if master_proxy:
        if not os.environ.get('SSH_AUTH_SOCK'):
            raise DCOSException(
                "There is no SSH_AUTH_SOCK env variable, which likely means "
                "you aren't running `ssh-agent`.  `dcos node ssh "
                "--master-proxy` depends on `ssh-agent` to safely use your "
                "private key to hop between nodes in your cluster.  Please "
                "run `ssh-agent`, then add your private key with `ssh-add`.")
        if not master_public_ip:
            raise DCOSException(("Cannot use --master-proxy.  Failed to find "
                                 "'PUBLIC_IPV4' at {}").format(
                                     dcos_client.get_dcos_url('metadata')))

        cmd = "ssh -A -t {0}{1}@{2} ssh -A -t {0}{1}@{3} {4}".format(
            ssh_options,
            user,
            master_public_ip,
            host,
            command)
    else:
        cmd = "ssh -t {0}{1}@{2} {3}".format(
            ssh_options,
            user,
            host,
            command)

    emitter.publish(DefaultError("Running `{}`".format(cmd)))
    if (not master_proxy) and master_public_ip:
        emitter.publish(
            DefaultError("If you are running this command from a separate "
                         "network than DC/OS, consider using "
                         "`--master-proxy`"))

    return subprocess.Subproc().call(cmd, shell=True)