示例#1
0
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)
示例#2
0
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
示例#3
0
    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()
示例#5
0
 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()