def _create_temp_vapp(ctx, client, vdc, config, template_config, ssh_key):
    """Handles temporary VApp creation and customization step of CSE install.

    Initializes and customizes VApp.

    :param click.core.Context ctx: click context object.
    :param pyvcloud.vcd.client.Client client:
    :param dict config: CSE config.
    :param dict template_config: specific template config section of @config.
    :param str ssh_key: ssh key to use in temporary VApp's VM. Can be None.

    :return: VApp object for temporary VApp.

    :rtype: pyvcloud.vcd.vapp.VApp

    :raises FileNotFoundError: if init/customization scripts are not found.
    :raises Exception: if VM customization fails.
    """
    vapp_name = template_config['temp_vapp']
    init_script = get_data_file(f"init-{template_config['name']}.sh",
                                logger=LOGGER)
    if ssh_key is not None:
        init_script += \
            f"""
            mkdir -p /root/.ssh
            echo '{ssh_key}' >> /root/.ssh/authorized_keys
            chmod -R go-rwx /root/.ssh
            """
    msg = f"Creating vApp '{vapp_name}'"
    click.secho(msg, fg='yellow')
    LOGGER.info(msg)
    vapp = _create_vapp_from_config(client, vdc, config, template_config,
                                    init_script)
    msg = f"Created vApp '{vapp_name}'"
    click.secho(msg, fg='green')
    LOGGER.info(msg)
    msg = f"Customizing vApp '{vapp_name}'"
    click.secho(msg, fg='yellow')
    LOGGER.info(msg)
    cust_script = get_data_file(f"cust-{template_config['name']}.sh",
                                logger=LOGGER)
    ova_name = template_config['source_ova_name']
    is_photon = True if 'photon' in ova_name else False
    _customize_vm(ctx,
                  config,
                  vapp,
                  vapp.name,
                  cust_script,
                  is_photon=is_photon)
    msg = f"Customized vApp '{vapp_name}'"
    click.secho(msg, fg='green')
    LOGGER.info(msg)

    return vapp
Пример #2
0
def init_cluster(config, vapp, template):
    script = get_data_file('mstr-%s.sh' % template['name'])
    nodes = get_nodes(vapp, TYPE_MASTER)
    result = execute_script_in_nodes(config, vapp, template['admin_password'],
                                     script, nodes)
    if result[0][0] != 0:
        raise ClusterInitializationError('Couldn\'t initialize cluster:\n%s' %
                                         result[0][2].content.decode())
Пример #3
0
def join_cluster(config, vapp, template, target_nodes=None):
    init_info = get_init_info(config, vapp, template['admin_password'])
    tmp_script = get_data_file('node-%s.sh' % template['name'])
    script = tmp_script.format(token=init_info[0], ip=init_info[1])
    if target_nodes is None:
        nodes = get_nodes(vapp, TYPE_NODE)
    else:
        nodes = []
        for node in vapp.get_all_vms():
            if node.get('name') in target_nodes:
                nodes.append(node)
    results = execute_script_in_nodes(config, vapp, template['admin_password'],
                                      script, nodes)
    for result in results:
        if result[0] != 0:
            raise ClusterJoiningError('Couldn\'t join cluster:\n%s' %
                                      result[2].content.decode())
Пример #4
0
def add_nodes(qty, template, node_type, config, client, org, vdc, vapp, body):
    if qty < 1:
        return None
    specs = []
    catalog_item = org.get_catalog_item(config['broker']['catalog'],
                                        template['catalog_item'])
    source_vapp = VApp(client, href=catalog_item.Entity.get('href'))
    source_vm = source_vapp.get_all_vms()[0].get('name')
    storage_profile = None
    if 'storage_profile' in body and body['storage_profile'] is not None:
        storage_profile = vdc.get_storage_profile(body['storage_profile'])
    cust_script_init = \
"""#!/usr/bin/env bash
if [ x$1=x"postcustomization" ];
then
""" # NOQA
    cust_script_common = ''
    cust_script_end = \
"""
fi
"""  # NOQA
    if 'ssh_key' in body and body['ssh_key'] is not None:
        cust_script_common += \
