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
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())
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())
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}
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()