def _filter_unsupported_templates(self):
     """Remove template descriptors which is not supported."""
     # No need to filter templates if CSE is configured in legacy mode.
     if self.legacy_mode:
         msg = "Skipping filtering templates as CSE is being" \
               " executed in legacy mode"
         self.filtered_cookbook = self.unfiltered_cookbook
         self.logger.debug(msg)
         self.msg_update_callback.general(msg)
         return
     # Fetch current CSE version
     current_cse_version = server_utils.get_installed_cse_version()
     supported_templates = []
     for template_description in self.unfiltered_cookbook['templates']:
         # only include the template if the current CSE version
         # supports it
         # template is supported if current CSE version is between
         # min_cse_version and max_cse_version of the template
         template_supported_cse_versions = semantic_version.SimpleSpec(
             f">={template_description[RemoteTemplateKey.MIN_CSE_VERSION]},"
             f"<={template_description[RemoteTemplateKey.MAX_CSE_VERSION]}")
         msg = f"Template {template_description['name']}"
         if template_supported_cse_versions.match(current_cse_version):
             msg += " is supported"
             supported_templates.append(template_description)
         else:
             msg += " is not supported"
         msg += f" by CSE {current_cse_version}"
         self.logger.debug(msg)
         self.msg_update_callback.general(msg)
     self.filtered_cookbook = {'templates': supported_templates}
     msg = "Successfully filtered unsupported templates."
     self.logger.debug(msg)
     self.msg_update_callback.general(msg)
    def _filter_unsupported_templates(self):
        """Remove template descriptors which is not supported."""
        # No need to filter templates if CSE is configured in legacy mode.
        if self.legacy_mode:
            msg = "Skipping filtering templates as CSE is being" \
                  " executed in legacy mode"
            self.filtered_cookbook = self.unfiltered_cookbook
            self.logger.debug(msg)
            self.msg_update_callback.general(msg)
            return
        # Cookbook version 1.0 doesn't have supported version information.
        if self.cookbook_version < \
                RemoteTemplateCookbookVersion.Version2.value:
            msg = "Skipping filtering templates as cookbook version " \
                f"{self.cookbook_version} doesn't have supported " \
                "CSE version information."
            self.logger.debug(msg)
            self.msg_update_callback.general(msg)
            return
        # Fetch current CSE version
        current_cse_version = server_utils.get_installed_cse_version()
        supported_templates = []
        remote_template_key = server_utils.get_template_descriptor_keys(
            self.cookbook_version)  # noqa: E501
        for template_description in self.unfiltered_cookbook['templates']:
            # only include the template if the current CSE version
            # supports it
            # template is supported if current CSE version is between
            # min_cse_version and max_cse_version of the template
            template_supported_cse_versions = semantic_version.SimpleSpec(
                f">={template_description[remote_template_key.MIN_CSE_VERSION]},"  # noqa: E501
                f"<={template_description[remote_template_key.MAX_CSE_VERSION]}"
            )  # noqa: E501
            msg = f"Template {template_description['name']}"
            if template_supported_cse_versions.match(current_cse_version):
                msg += " is supported"
                supported_templates.append(template_description)
            else:
                msg += " is not supported"
            msg += f" by CSE {current_cse_version}"
            self.logger.debug(msg)
            self.msg_update_callback.general(msg)
        self.filtered_cookbook = self.unfiltered_cookbook
        # update templates list with only supported templates
        self.filtered_cookbook['templates'] = supported_templates

        msg = "Successfully filtered unsupported templates."
        self.logger.debug(msg)
        self.msg_update_callback.general(msg)
