def download_file( self, remote_path: Path, local_path: Path, user: str, ssh_key_path: Path, public_ip_address: IPv4Address, ) -> None: """ Download a file from this node. Args: remote_path: The path on the node to download the file from. local_path: The path on the host to download the file to. user: The name of the remote user to send the file. ssh_key_path: The path to an SSH key which can be used to SSH to the node as the ``user`` user. public_ip_address: The public IP address of the node. """ container = _container_from_ip_address(ip_address=public_ip_address) args = [ 'docker', 'cp', container.id + ':' + str(remote_path), str(local_path), ] run_subprocess( args=args, log_output_live=False, pipe_output=True, )
def run( self, args: List[str], user: str, log_output_live: bool, env: Dict[str, Any], tty: bool, ssh_key_path: Path, public_ip_address: IPv4Address, capture_output: bool, ) -> subprocess.CompletedProcess: """ Run a command on this node the given user. Args: args: The command to run on the node. user: The username to communicate as. log_output_live: If ``True``, log output live. If ``True``, stderr is merged into stdout in the return value. env: Environment variables to be set on the node before running the command. A mapping of environment variable names to values. tty: If ``True``, allocate a pseudo-tty. This means that the users terminal is attached to the streams of the process. This means that the values of stdout and stderr will not be in the returned ``subprocess.CompletedProcess``. ssh_key_path: The path to an SSH key which can be used to SSH to the node as the ``user`` user. public_ip_address: The public IP address of the node. capture_output: Whether to capture output in the result. Returns: The representation of the finished process. Raises: subprocess.CalledProcessError: The process exited with a non-zero code. """ ssh_args = _compose_ssh_command( args=args, user=user, env=env, tty=tty, ssh_key_path=ssh_key_path, public_ip_address=public_ip_address, ) return run_subprocess( args=ssh_args, log_output_live=log_output_live, pipe_output=capture_output, )
def install_dcos_from_path( self, dcos_installer: Path, dcos_config: Dict[str, Any], ip_detect_path: Path, output: Output, files_to_copy_to_genconf_dir: Iterable[Tuple[Path, Path]], ) -> None: """ Install DC/OS from a given installer. Args: dcos_installer: The ``Path`` to an installer to install DC/OS from. dcos_config: The DC/OS configuration to use. ip_detect_path: The ``ip-detect`` script that is used for installing DC/OS. output: What happens with stdout and stderr. files_to_copy_to_genconf_dir: Pairs of host paths to paths on the installer node. These are files to copy from the host to the installer node before installing DC/OS. Raises: CalledProcessError: There was an error installing DC/OS on a node. """ copyfile( src=str(ip_detect_path), dst=str(self._genconf_dir / 'ip-detect'), ) config_yaml = yaml.dump(data=dcos_config) config_file_path = self._genconf_dir / 'config.yaml' config_file_path.write_text(data=config_yaml) for host_path, installer_path in files_to_copy_to_genconf_dir: relative_installer_path = installer_path.relative_to('/genconf') destination_path = self._genconf_dir / relative_installer_path if host_path.is_dir(): destination_path = destination_path / host_path.stem copytree(src=str(host_path), dst=str(destination_path)) else: copyfile(src=str(host_path), dst=str(destination_path)) genconf_args = [ 'bash', str(dcos_installer), '--offline', '-v', '--genconf', ] installer_ctr = '{cluster_id}-installer'.format( cluster_id=self._cluster_id, ) installer_port = _get_open_port() log_output_live = { Output.CAPTURE: False, Output.LOG_AND_CAPTURE: True, Output.NO_CAPTURE: False, }[output] capture_output = { Output.CAPTURE: True, Output.LOG_AND_CAPTURE: True, Output.NO_CAPTURE: False, }[output] run_subprocess( args=genconf_args, env={ 'PORT': str(installer_port), 'DCOS_INSTALLER_CONTAINER_NAME': installer_ctr, }, log_output_live=log_output_live, cwd=str(self._path), pipe_output=capture_output, ) for role, nodes in [ ('master', self.masters), ('slave', self.agents), ('slave_public', self.public_agents), ]: dcos_install_args = [ '/bin/bash', str(self._bootstrap_tmp_path / 'dcos_install.sh'), '--no-block-dcos-setup', role, ] for node in nodes: try: node.run(args=dcos_install_args) except subprocess.CalledProcessError as ex: # pragma: no cover LOGGER.error(ex.stdout) LOGGER.error(ex.stderr) raise