def init_environment(config_filepath=BASE_CONFIG_FILEPATH): """Set up module variables according to config dict. :param str config_filepath: """ global AMQP_USERNAME, AMQP_PASSWORD, CLIENT, ORG_HREF, VDC_HREF, \ CATALOG_NAME, TEARDOWN_INSTALLATION, TEARDOWN_CLUSTERS, \ TEST_ALL_TEMPLATES config = testutils.yaml_to_dict(config_filepath) CLIENT = Client(config['vcd']['host'], api_version=config['vcd']['api_version'], verify_ssl_certs=config['vcd']['verify']) credentials = BasicLoginCredentials(config['vcd']['username'], utils.SYSTEM_ORG_NAME, config['vcd']['password']) CLIENT.set_credentials(credentials) org = utils.get_org(CLIENT, org_name=config['broker']['org']) vdc = utils.get_vdc(CLIENT, config['broker']['vdc'], org=org) ORG_HREF = org.href VDC_HREF = vdc.href CATALOG_NAME = config['broker']['catalog'] AMQP_USERNAME = config['amqp']['username'] AMQP_PASSWORD = config['amqp']['password'] test_config = config.get('test') if test_config is not None: TEARDOWN_INSTALLATION = test_config.get('teardown_installation', True) TEARDOWN_CLUSTERS = test_config.get('teardown_clusters', True) TEST_ALL_TEMPLATES = test_config.get('test_all_templates', False)
def init_environment(config_filepath=BASE_CONFIG_FILEPATH): """Set up module variables according to config dict. :param str config_filepath: """ global AMQP_USERNAME, AMQP_PASSWORD, CLIENT, ORG_HREF, VDC_HREF, \ CATALOG_NAME, DEV_MODE config = testutils.yaml_to_dict(config_filepath) CLIENT = Client(config['vcd']['host'], api_version=config['vcd']['api_version'], verify_ssl_certs=config['vcd']['verify']) credentials = BasicLoginCredentials(config['vcd']['username'], utils.SYSTEM_ORG_NAME, config['vcd']['password']) CLIENT.set_credentials(credentials) org = utils.get_org(CLIENT, org_name=config['broker']['org']) vdc = utils.get_vdc(CLIENT, config['broker']['vdc'], org=org) ORG_HREF = org.href VDC_HREF = vdc.href CATALOG_NAME = config['broker']['catalog'] AMQP_USERNAME = config['amqp']['username'] AMQP_PASSWORD = config['amqp']['password'] try: DEV_MODE = config['test']['developer_mode'] except KeyError: pass
def set_ovdc_container_provider_metadata(self, ovdc_name, ovdc_id=None, org_name=None, container_provider=None, pks_plans=''): """Set the container provider metadata of given ovdc. :param str ovdc_name: name of the ovdc :param str ovdc_id: unique id of the ovdc :param str org_name: specific org to use if @org is not given. If None, uses currently logged-in org from @client. :param str container_provider: name of container provider for which the ovdc is being enabled to deploy k8 clusters on. :param str pks_plans: PKS plans for deployment. If container provider is vCD or None, pks_plans are not applicable. """ metadata = dict() org = get_org(self.client, org_name=org_name) if ovdc_id is None: ovdc = get_vdc(self.client, ovdc_name, org=org, is_admin_operation=True) ovdc_id = utils.extract_id(ovdc.resource.get('id')) else: ovdc = self._get_vdc_by_id(ovdc_id) if container_provider != 'pks': LOGGER.debug(f'Remove metadata for ovdc:{ovdc_name}') self._remove_metadata(ovdc, self.__ovdc_metadata_keys) metadata['container_provider'] = container_provider or '' else: # Get resource pool resource_pool = f"{ovdc.name} ({ovdc_id})" # Get pvdc and pks information from pvdc cache org_name = org.resource.get('name') pvdc_element = ovdc.resource.ProviderVdcReference pvdc_id = pvdc_element.get('id') pvdc_info = self.pvdc_cache.get_pvdc_info(pvdc_id) pks_info = self.pvdc_cache.get_pks_info(org_name, pvdc_info['vc']) # construct ovdc metadata metadata['name'] = pvdc_info['name'] metadata['vc'] = pvdc_info['vc'] metadata['rp_path'] = ','.join(f'{rp_path}/{resource_pool}' for rp_path in pvdc_info['rp_path']) metadata['host'] = pks_info['host'] metadata['port'] = pks_info['port'] metadata['uaac_port'] = pks_info['uaac_port'] metadata['pks_plans'] = pks_plans or '' metadata['container_provider'] = container_provider pks_compute_profile_name = f"{org_name}-{ovdc_name}-{ovdc_id}" metadata['pks_compute_profile_name'] = pks_compute_profile_name # set ovdc metadata into Vcd LOGGER.debug(f"Setting below metadata on ovdc {ovdc_name}:{metadata}") return ovdc.set_multiple_metadata(metadata, MetadataDomain.SYSTEM, MetadataVisibility.PRIVATE)
def setUpClass(cls): """Runs once for this class, before all test methods. Tasks: - Initialize client, config, and other attributes. - Restore VCD AMQP settings to defaults. - Delete any pre-existing CSE entities. """ cls._config = yaml_to_dict(BASE_CONFIG_FILEPATH) cls._client = Client(cls._config['vcd']['host'], api_version=cls._config['vcd']['api_version'], verify_ssl_certs=cls._config['vcd']['verify']) credentials = BasicLoginCredentials(cls._config['vcd']['username'], SYSTEM_ORG_NAME, cls._config['vcd']['password']) cls._client.set_credentials(credentials) assert cls._client is not None cls._org = get_org(cls._client, org_name=cls._config['broker']['org']) assert cls._org is not None cls._vdc = get_vdc(cls._client, cls._config['broker']['vdc'], org=cls._org) assert cls._vdc is not None cls._api_extension = APIExtension(cls._client) assert cls._api_extension is not None cls._amqp_service = AmqpService(cls._client) assert cls._amqp_service is not None cls._runner = CliRunner() assert cls._runner is not None cls._ssh_key_filepath = f"{Path.home() / '.ssh' / 'id_rsa.pub'}" configure_vcd_amqp(cls._client, 'vcdext', cls._config['amqp']['host'], cls._config['amqp']['port'], 'vcd', cls._config['amqp']['ssl_accept_all'], cls._config['amqp']['ssl'], '/', cls._config['amqp']['username'], cls._config['amqp']['password'], quiet=True) cls._default_amqp_settings = to_dict(cls._amqp_service.get_settings()) assert cls._default_amqp_settings is not None cls._amqp_username = cls._config['amqp']['username'] assert cls._amqp_username is not None cls._amqp_password = cls._config['amqp']['password'] assert cls._amqp_password is not None CSEServerInstallationTest.delete_cse_entities()
def get_ovdc(self, ovdc_name=None, ovdc_id=None, org_name=None): if ovdc_id is None: org = get_org(self.client, org_name=org_name) return get_vdc(self.client, ovdc_name, org=org, is_admin_operation=True) else: return get_vdc_by_id(self.client, ovdc_id)
def capture_vapp_to_template(ctx, vapp, catalog_name, catalog_item_name, desc='', power_on=False, org=None, org_name=None): """Shutdown and capture existing VApp as a template in @catalog. VApp should have tools ready, or shutdown will fail, and VApp will be unavailable to be captured. :param click.core.Context ctx: click context object needed for stdout. :param pyvcloud.vcd.vapp.VApp vapp: :param str catalog_name: :param str catalog_item_name: catalog item name for the template. :param str desc: template description. :param bool power_on: if True, turns on VApp after capturing. :param pyvcloud.vcd.org.Org org: specific org to use. :param str org_name: specific org to use if @org is not given. If None, uses currently logged-in org from @vapp (vapp.client). :raises EntityNotFoundException: if the org could not be found. """ if org is None: org = get_org(vapp.client, org_name=org_name) catalog = org.get_catalog(catalog_name) try: task = vapp.shutdown() stdout(task, ctx=ctx) vapp.reload() except OperationNotSupportedException: pass task = org.capture_vapp(catalog, vapp.href, catalog_item_name, desc, customize_on_instantiate=True, overwrite=True) stdout(task, ctx=ctx) org.reload() if power_on: task = vapp.power_on() stdout(task, ctx=ctx) vapp.reload()
def create_template(ctx, client, config, template_config, update=False, no_capture=False, ssh_key=None, org=None, vdc=None): """Handles template creation phase during CSE installation. :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 section of @config. :param bool update: if True and templates already exist in vCD, overwrites existing templates. :param bool no_capture: if True, temporary vApp will not be captured or destroyed, so the user can ssh into the VM and debug. :param str ssh_key: public ssh key to place into the template vApp(s). :param pyvcloud.vcd.org.Org org: specific org to use. If None, uses org specified in @config. :param pyvcloud.vcd.vdc.VDC vdc: specific vdc to use. If None, uses vdc specified in @config. """ if org is None: org = get_org(client, org_name=config['broker']['org']) if vdc is None: vdc = get_vdc(client, config['broker']['vdc'], org=org) ctx.obj = {'client': client} catalog_name = config['broker']['catalog'] template_name = template_config['catalog_item'] vapp_name = template_config['temp_vapp'] ova_name = template_config['source_ova_name'] if not update and catalog_item_exists(org, catalog_name, template_name): msg = f"Found template '{template_name}' in catalog '{catalog_name}'" click.secho(msg, fg='green') LOGGER.info(msg) return # if update flag is set, delete existing template/ova file/temp vapp if update: msg = f"--update flag set. If template, source ova file, " \ f"and temporary vApp exist, they will be deleted" click.secho(msg, fg='yellow') LOGGER.info(msg) try: org.delete_catalog_item(catalog_name, template_name) wait_for_catalog_item_to_resolve(client, catalog_name, template_name, org=org) org.reload() msg = "Deleted vApp template" click.secho(msg, fg='green') LOGGER.info(msg) except EntityNotFoundException: pass try: org.delete_catalog_item(catalog_name, ova_name) wait_for_catalog_item_to_resolve(client, catalog_name, ova_name, org=org) org.reload() msg = "Deleted ova file" click.secho(msg, fg='green') LOGGER.info(msg) except EntityNotFoundException: pass try: task = vdc.delete_vapp(vapp_name, force=True) stdout(task, ctx=ctx) vdc.reload() msg = "Deleted temporary vApp" click.secho(msg, fg='green') LOGGER.info(msg) except EntityNotFoundException: pass # if needed, upload ova and create temp vapp msg = f"Creating template '{template_name}' in catalog '{catalog_name}'" click.secho(msg, fg='yellow') LOGGER.info(msg) temp_vapp_exists = True try: vapp = VApp(client, resource=vdc.get_vapp(vapp_name)) msg = f"Found vApp '{vapp_name}'" click.secho(msg, fg='green') LOGGER.info(msg) except EntityNotFoundException: temp_vapp_exists = False # flag is used to hide previous try/except error if an error occurs below if not temp_vapp_exists: if catalog_item_exists(org, catalog_name, ova_name): msg = f"Found ova file '{ova_name}' in catalog '{catalog_name}'" click.secho(msg, fg='green') LOGGER.info(msg) else: # download/upload files to catalog if necessary ova_filepath = f"cse_cache/{ova_name}" download_file(template_config['source_ova'], ova_filepath, sha256=template_config['sha256_ova'], logger=LOGGER) upload_ova_to_catalog(client, catalog_name, ova_filepath, org=org, logger=LOGGER) vapp = _create_temp_vapp(ctx, client, vdc, config, template_config, ssh_key) if no_capture: msg = f"'--no-capture' flag set. " \ f"Not capturing vApp '{vapp.name}' as a template" click.secho(msg, fg='yellow') LOGGER.info(msg) return # capture temp vapp as template msg = f"Creating template '{template_name}' from vApp '{vapp.name}'" click.secho(msg, fg='yellow') LOGGER.info(msg) capture_vapp_to_template(ctx, vapp, catalog_name, template_name, org=org, desc=template_config['description'], power_on=not template_config['cleanup']) msg = f"Created template '{template_name}' from vApp '{vapp_name}'" click.secho(msg, fg='green') LOGGER.info(msg) # delete temp vapp if template_config['cleanup']: msg = f"Deleting vApp '{vapp_name}'" click.secho(msg, fg='yellow') LOGGER.info(msg) task = vdc.delete_vapp(vapp_name, force=True) stdout(task, ctx=ctx) vdc.reload() msg = f"Deleted vApp '{vapp_name}'" click.secho(msg, fg='green') LOGGER.info(msg)
def install_cse(ctx, config_file_name='config.yaml', template_name='*', update=False, no_capture=False, ssh_key=None, amqp_install='prompt', ext_install='prompt'): """Handles logistics for CSE installation. Handles decision making for configuring AMQP exchange/settings, extension registration, catalog setup, and template creation. :param click.core.Context ctx: :param str config_file_name: config file name. :param str template_name: which templates to create/update. A value of '*' means to create/update all templates specified in config file. :param bool update: if True and templates already exist in vCD, overwrites existing templates. :param bool no_capture: if True, temporary vApp will not be captured or destroyed, so the user can ssh into and debug the VM. :param str ssh_key: public ssh key to place into template vApp(s). :param str amqp_install: 'prompt' asks the user if vCD AMQP should be configured. 'skip' does not configure vCD AMQP. 'config' configures vCD AMQP without asking the user. :param str ext_install: 'prompt' asks the user if CSE should be registered to vCD. 'skip' does not register CSE to vCD. 'config' registers CSE to vCD without asking the user. :raises AmqpError: if AMQP exchange could not be created. """ config = get_validated_config(config_file_name) configure_install_logger() msg = f"Installing CSE on vCloud Director using config file " \ f"'{config_file_name}'" click.secho(msg, fg='yellow') LOGGER.info(msg) client = None try: client = Client(config['vcd']['host'], api_version=config['vcd']['api_version'], verify_ssl_certs=config['vcd']['verify'], log_file=INSTALL_LOG_FILEPATH, log_headers=True, log_bodies=True) credentials = BasicLoginCredentials(config['vcd']['username'], SYSTEM_ORG_NAME, config['vcd']['password']) client.set_credentials(credentials) msg = f"Connected to vCD as system administrator: " \ f"{config['vcd']['host']}:{config['vcd']['port']}" click.secho(msg, fg='green') LOGGER.info(msg) # configure amqp amqp = config['amqp'] create_amqp_exchange(amqp['exchange'], amqp['host'], amqp['port'], amqp['vhost'], amqp['ssl'], amqp['username'], amqp['password']) if should_configure_amqp(client, amqp, amqp_install): configure_vcd_amqp(client, amqp['exchange'], amqp['host'], amqp['port'], amqp['prefix'], amqp['ssl_accept_all'], amqp['ssl'], amqp['vhost'], amqp['username'], amqp['password']) # register cse as extension to vCD if should_register_cse(client, ext_install): register_cse(client, amqp['routing_key'], amqp['exchange']) # set up cse catalog org = get_org(client, org_name=config['broker']['org']) create_and_share_catalog(org, config['broker']['catalog'], catalog_desc='CSE templates') # create, customize, capture VM templates for template in config['broker']['templates']: if template_name == '*' or template['name'] == template_name: create_template(ctx, client, config, template, update=update, no_capture=no_capture, ssh_key=ssh_key, org=org) except Exception: click.secho("CSE Installation Error. Check CSE install logs", fg='red') LOGGER.error("CSE Installation Error", exc_info=True) raise # TODO need installation relevant exceptions for rollback finally: if client is not None: client.logout()