예제 #1
0
    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,
        )
예제 #2
0
    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,
        )
예제 #3
0
    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