"""
mkdir -p /root/.ssh
echo '{ssh_key}' >> /root/.ssh/authorized_keys
chmod -R go-rwx /root/.ssh
""".format(ssh_key=body['ssh_key'])  # NOQA

    if cust_script_common is '':
        cust_script = None
    else:
        cust_script = cust_script_init + cust_script_common + cust_script_end
    for n in range(qty):
        name = None
        while True:
            name = '%s-%s' % (node_type, ''.join(
                random.choices(string.ascii_lowercase + string.digits, k=4)))
            try:
                vapp.get_vm(name)
            except Exception:
                break
        spec = {
            'source_vm_name': source_vm,
            'vapp': source_vapp.resource,
            'target_vm_name': name,
            'hostname': name,
            'network': body['network'],
            'ip_allocation_mode': 'pool'
        }
        if cust_script is not None:
            spec['cust_script'] = cust_script
        if storage_profile is not None:
            spec['storage_profile'] = storage_profile
        specs.append(spec)
    if ('cpu' in body and body['cpu'] is not None) or \
       ('memory' in body and body['memory'] is not None):
        reconfigure_hw = True
    else:
        reconfigure_hw = False
    task = vapp.add_vms(specs, power_on=not reconfigure_hw)
    # TODO(get details of the exception like not enough resources avail)
    client.get_task_monitor().wait_for_status(task)
    if reconfigure_hw:
        vapp.reload()
        for spec in specs:
            vm_resource = vapp.get_vm(spec['target_vm_name'])
            if 'cpu' in body and body['cpu'] is not None:
                vm = VM(client, resource=vm_resource)
                task = vm.modify_cpu(body['cpu'])
                client.get_task_monitor().wait_for_status(task)
            if 'memory' in body and body['memory'] is not None:
                vm = VM(client, resource=vm_resource)
                task = vm.modify_memory(body['memory'])
                client.get_task_monitor().wait_for_status(task)
            vm = VM(client, resource=vm_resource)
            task = vm.power_on()
            client.get_task_monitor().wait_for_status(task)
    password = source_vapp.get_admin_password(source_vm)
    vapp.reload()
    for spec in specs:
        vm_resource = vapp.get_vm(spec['target_vm_name'])
        command = '/bin/echo "root:{password}" | chpasswd'.format(
            password=template['admin_password'])
        nodes = [vm_resource]
        execute_script_in_nodes(config,
                                vapp,
                                password,
                                command,
                                nodes,
                                check_tools=True,
                                wait=False)
        if node_type == TYPE_NFS:
            LOGGER.debug('Enabling NFS server on %s' % spec['target_vm_name'])
            script = get_data_file('nfsd-%s.sh' % template['name'])
            execute_script_in_nodes(config, vapp, template['admin_password'],
                                    script, nodes)
    return {'task': task, 'specs': specs}
