Beispiel #1
0
def cluster_install_dcos_from_url(
    cluster: Cluster,
    cluster_representation: ClusterRepresentation,
    ip_detect_path: Path,
    dcos_config: Dict[str, Any],
    files_to_copy_to_genconf_dir: Iterable[Tuple[Path, Path]],
    dcos_installer: str,
    doctor_message: str,
    enable_spinner: bool,
) -> None:
    """
    Install DC/OS on a cluster.

    Args:
        cluster: The cluster to install DC/OS on.
        cluster_representation: A representation of the cluster.
        ip_detect_path: The ``ip-detect`` script to use for installing DC/OS.
        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 upgrading DC/OS.
        dcos_config: The DC/OS configuration to use.
        dcos_installer: A URL pointing to an installer.
        doctor_message: A message which instructs the user on which command to
            use if installation fails.
        enable_spinner: Whether to enable the spinner animation.
    """
    spinner = Halo(enabled=enable_spinner)
    spinner.start('Installing DC/OS')

    # We allow a cluster to be passed in rather than just inferring it from
    # ``cluster_representation`` in case the ``cluster`` has a more efficient
    # installation method than a ``Cluster.from_nodes``.
    # However, if the cluster is a ``Cluster.from_nodes``, ``destroy`` will not
    # work and therefore we use ``cluster_representation.destroy`` instead.
    try:
        cluster.install_dcos_from_url(
            dcos_installer=dcos_installer,
            dcos_config=dcos_config,
            ip_detect_path=ip_detect_path,
            files_to_copy_to_genconf_dir=files_to_copy_to_genconf_dir,
            output=Output.LOG_AND_CAPTURE,
        )
    except subprocess.CalledProcessError as exc:
        spinner.stop()
        click.echo('Error installing DC/OS.', err=True)
        show_calledprocess_error(exc=exc)
        click.echo(doctor_message)
        cluster_representation.destroy()
        sys.exit(exc.returncode)

    spinner.succeed()
Beispiel #2
0
extra_config = {
    'superuser_username': username,
    'superuser_password_hash': sha512_crypt.hash(password),
#    'fault_domain_enabled': False,
}

test_license = os.environ.get('DCOS_TEST_LICENSE')
if test_license:
    extra_config['license_key_contents'] = test_license

dcos_config = {**cluster.base_config, **extra_config}

cluster.install_dcos_from_url(
    dcos_installer=sys.argv[1],
    dcos_config=dcos_config,
    ip_detect_path=cluster_backend.ip_detect_path,
    output=Output.LOG_AND_CAPTURE,
)

if dcos_variant == 'open':
    cluster.wait_for_dcos_oss()
else:
    cluster.wait_for_dcos_ee(
        superuser_username=username,
        superuser_password=password,
    )

master_node = next(iter(cluster.masters))
master_ip = master_node.public_ip_address.exploded

# In order to create a user with a password on DC/OS Open, we login with the well-known key
Beispiel #3
0
extra_config = {
    'superuser_username': username,
    'superuser_password_hash': sha512_crypt.hash(password),
    #    'fault_domain_enabled': False,
}

test_license = os.environ.get('DCOS_TEST_LICENSE')
if test_license:
    extra_config['license_key_contents'] = test_license

dcos_config = {**cluster.base_config, **extra_config}

cluster.install_dcos_from_url(
    dcos_installer=sys.argv[1],
    dcos_config=dcos_config,
    ip_detect_path=cluster_backend.ip_detect_path,
    output=Output.LOG_AND_CAPTURE,
)

if dcos_variant == 'open':
    cluster.wait_for_dcos_oss()
else:
    cluster.wait_for_dcos_ee(
        superuser_username=username,
        superuser_password=password,
    )

master_node = next(iter(cluster.masters))
master_ip = master_node.public_ip_address.exploded

# In order to create a user with a password on DC/OS Open, we login with the well-known key
Beispiel #4
0
username = '******'
password = ''.join(
    random.choice(string.ascii_letters + string.digits) for i in range(12))

extra_config = {
    'superuser_username': username,
    'superuser_password_hash': sha512_crypt.hash(password),
    'fault_domain_enabled': False,
    'license_key_contents': test_license,
}

dcos_config = {**cluster.base_config, **extra_config}

cluster.install_dcos_from_url(
    build_artifact=sys.argv[1],
    dcos_config=dcos_config,
    log_output_live=True,
    ip_detect_path=cluster_backend.ip_detect_path,
)

cluster.wait_for_dcos_ee(
    superuser_username=username,
    superuser_password=password,
)

master_node = next(iter(cluster.masters))
master_ip = master_node.public_ip_address.exploded