Example #3
0
def verify_version_compatibility(sysadmin_client: Client,
                                 target_vcd_api_version, is_mqtt_extension):
    cse_version = server_utils.get_installed_cse_version()
    ext_cse_version, ext_vcd_api_version = \
        configure_cse.parse_cse_extension_description(
            sysadmin_client, is_mqtt_extension)
    if cse_version == server_constants.UNKNOWN_CSE_VERSION or \
            ext_vcd_api_version == server_constants.UNKNOWN_VCD_API_VERSION:
        # version data doesn't exist, so CSE <= 2.6.1 was installed
        raise cse_exception.VersionCompatibilityError(
            "CSE and VCD API version data not found on VCD. "
            "Upgrade CSE to update version data.")

    version_error_msg = ''
    if cse_version > ext_cse_version:
        version_error_msg += \
            f"CSE Server version ({cse_version}) is higher than what was " \
            f"previously registered with VCD ({ext_cse_version}). " \
            f"Upgrade CSE to update CSE version on VCD."
    if cse_version < ext_cse_version:
        version_error_msg += \
            f"CSE Server version ({cse_version}) cannot be lower than what " \
            f"was previously registered with VCD ({ext_cse_version})."

    if target_vcd_api_version > ext_vcd_api_version:
        version_error_msg += \
            f"Target VCD API version ({target_vcd_api_version}) is higher " \
            f"than what was previously registered by CSE " \
            f"({ext_vcd_api_version}). Upgrade CSE to update " \
            f"registered VCD API version."
    if target_vcd_api_version < ext_vcd_api_version:
        version_error_msg += \
            f"Target VCD API version ({target_vcd_api_version}) cannot be " \
            f"lower than what was previously registered by " \
            f"CSE ({ext_vcd_api_version})."

    if version_error_msg:
        raise cse_exception.VersionCompatibilityError(version_error_msg)
Example #4
0
def verify_version_compatibility(sysadmin_client: Client,
                                 should_cse_run_in_legacy_mode: bool,
                                 is_mqtt_extension: bool):
    ext_description = configure_cse.get_extension_description(
        sysadmin_client, is_mqtt_extension)
    dikt = configure_cse.parse_cse_extension_description(ext_description)
    ext_cse_version = dikt[server_constants.CSE_VERSION_KEY]
    ext_in_legacy_mode = dikt[server_constants.LEGACY_MODE_KEY]
    ext_rde_in_use = dikt[server_constants.RDE_VERSION_IN_USE_KEY]

    # version data doesn't exist, so installed CSE is <= 2.6.1
    if ext_cse_version == server_constants.UNKNOWN_CSE_VERSION:
        raise cse_exception.VersionCompatibilityError(
            "CSE and VCD API version data not found on VCD. "
            "Please upgrade CSE and retry.")

    error_msg = ''
    cse_version = server_utils.get_installed_cse_version()
    # Trying to use newer version of CSE without running `cse upgrade`
    if cse_version > ext_cse_version:
        error_msg += \
            f"CSE Server version ({cse_version}) is higher than what was " \
            f"previously registered with VCD ({ext_cse_version}). " \
            "Please upgrade CSE and retry."
    # Trying to use an older version of CSE
    if cse_version < ext_cse_version:
        error_msg += \
            f"CSE Server version ({cse_version}) cannot be lower than what " \
            f"was previously registered with VCD ({ext_cse_version}). " \
            "Please use a newer version of CSE."

    # Trying to run a legacy CSE in non-legacy mode
    if not should_cse_run_in_legacy_mode and ext_in_legacy_mode:
        error_msg += \
            "Installed CSE is configured in legacy mode. Unable to run it " \
            "in non-legacy mode. Please use `cse upgrade` to configure " \
            "CSE to operate in non-legacy mode."

    # Trying to run a non legacy CSE in legacy mode
    if should_cse_run_in_legacy_mode and not ext_in_legacy_mode:
        error_msg += \
            "Installed CSE is configured in non-legacy mode. Unable to run " \
            "it in legacy mode."

    expected_runtime_rde_version = semantic_version.Version(
        server_utils.get_rde_version_in_use())  # noqa: E501
    if not ext_in_legacy_mode:
        # VCD downgrade?
        if ext_rde_in_use > expected_runtime_rde_version:
            error_msg += \
                "Installed CSE Runtime Defined Entity (RDE) version " \
                f"({ext_rde_in_use}) is higher than the expected RDE " \
                f"version ({expected_runtime_rde_version}). Please " \
                "upgrade VCD to proceed."

        # VCD got upgraded without `cse upgrade` being run.
        if ext_rde_in_use < expected_runtime_rde_version:
            error_msg += \
                "Installed CSE Runtime Defined Entity (RDE) version " \
                f"({ext_rde_in_use}) is lower than the expected RDE " \
                f"version ({expected_runtime_rde_version}). Please " \
                "use `cse upgrade` to upgrade CSE RDE version and " \
                "retry."

    if error_msg:
        raise cse_exception.VersionCompatibilityError(error_msg)
