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
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
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
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)
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'] } )
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
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
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)
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
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
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)
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)
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)
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)
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)
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)
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)