out = '''
export DCOS_TEST_DEFAULT_CLUSTER_VARIANT=enterprise
export DCOS_TEST_DEFAULT_CLUSTER_USERNAME={}
export DCOS_TEST_DEFAULT_CLUSTER_PASSWORD={}
Beispiel #5
0
def create(
    agents: int,
    artifact_url: str,
    extra_config: Dict[str, Any],
    masters: int,
    public_agents: int,
    variant: str,
    workspace_dir: Optional[Path],
    license_key: Optional[str],
    security_mode: Optional[str],
    copy_to_master: List[Tuple[Path, Path]],
    verbose: int,
    aws_region: str,
    linux_distribution: str,
    cluster_id: str,
    enable_selinux_enforcing: bool,
    genconf_dir: Optional[Path],
    custom_tag: Dict[str, str],
) -> None:
    """
    Create a DC/OS cluster.

        DC/OS Enterprise

            \b
            DC/OS Enterprise clusters require different configuration variables to DC/OS OSS.
            For example, enterprise clusters require the following configuration parameters:

            ``superuser_username``, ``superuser_password_hash``, ``fault_domain_enabled``, ``license_key_contents``

            \b
            These can all be set in ``--extra-config``.
            However, some defaults are provided for all but the license key.

            \b
            The default superuser username is ``admin``.
            The default superuser password is ``admin``.
            The default ``fault_domain_enabled`` is ``false``.

            \b
            ``license_key_contents`` must be set for DC/OS Enterprise 1.11 and above.
            This is set to one of the following, in order:

            \b
            * The ``license_key_contents`` set in ``--extra-config``.
            * The contents of the path given with ``--license-key``.
            * The contents of the path set in the ``DCOS_LICENSE_KEY_PATH`` environment variable.

            \b
            If none of these are set, ``license_key_contents`` is not given.
    """  # noqa: E501
    set_logging(verbosity_level=verbose)
    check_cluster_id_unique(
        new_cluster_id=cluster_id,
        existing_cluster_ids=existing_cluster_ids(aws_region=aws_region),
    )
    base_workspace_dir = workspace_dir or Path(tempfile.gettempdir())
    workspace_dir = base_workspace_dir / uuid.uuid4().hex
    workspace_dir.mkdir(parents=True)
    ssh_keypair_dir = workspace_dir / 'ssh'
    ssh_keypair_dir.mkdir(parents=True)
    key_name = 'dcos-e2e-{random}'.format(random=uuid.uuid4().hex)
    public_key_path = ssh_keypair_dir / 'id_rsa.pub'
    private_key_path = ssh_keypair_dir / 'id_rsa'
    write_key_pair(
        public_key_path=public_key_path,
        private_key_path=private_key_path,
    )

    ec2 = boto3.resource('ec2', region_name=aws_region)
    ec2.import_key_pair(
        KeyName=key_name,
        PublicKeyMaterial=public_key_path.read_bytes(),
    )

    doctor_message = 'Try `dcos-aws doctor` for troubleshooting help.'
    enterprise = bool(variant == 'enterprise')

    ssh_user = {
        Distribution.CENTOS_7: 'centos',
        Distribution.COREOS: 'core',
        Distribution.UBUNTU_16_04: 'ubuntu',
        Distribution.RHEL_7: 'ec2-user',
    }

    distribution = LINUX_DISTRIBUTIONS[linux_distribution]

    default_user = ssh_user[distribution]

    cluster_tags = {
        SSH_USER_TAG_KEY: default_user,
        CLUSTER_ID_TAG_KEY: cluster_id,
        WORKSPACE_DIR_TAG_KEY: str(workspace_dir),
        KEY_NAME_TAG_KEY: key_name,
        VARIANT_TAG_KEY: 'ee' if enterprise else '',
        **custom_tag,
    }

    master_tags = {NODE_TYPE_TAG_KEY: NODE_TYPE_MASTER_TAG_VALUE}
    agent_tags = {NODE_TYPE_TAG_KEY: NODE_TYPE_AGENT_TAG_VALUE}
    public_agent_tags = {NODE_TYPE_TAG_KEY: NODE_TYPE_PUBLIC_AGENT_TAG_VALUE}
    cluster_backend = AWS(
        aws_key_pair=(key_name, private_key_path),
        workspace_dir=workspace_dir,
        aws_region=aws_region,
        linux_distribution=distribution,
        ec2_instance_tags=cluster_tags,
        master_ec2_instance_tags=master_tags,
        agent_ec2_instance_tags=agent_tags,
        public_agent_ec2_instance_tags=public_agent_tags,
    )

    if enterprise:
        superuser_username = '******'
        superuser_password = '******'

        enterprise_extra_config = {
            'superuser_username': superuser_username,
            'superuser_password_hash': sha512_crypt.hash(superuser_password),
            'fault_domain_enabled': False,
        }
        if license_key is not None:
            key_contents = Path(license_key).read_text()
            enterprise_extra_config['license_key_contents'] = key_contents

        extra_config = {**enterprise_extra_config, **extra_config}
        if security_mode is not None:
            extra_config['security'] = security_mode

    try:
        cluster = Cluster(
            cluster_backend=cluster_backend,
            masters=masters,
            agents=agents,
            public_agents=public_agents,
        )
    except CalledProcessError as exc:
        click.echo('Error creating cluster.', err=True)
        click.echo(doctor_message)
        sys.exit(exc.returncode)

    nodes = {*cluster.masters, *cluster.agents, *cluster.public_agents}
    for node in nodes:
        if enable_selinux_enforcing:
            node.run(args=['setenforce', '1'], sudo=True)

    for node in cluster.masters:
        for path_pair in copy_to_master:
            local_path, remote_path = path_pair
            node.send_file(
                local_path=local_path,
                remote_path=remote_path,
            )

    files_to_copy_to_genconf_dir = []
    if genconf_dir is not None:
        container_genconf_path = Path('/genconf')
        for genconf_file in genconf_dir.glob('*'):
            genconf_relative = genconf_file.relative_to(genconf_dir)
            relative_path = container_genconf_path / genconf_relative
            files_to_copy_to_genconf_dir.append((genconf_file, relative_path))

    try:
        with click_spinner.spinner():
            cluster.install_dcos_from_url(
                build_artifact=artifact_url,
                dcos_config={
                    **cluster.base_config,
                    **extra_config,
                },
                ip_detect_path=cluster_backend.ip_detect_path,
                files_to_copy_to_genconf_dir=files_to_copy_to_genconf_dir,
            )
    except CalledProcessError as exc:
        click.echo('Error installing DC/OS.', err=True)
        click.echo(doctor_message)
        cluster.destroy()
        sys.exit(exc.returncode)