Пример #5
0
def test_0070_install_update(config, blank_cust_scripts, unregister_cse):
    """Tests installation option: '--update'.

    Tests that installation:
    - registers cse (when answering yes to prompt),
    - creates all templates correctly,
    - customizes temp vapps correctly.

    command: cse install --config cse_test_config.yaml
        --ssh-key ~/.ssh/id_rsa.pub --update --no-capture
    required files: cse_test_config.yaml, ~/.ssh/id_rsa.pub,
        ubuntu/photon init/cust scripts
    expected: cse registered, ubuntu/photon ovas exist, temp vapps exist,
        templates exist.
    """
    env.prepare_customization_scripts()
    result = env.CLI_RUNNER.invoke(cli,
                                   ['install',
                                    '--config', env.ACTIVE_CONFIG_FILEPATH,
                                    '--ssh-key', env.SSH_KEY_FILEPATH,
                                    '--update',
                                    '--no-capture'],
                                   input='y\ny',
                                   catch_exceptions=False)
    assert result.exit_code == 0

    vdc = VDC(env.CLIENT, href=env.VDC_HREF)

    # check that cse was registered correctly
    is_cse_registered = env.is_cse_registered()
    assert is_cse_registered, \
        'CSE is not registered as an extension when it should be.'
    if is_cse_registered:
        assert env.is_cse_registration_valid(config['amqp']['routing_key'],
                                             config['amqp']['exchange']), \
            'CSE is registered as an extension, but the extension settings ' \
            'on vCD are not the same as config settings.'

    # ssh into vms to check for installed software
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    # check that ova files and temp vapps exist
    for template_config in config['broker']['templates']:
        assert env.catalog_item_exists(template_config['source_ova_name']), \
            'Source ova files do not exist when they should.'

        temp_vapp_name = template_config['temp_vapp']
        try:
            vapp_resource = vdc.get_vapp(temp_vapp_name)
        except EntityNotFoundException:
            assert False, 'vApp does not exist when it should (--no-capture)'

        vapp = VApp(env.CLIENT, resource=vapp_resource)
        ip = vapp.get_primary_ip(temp_vapp_name)
        try:
            ssh_client.connect(ip, username='******')
            # run different commands depending on OS
            if 'photon' in temp_vapp_name:
                script = utils.get_data_file(env.STATIC_PHOTON_CUST_SCRIPT)
                pattern = r'(kubernetes\S*)'
                packages = re.findall(pattern, script)
                stdin, stdout, stderr = ssh_client.exec_command("rpm -qa")
                installed = [line.strip('.x86_64\n') for line in stdout]
                for package in packages:
                    assert package in installed, \
                        f"{package} not found in Photon VM"
            elif 'ubuntu' in temp_vapp_name:
                script = utils.get_data_file(env.STATIC_UBUNTU_CUST_SCRIPT)
                pattern = r'((kubernetes|docker\S*|kubelet|kubeadm|kubectl)\S*=\S*)'  # noqa
                packages = [tup[0] for tup in re.findall(pattern, script)]
                cmd = "dpkg -l | grep '^ii' | awk '{print $2\"=\"$3}'"
                stdin, stdout, stderr = ssh_client.exec_command(cmd)
                installed = [line.strip() for line in stdout]
                for package in packages:
                    assert package in installed, \
                        f"{package} not found in Ubuntu VM"
        finally:
            ssh_client.close()
    def test_0070_install_update(self):
        """Tests installation option: '--update'.
        Tests that installation configures amqp (when answering yes to prompt),
        registers cse (when answering yes to prompt),
        creates all templates correctly,
        customizes temp vapps correctly.

        command: cse install --config cse_test_config.yaml
            --ssh-key ~/.ssh/id_rsa.pub --update --no-capture
        required files: cse_test_config.yaml, ~/.ssh/id_rsa.pub,
            ubuntu/photon init/cust scripts
        expected: cse registered, amqp configured, ubuntu/photon ovas exist,
            temp vapps exist, templates exist.
        """
        prepare_customization_scripts()
        result = self._runner.invoke(cli, [
            'install', '--config', ACTIVE_CONFIG_FILEPATH, '--ssh-key',
            self._ssh_key_filepath, '--update', '--no-capture'
        ],
                                     input='y\ny',
                                     catch_exceptions=False)
        assert result.exit_code == 0

        # reloads required due to inability to wait for catalog deletion.
        # vdc can't find vapp unless we reload
        self._org.reload()
        self._vdc.reload()

        # check that amqp was configured
        assert not diff_amqp_settings(self._amqp_service, self._config['amqp'])

        # check that cse was registered
        try:
            self._api_extension.get_extension(CSE_NAME,
                                              namespace=CSE_NAMESPACE)
        except MissingRecordException:
            print('CSE is not registered as an extension when it should be.')
            assert False

        # ssh into vms to check for installed software
        ssh_client = paramiko.SSHClient()
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # check that ova files and temp vapps exist
        for template_config in self._config['broker']['templates']:
            try:
                self._org.get_catalog_item(self._config['broker']['catalog'],
                                           template_config['source_ova_name'])
            except EntityNotFoundException:
                print('Source ova files do not exist when they should')
                assert False
            temp_vapp_name = template_config['temp_vapp']
            try:
                vapp_resource = self._vdc.get_vapp(temp_vapp_name)
            except EntityNotFoundException:
                print('vApp does not exist when it should (--no-capture)')
                assert False
            vapp = VApp(self._client, resource=vapp_resource)
            ip = vapp.get_primary_ip(temp_vapp_name)
            try:
                ssh_client.connect(ip, username='******')
                # run different commands depending on OS
                if 'photon' in temp_vapp_name:
                    script = get_data_file(STATIC_PHOTON_CUST_SCRIPT)
                    pattern = r'(kubernetes\S*)'
                    packages = re.findall(pattern, script)
                    stdin, stdout, stderr = ssh_client.exec_command("rpm -qa")
                    installed = [line.strip('.x86_64\n') for line in stdout]
                    for package in packages:
                        if package not in installed:
                            print(f"{package} not found in Photon VM")
                            assert False
                elif 'ubuntu' in temp_vapp_name:
                    script = get_data_file(STATIC_UBUNTU_CUST_SCRIPT)
                    pattern = r'((kubernetes|docker\S*|kubelet|kubeadm|kubectl)\S*=\S*)'  # noqa
                    packages = [tup[0] for tup in re.findall(pattern, script)]
                    cmd = "dpkg -l | grep '^ii' | awk '{print $2\"=\"$3}'"
                    stdin, stdout, stderr = ssh_client.exec_command(cmd)
                    installed = [line.strip() for line in stdout]
                    for package in packages:
                        if package not in installed:
                            print(f"{package} not found in Ubuntu VM")
                            assert False
            finally:
                ssh_client.close()