Example #5
0
def get_all_k8s_local_template_definition(
    client,
    catalog_name,
    org=None,
    org_name=None,
    legacy_mode=False,
    logger_debug=logger.NULL_LOGGER,
    msg_update_callback=utils.NullPrinter()):  # noqa: E501
    """Fetch all CSE k8s templates in a catalog.

    A CSE k8s template is a catalog item that has all the necessary metadata
    stamped onto it. If only partial metadata is present on a catalog item,
    that catalog item will be disqualified from the result.

    :param pyvcloud.vcd.Client client: A sys admin client to be used to
        retrieve metadata off the catalog items.
    :param str catalog_name: Name of the catalog where the template resides.
    :param pyvcloud.vcd.Org org: Org object which hosts the catalog.
    :param str org_name: Name of the org that is hosting the catalog. Can be
        provided in lieu of param org, however param org takes precedence.
    :param bool legacy_mode: True, if CSE is running in legacy mode
    :param logging.Logger logger_debug:
    :param utils.NullPrinter msg_update_callback:

    :return: list of dictionaries containing template data

    :rtype: list of dicts
    """
    if not org:
        org = get_org(client, org_name=org_name)
    catalog_item_names = [
        entry['name'] for entry in org.list_catalog_items(catalog_name)
    ]
    templates = []

    # Select the right Key enum based on legacy_mode flag
    localTemplateKey = LocalTemplateKey
    if legacy_mode:
        # if template is loaded in legacy mode, make sure to avoid the keys
        # min_cse_version and max_cse_version
        localTemplateKey = LegacyLocalTemplateKey

    for item_name in catalog_item_names:
        md = org.get_all_metadata_from_catalog_item(catalog_name=catalog_name,
                                                    item_name=item_name)
        metadata_dict = metadata_to_dict(md)

        # if catalog item doesn't have all the required metadata keys,
        # CSE should not recognize it as a template
        expected_metadata_keys = \
            set([entry.value for entry in localTemplateKey])
        missing_metadata_keys = expected_metadata_keys - metadata_dict.keys()
        num_missing_metadata_keys = len(missing_metadata_keys)
        if num_missing_metadata_keys == len(expected_metadata_keys):
            # This catalog item has no CSE related metadata, so skip it.
            continue
        if num_missing_metadata_keys > 0:
            # This catalog item has partial CSE metadata, so skip it but also
            # log relevant information.
            msg = f"Catalog item '{item_name}' missing " \
                  f"{num_missing_metadata_keys} metadata: " \
                  f"{missing_metadata_keys}"  # noqa: F841
            logger_debug.debug(msg)
            msg_update_callback.info(msg)
            continue

        if not legacy_mode:
            # Do not load the template in non-legacy_mode if
            # min_cse_version and max_cse_version are not present
            # in the metadata_dict
            curr_cse_version = server_utils.get_installed_cse_version()
            valid_cse_versions = semantic_version.SimpleSpec(
                f">={metadata_dict[localTemplateKey.MIN_CSE_VERSION]},"
                f"<={metadata_dict[localTemplateKey.MAX_CSE_VERSION]}")
            if not valid_cse_versions.match(curr_cse_version):
                template_name = \
                    metadata_dict.get(localTemplateKey.NAME, "Unknown")
                template_revision = \
                    metadata_dict.get(localTemplateKey.REVISION, "Unknown")
                msg = f"Template '{template_name}' at " \
                      f"revision '{template_revision}' exists but is " \
                      f"not valid for CSE {curr_cse_version}"
                logger_debug.debug(msg)
                msg_update_callback.info(msg)
                continue

        # non-string metadata is written to the dictionary as a string
        # when 'upgrade_from' metadata is empty, vcd returns it as: "['']"
        # when 'upgrade_from' metadata is not empty, vcd returns it as an array
        # coerce "['']" to the more usable empty array []
        if isinstance(metadata_dict[localTemplateKey.UPGRADE_FROM], str):
            metadata_dict[localTemplateKey.UPGRADE_FROM] = \
                ast.literal_eval(metadata_dict[localTemplateKey.UPGRADE_FROM])
        if metadata_dict[localTemplateKey.UPGRADE_FROM] == ['']:
            metadata_dict[localTemplateKey.UPGRADE_FROM] = []

        templates.append(metadata_dict)

    return templates