Ejemplo n.º 1
0
def delete_rde(cluster_name, logger=NULL_LOGGER):
    """Delete defined entity with the given name.

    NOTE: RDE names are not unique. This function deletes all occurances
    """
    try:
        cloudapi_client: CloudApiClient = \
            pyvcloud_utils.get_cloudapi_client_from_vcd_client(
                CLIENT, logger_debug=logger, logger_wire=SERVER_CLOUDAPI_WIRE_LOGGER)  # noqa: E501
        from container_service_extension.rde.common.entity_service import DefEntityService  # noqa: E501
        entity_svc = DefEntityService(cloudapi_client)
        for cluster_rde in \
            entity_svc.list_all_native_rde_by_name_and_rde_version(
                cluster_name,
                rde_utils.get_runtime_rde_version_by_vcd_api_version(CLIENT.get_api_version())):  # noqa: E501
            entity_svc.resolve_entity(cluster_rde.id, cluster_rde.entityType)
            entity_svc.delete_entity(cluster_rde.id)
    except cse_exceptions.DefEntityServiceError as e:
        PYTEST_LOGGER.error(f"Failed to delete RDE: {e}")
        pass
Ejemplo n.º 2
0
def rde_exists(rde_name, logger=NULL_LOGGER):
    try:
        cloudapi_client: CloudApiClient = \
            pyvcloud_utils.get_cloudapi_client_from_vcd_client(
                CLIENT,
                logger_debug=logger,
                logger_wire=SERVER_CLOUDAPI_WIRE_LOGGER)
        # To avoid cyclic import
        from container_service_extension.rde.common.entity_service import \
            DefEntityService
        entity_svc = DefEntityService(cloudapi_client)
        rde_version = rde_utils.get_runtime_rde_version_by_vcd_api_version(
            CLIENT.get_api_version())
        entity = \
            entity_svc.get_native_rde_by_name_and_rde_version(
                rde_name, rde_version)
        return bool(entity)
    except Exception as e:
        logger.warning(f"Exception occured when checking if rde exists: {e}")
        return False
    def validate(self,
                 cloudapi_client: CloudApiClient,
                 entity_id: str = None,
                 entity: dict = None,
                 operation: BehaviorOperation = None) -> bool:  # noqa: E501
        """Validate the input request.

        This method performs
        1. Basic validation of the entity by simply casting the input entity
        dict to the model class dictated by the api_version specified in the
        request. This is usually performed for the "create" operation.
        2. Operation (create, update, delete) specific validation.
        - create: "entity" is the only required parameter.
        - update: both "entity" and "entity_id" are required parameters.
        - delete: "entity_id" is the only required parameter.
        - kubeconfig: "entity_id" is the only required parameter.

        :param cloudapi_client: cloud api client
        :param dict entity: dict form of the native entity to be validated
        :param entity_id: entity id to be validated
        :param BehaviorOperation operation: CSE operation key
        :return: is validation successful or failure
        :rtype: bool
        """
        if not entity_id and not entity:
            raise ValueError(
                'Either entity_id or entity is required to validate.'
            )  # noqa: E501
        entity_svc = DefEntityService(cloudapi_client=cloudapi_client)

        api_version: str = cloudapi_client.get_api_version()
        rde_version_introduced_at_api_version: str = rde_utils.get_rde_version_introduced_at_api_version(
            api_version)  # noqa: E501

        # TODO Reject the request if payload_version does not match with
        #  either rde_in_use (or) rde_version_introduced_at_api_version

        # Cast the entity to the model class based on the user-specified
        # api_version. This can be considered as a basic request validation.
        # Any operation specific validation is handled further down
        NativeEntityClass: AbstractNativeEntity = rde_factory. \
            get_rde_model(rde_version_introduced_at_api_version)
        input_entity = None
        if entity:
            try:
                input_entity: AbstractNativeEntity = NativeEntityClass.from_dict(
                    entity)  # noqa: E501
            except Exception as err:
                msg = f"Failed to parse request body: {err}"
                raise BadRequestError(msg)

        # Return True if the operation is not specified.
        if not operation:
            return True

        # TODO: validators for rest of the CSE operations in V36 will be
        #  implemented as and when v36/def_cluster_handler.py get other handler
        #  functions
        if operation == BehaviorOperation.UPDATE_CLUSTER:
            if not entity_id or not entity:
                raise ValueError(
                    'Both entity_id and entity are required to validate the Update operation.'
                )  # noqa: E501
            current_entity: AbstractNativeEntity = entity_svc.get_entity(
                entity_id).entity  # noqa: E501
            input_entity_spec: rde_2_0_0.ClusterSpec = input_entity.spec
            current_entity_status: rde_2_0_0.Status = current_entity.status
            current_entity_spec = \
                rde_utils.construct_cluster_spec_from_entity_status(
                    current_entity_status, rde_constants.RDEVersion.RDE_2_0_0.value)  # noqa: E501
            return validate_cluster_update_request_and_check_cluster_upgrade(
                input_entity_spec, current_entity_spec)

        # TODO check the reason why there was an unreachable raise statement
        raise NotImplementedError(f"Validator for {operation.name} not found")
    def validate(
            self,
            cloudapi_client: CloudApiClient,
            sysadmin_client: Client,
            entity_id: str = None,
            entity: dict = None,
            operation: BehaviorOperation = BehaviorOperation.CREATE_CLUSTER,
            **kwargs) -> bool:
        """Validate the input request.

        This method performs
        1. Basic validation of the entity by simply casting the input entity
        dict to the model class dictated by the api_version specified in the
        request. This is usually performed for the "create" operation.
        2. Operation (create, update, delete) specific validation.
        - create: "entity" is the only required parameter.
        - update: both "entity" and "entity_id" are required parameters.
        - delete: "entity_id" is the only required parameter.
        - kubeconfig: "entity_id" is the only required parameter.

        :param cloudapi_client: cloud api client
        :param sysadmin_client:
        :param dict entity: dict form of the native entity to be validated
        :param entity_id: entity id to be validated
        :param BehaviorOperation operation: CSE operation key
        :return: is validation successful or failure
        :rtype: bool
        """
        is_tkgm_cluster = kwargs.get('is_tkgm_cluster', False)
        if not entity_id and not entity:
            raise ValueError(
                'Either entity_id or entity is required to validate.'
            )  # noqa: E501
        entity_svc = DefEntityService(cloudapi_client=cloudapi_client)

        api_version: str = cloudapi_client.get_api_version()
        rde_version_introduced_at_api_version: str = rde_utils.get_rde_version_introduced_at_api_version(
            api_version)  # noqa: E501

        # TODO Reject the request if payload_version does not match with
        #  either rde_in_use (or) rde_version_introduced_at_api_version

        # Cast the entity to the model class based on the user-specified
        # api_version. This can be considered as a basic request validation.
        # Any operation specific validation is handled further down
        native_entity_class: AbstractNativeEntity = rde_factory. \
            get_rde_model(rde_version_introduced_at_api_version)
        input_entity = None
        if entity:
            try:
                input_entity: AbstractNativeEntity = native_entity_class.from_dict(
                    entity)  # noqa: E501
            except Exception as err:
                msg = f"Failed to parse request body: {err}"
                raise BadRequestError(msg)

        # Need to ensure that sizing class along with cpu/memory is not
        # present in the request
        if isinstance(input_entity, rde_2_1_0.NativeEntity):
            # cpu and mem are properties of only rde 2.0.0
            bad_request_msg = ""
            if input_entity.spec.topology.workers.sizing_class and \
                    (input_entity.spec.topology.workers.cpu or input_entity.spec.topology.workers.memory):  # noqa: E501
                bad_request_msg = "Cannot specify both sizing class and cpu/memory for Workers nodes."  # noqa: E501
            if input_entity.spec.topology.control_plane.sizing_class and (
                    input_entity.spec.topology.control_plane.cpu
                    or input_entity.spec.topology.control_plane.memory
            ):  # noqa: E501
                bad_request_msg = "Cannot specify both sizing class and cpu/memory for Control Plane nodes."  # noqa: E501
            if bad_request_msg:
                raise BadRequestError(bad_request_msg)
        # Return True if the operation is not specified.
        if operation == BehaviorOperation.CREATE_CLUSTER:
            return True

        # TODO: validators for rest of the CSE operations in V36 will be
        #  implemented as and when v36/def_cluster_handler.py get other handler
        #  functions
        if operation == BehaviorOperation.UPDATE_CLUSTER:
            if not entity_id or not entity:
                raise ValueError(
                    'Both entity_id and entity are required to validate the Update operation.'
                )  # noqa: E501
            current_entity: AbstractNativeEntity = entity_svc.get_entity(
                entity_id).entity  # noqa: E501
            input_entity_spec: rde_2_1_0.ClusterSpec = input_entity.spec
            current_entity_status: rde_2_1_0.Status = current_entity.status
            is_tkgm_with_default_sizing_in_control_plane = False
            is_tkgm_with_default_sizing_in_workers = False
            if is_tkgm_cluster:
                # NOTE: Since for TKGm cluster, if cluster is created without
                # a sizing class, default sizing class is assigned by VCD,
                # If we find the default sizing policy in the status section,
                # validate cpu/memory and sizing policy.
                # Also note that at this point in code, we are sure that only
                # one of sizing class or cpu/mem will be associated with
                # control plane and workers.
                vdc: VDC = get_vdc(
                    sysadmin_client,
                    vdc_name=current_entity_status.cloud_properties.
                    virtual_data_center_name,  # noqa: E501
                    org_name=current_entity_status.cloud_properties.org_name)
                vdc_resource = vdc.get_resource_admin()
                default_cp_name = vdc_resource.DefaultComputePolicy.get('name')
                control_plane_sizing_class = current_entity_status.nodes.control_plane.sizing_class  # noqa: E501
                is_tkgm_with_default_sizing_in_control_plane = \
                    (control_plane_sizing_class == default_cp_name)
                is_tkgm_with_default_sizing_in_workers = \
                    (len(current_entity_status.nodes.workers) > 0
                     and current_entity_status.nodes.workers[0].sizing_class == default_cp_name)  # noqa: E501
            current_entity_spec = \
                rde_utils.construct_cluster_spec_from_entity_status(
                    current_entity_status,
                    rde_constants.RDEVersion.RDE_2_1_0.value,
                    is_tkgm_with_default_sizing_in_control_plane=is_tkgm_with_default_sizing_in_control_plane,  # noqa: E501
                    is_tkgm_with_default_sizing_in_workers=is_tkgm_with_default_sizing_in_workers)  # noqa: E501
            return validate_cluster_update_request_and_check_cluster_upgrade(
                input_entity_spec, current_entity_spec, is_tkgm_cluster)

        # TODO check the reason why there was an unreachable raise statement
        raise NotImplementedError(f"Validator for {operation.name} not found")