def cluster_create(request_data, request_context: ctx.RequestContext):
    """Request handler for cluster create operation.

    Required data: org_name, ovdc_name, cluster_name

    (data validation handled in broker)

    :return: Dict
    """
    _raise_error_if_pks_not_enabled()
    required = [RequestKey.CLUSTER_NAME]
    req_utils.validate_payload(request_data, required)

    cluster_name = request_data[RequestKey.CLUSTER_NAME]
    request_data['is_org_admin_search'] = True

    try:
        _get_cluster_and_broker(request_data, request_context, telemetry=False)
        raise ClusterAlreadyExistsError(f"Cluster {cluster_name} "
                                        f"already exists.")
    except ClusterNotFoundError:
        pass

    k8s_metadata = \
        ovdc_utils.get_ovdc_k8s_provider_metadata(
            request_context.sysadmin_client,
            org_name=request_data[RequestKey.ORG_NAME],
            ovdc_name=request_data[RequestKey.OVDC_NAME],
            include_credentials=True,
            include_nsxt_info=True)
    broker = _get_broker_from_k8s_metadata(k8s_metadata, request_context)
    request_data[RequestKey.PKS_PLAN_NAME] = k8s_metadata[PKS_PLANS_KEY][0]
    request_data[RequestKey.PKS_EXT_HOST] = \
        f"{cluster_name}.{k8s_metadata[PKS_CLUSTER_DOMAIN_KEY]}"
    return broker.create_cluster(data=request_data)
def get_cluster_info(request_data, tenant_auth_token):
    """Get cluster details directly from cloud provider.

    Logic of the method is as follows.

    If 'ovdc' is present in the cluster spec,
        choose the right broker (by identifying the k8s provider
        (vcd|pks) defined for that ovdc) to do get_cluster operation.
    else
        Invoke set of all (vCD/PKS) brokers in the org to find the cluster

    :return: a tuple of cluster information as dictionary and the broker
        instance used to find the cluster information.

    :rtype: tuple
    """
    required = [RequestKey.CLUSTER_NAME]
    req_utils.validate_payload(request_data, required)

    org_name = request_data.get(RequestKey.ORG_NAME)
    ovdc_name = request_data.get(RequestKey.OVDC_NAME)

    if ovdc_name is not None and org_name is not None:
        k8s_metadata = \
            ovdc_utils.get_ovdc_k8s_provider_metadata(org_name=org_name,
                                                      ovdc_name=ovdc_name,
                                                      include_credentials=True,
                                                      include_nsxt_info=True)
        broker = get_broker_from_k8s_metadata(k8s_metadata, tenant_auth_token)
        return broker.get_cluster_info(request_data), broker

    return get_cluster_and_broker(request_data, tenant_auth_token)
def _get_cluster_info(request_data, request_context, **kwargs):
    """Get cluster details directly from cloud provider.

    Logic of the method is as follows.

    If 'ovdc' is present in the cluster spec,
        choose the right PKS broker to do get_cluster operation.
    else
        Invoke set of all PKS brokers in the org to find the cluster

    :return: a tuple of cluster information as dictionary and the broker
        instance used to find the cluster information.

    :rtype: tuple
    """
    required = [RequestKey.CLUSTER_NAME]
    req_utils.validate_payload(request_data, required)

    org_name = request_data.get(RequestKey.ORG_NAME)
    ovdc_name = request_data.get(RequestKey.OVDC_NAME)

    if ovdc_name is not None and org_name is not None:
        k8s_metadata = \
            ovdc_utils.get_ovdc_k8s_provider_metadata(request_context.sysadmin_client,  # noqa: E501
                                                      org_name=org_name,
                                                      ovdc_name=ovdc_name,
                                                      include_credentials=True,
                                                      include_nsxt_info=True)
        broker = _get_broker_from_k8s_metadata(k8s_metadata, request_context)
        return broker.get_cluster_info(data=request_data, **kwargs), broker

    return _get_cluster_and_broker(request_data, request_context, **kwargs)
def create_pks_context_for_all_accounts_in_org(
        request_context: ctx.RequestContext):  # noqa: E501
    """Create PKS context for accounts in a given Org.

    If user is Sysadmin
        Creates PKS contexts for all PKS accounts defined in the entire
        system.
    else
        Creates PKS contexts for all PKS accounts assigned to the org.
        However if separate service accounts for each org hasn't been
        configued by admin via pks.yaml, then PKS accounts of the PKS
        server corresponding to the vCenters powering the individual
        orgVDC of the org will be picked up for creating the PKS contexts.

    :return: list of dict, where each dictionary is a PKS context

    :rtype: list
    """
    pks_cache = utils.get_pks_cache()
    if pks_cache is None:
        return []

    if request_context.client.is_sysadmin():
        all_pks_account_info = pks_cache.get_all_pks_account_info_in_system()
        pks_ctx_list = [
            ovdc_utils.construct_pks_context(pks_account_info,
                                             credentials_required=True)
            for pks_account_info in all_pks_account_info
        ]  # noqa: E501
        return pks_ctx_list

    if pks_cache.do_orgs_have_exclusive_pks_account():
        pks_account_infos = pks_cache.get_exclusive_pks_accounts_info_for_org(
            request_context.user.org_name)  # noqa: E501
        pks_ctx_list = [
            ovdc_utils.construct_pks_context(pks_account_info,
                                             credentials_required=True)
            for pks_account_info in pks_account_infos
        ]  # noqa: E501
        return pks_ctx_list

    org_resource = request_context.client.get_org()
    org = Org(request_context.client, resource=org_resource)
    vdc_names = [vdc['name'] for vdc in org.list_vdcs()]
    # Constructing dict instead of list to avoid duplicates
    # TODO() figure out a way to add pks contexts to a set directly
    pks_ctx_dict = {}
    for vdc_name in vdc_names:
        # this is a full blown pks_account_info + pvdc_info +
        # compute_profile_name dictionary
        k8s_metadata = ovdc_utils.get_ovdc_k8s_provider_metadata(
            request_context.sysadmin_client,
            ovdc_name=vdc_name,
            org_name=request_context.user.org_name,
            include_credentials=True)
        if k8s_metadata[K8S_PROVIDER_KEY] == K8sProvider.PKS:
            pks_ctx_dict[k8s_metadata['vc']] = k8s_metadata

    return list(pks_ctx_dict.values())
def ovdc_info(request_data, tenant_auth_token):
    """Request handler for ovdc info operation.

    Required data: org_name, ovdc_name

    :return: Dictionary with org VDC k8s provider metadata.
    """
    required = [RequestKey.OVDC_ID]
    req_utils.validate_payload(request_data, required)

    return ovdc_utils.get_ovdc_k8s_provider_metadata(
        ovdc_id=request_data[RequestKey.OVDC_ID])
Ejemplo n.º 6
0
def ovdc_info(request_data, tenant_auth_token):
    """Request handler for ovdc info operation.

    Required data: org_name, ovdc_name

    :return: Dictionary with org VDC k8s provider metadata.
    """
    required = [RequestKey.OVDC_ID]
    utils.ensure_keys_in_dict(required, request_data, dict_name='data')

    return ovdc_utils.get_ovdc_k8s_provider_metadata(
        ovdc_id=request_data[RequestKey.OVDC_ID])
def cluster_create(request_data, tenant_auth_token):
    """Request handler for cluster create operation.

    Required data: org_name, ovdc_name, cluster_name
    Conditional data and default values:
        if k8s_provider is 'native':
            network_name, num_nodes=2, num_cpu=None, mb_memory=None,
            storage_profile_name=None, template_name=default,
            template_revision=default, ssh_key=None, enable_nfs=False,
            rollback=True

    (data validation handled in brokers)

    :return: Dict
    """
    required = [
        RequestKey.CLUSTER_NAME
    ]
    req_utils.validate_payload(request_data, required)

    cluster_name = request_data[RequestKey.CLUSTER_NAME]
    # TODO HACK 'is_org_admin_search' is used here to prevent users from
    # creating clusters with the same name, including clusters in PKS
    # True means that the cluster list is filtered by the org name of
    # the logged-in user to check that there are no duplicate clusters
    request_data['is_org_admin_search'] = True

    try:
        broker_manager.get_cluster_and_broker(request_data, tenant_auth_token)
        raise ClusterAlreadyExistsError(f"Cluster {cluster_name} "
                                        f"already exists.")
    except ClusterNotFoundError:
        pass

    k8s_metadata = \
        ovdc_utils.get_ovdc_k8s_provider_metadata(
            org_name=request_data[RequestKey.ORG_NAME],
            ovdc_name=request_data[RequestKey.OVDC_NAME],
            include_credentials=True,
            include_nsxt_info=True)
    if k8s_metadata.get(K8S_PROVIDER_KEY) == K8sProvider.PKS:
        request_data[RequestKey.PKS_PLAN_NAME] = k8s_metadata[PKS_PLANS_KEY][0]
        request_data[RequestKey.PKS_EXT_HOST] = \
            f"{cluster_name}.{k8s_metadata[PKS_CLUSTER_DOMAIN_KEY]}"
    broker = broker_manager.get_broker_from_k8s_metadata(k8s_metadata,
                                                         tenant_auth_token)
    return broker.create_cluster(request_data)
def ovdc_info(request_data, op_ctx: ctx.OperationContext):
    """Request handler for ovdc info operation.

    Required data: org_name, ovdc_name

    :return: Dictionary with org VDC k8s provider metadata.
    """
    required = [RequestKey.OVDC_ID]
    req_utils.validate_payload(request_data, required)

    # Record telemetry data
    cse_params = copy.deepcopy(request_data)
    record_user_action_details(cse_operation=CseOperation.OVDC_INFO,
                               cse_params=cse_params)

    return ovdc_utils.get_ovdc_k8s_provider_metadata(
        op_ctx.sysadmin_client, ovdc_id=request_data[RequestKey.OVDC_ID])
def ovdc_info(request_data, tenant_auth_token, is_jwt_token):
    """Request handler for ovdc info operation.

    Required data: org_name, ovdc_name

    :return: Dictionary with org VDC k8s provider metadata.
    """
    required = [
        RequestKey.OVDC_ID
    ]
    req_utils.validate_payload(request_data, required)

    # Record telemetry data
    cse_params = copy.deepcopy(request_data)
    record_user_action_details(cse_operation=CseOperation.OVDC_INFO, cse_params=cse_params)  # noqa: E501

    return ovdc_utils.get_ovdc_k8s_provider_metadata(
        ovdc_id=request_data[RequestKey.OVDC_ID])
def ovdc_update(request_data, op_ctx: ctx.OperationContext):
    """Request handler for ovdc enable, disable operations.

    Required data: org_name, ovdc_name, k8s_provider
    Conditional data:
        if k8s_provider is 'ent-pks': pks_plan_name, pks_cluster_domain

    :return: Dictionary with org VDC update task href.
    """
    # TODO the data flow here should be better understood.
    # org_name and ovdc_name seem redundant if we already have ovdc_id
    required = [
        RequestKey.ORG_NAME, RequestKey.OVDC_NAME, RequestKey.K8S_PROVIDER,
        RequestKey.OVDC_ID
    ]
    validated_data = request_data
    req_utils.validate_payload(validated_data, required)

    k8s_provider = validated_data[RequestKey.K8S_PROVIDER]
    k8s_provider_info = {K8S_PROVIDER_KEY: k8s_provider}

    # Record the telemetry data
    cse_params = copy.deepcopy(validated_data)
    cse_operation = CseOperation.OVDC_DISABLE if k8s_provider == K8sProvider.NONE else CseOperation.OVDC_ENABLE  # noqa: E501
    record_user_action_details(cse_operation=cse_operation,
                               cse_params=cse_params)  # noqa: E501

    try:
        if k8s_provider == K8sProvider.PKS:
            if not utils.is_pks_enabled():
                raise e.CseServerError('CSE server is not '
                                       'configured to work with PKS.')
            required = [
                RequestKey.PKS_PLAN_NAME, RequestKey.PKS_CLUSTER_DOMAIN
            ]
            req_utils.validate_payload(validated_data, required)

            # Check if target ovdc is not already enabled for other non PKS k8 providers # noqa: E501
            ovdc_metadata = ovdc_utils.get_ovdc_k8s_provider_metadata(
                op_ctx.sysadmin_client,
                ovdc_id=validated_data[RequestKey.OVDC_ID])
            ovdc_k8_provider = ovdc_metadata.get(K8S_PROVIDER_KEY)
            if ovdc_k8_provider != K8sProvider.NONE and \
                    ovdc_k8_provider != k8s_provider:
                raise e.CseServerError(
                    "Ovdc already enabled for different K8 provider"
                )  # noqa: E501

            k8s_provider_info = ovdc_utils.construct_k8s_metadata_from_pks_cache(  # noqa: E501
                op_ctx.sysadmin_client,
                ovdc_id=validated_data[RequestKey.OVDC_ID],
                org_name=validated_data[RequestKey.ORG_NAME],
                pks_plans=validated_data[RequestKey.PKS_PLAN_NAME],
                pks_cluster_domain=validated_data[
                    RequestKey.PKS_CLUSTER_DOMAIN],  # noqa: E501
                k8s_provider=k8s_provider)
            ovdc_utils.create_pks_compute_profile(validated_data, op_ctx,
                                                  k8s_provider_info)

        task = ovdc_utils.update_ovdc_k8s_provider_metadata(
            op_ctx.sysadmin_client,
            validated_data[RequestKey.OVDC_ID],
            k8s_provider_data=k8s_provider_info,
            k8s_provider=k8s_provider)

        # Telemetry - Record successful enabling/disabling of ovdc
        record_user_action(cse_operation, status=OperationStatus.SUCCESS)

        return {'task_href': task.get('href')}
    except Exception as err:
        # Telemetry - Record failed enabling/disabling of ovdc
        record_user_action(cse_operation, status=OperationStatus.FAILED)
        raise err
def ovdc_list(request_data, op_ctx: ctx.OperationContext):
    """Request handler for ovdc list operation.

    :return: List of dictionaries with org VDC k8s provider metadata.
    """
    defaults = {RequestKey.LIST_PKS_PLANS: False}
    validated_data = {**defaults, **request_data}

    list_pks_plans = utils.str_to_bool(
        validated_data[RequestKey.LIST_PKS_PLANS])  # noqa: E501

    # Record telemetry data
    cse_params = copy.deepcopy(validated_data)
    cse_params[RequestKey.LIST_PKS_PLANS] = list_pks_plans
    record_user_action_details(cse_operation=CseOperation.OVDC_LIST,
                               cse_params=cse_params)

    if list_pks_plans and not op_ctx.client.is_sysadmin():
        raise e.UnauthorizedRequestError(
            'Operation denied. Enterprise PKS plans visible only '
            'to System Administrators.')

    # Ideally this should be extracted out to ovdc_utils, but the mandatory
    # usage of sysadmin client along with a potentially non-sysadmin client
    # means that the function signature require both tenant client and
    # sysadmin client, which is very awkward
    if op_ctx.client.is_sysadmin():
        org_resource_list = op_ctx.client.get_org_list()
    else:
        org_resource_list = list(op_ctx.client.get_org())
    ovdcs = []
    for org_resource in org_resource_list:
        org = vcd_org.Org(op_ctx.client, resource=org_resource)
        for vdc_sparse in org.list_vdcs():
            ovdc_name = vdc_sparse['name']
            org_name = org.get_name()

            k8s_metadata = ovdc_utils.get_ovdc_k8s_provider_metadata(
                op_ctx.sysadmin_client, ovdc_name=ovdc_name, org_name=org_name)
            k8s_provider = k8s_metadata[K8S_PROVIDER_KEY]
            ovdc_dict = {
                'name': ovdc_name,
                'org': org_name,
                'k8s provider': k8s_provider
            }

            if list_pks_plans:
                pks_plans = ''
                pks_server = ''
                if k8s_provider == K8sProvider.PKS:
                    # vc name for vdc can only be found using typed query
                    q = op_ctx.client.get_typed_query(
                        vcd_client.ResourceType.ADMIN_ORG_VDC.value,
                        query_result_format=vcd_client.QueryResultFormat.
                        RECORDS,  # noqa: E501
                        qfilter=f"name=={ovdc_name};orgName=={org_name}")
                    # should only ever be one element in the generator
                    ovdc_records = list(q.execute())
                    if len(ovdc_records) == 0:
                        raise vcd_e.EntityNotFoundException(
                            f"Org VDC {ovdc_name} not found in org {org_name}")
                    ovdc_record = None
                    for record in ovdc_records:
                        ovdc_record = pyvcd_utils.to_dict(
                            record,
                            resource_type=vcd_client.ResourceType.
                            ADMIN_ORG_VDC.value)  # noqa: E501
                        break

                    vc_to_pks_plans_map = {}
                    pks_contexts = pksbroker_manager.create_pks_context_for_all_accounts_in_org(
                        op_ctx)  # noqa: E501

                    for pks_context in pks_contexts:
                        if pks_context['vc'] in vc_to_pks_plans_map:
                            continue
                        pks_broker = pksbroker.PksBroker(pks_context, op_ctx)
                        plans = pks_broker.list_plans()
                        plan_names = [plan.get('name') for plan in plans]
                        vc_to_pks_plans_map[pks_context['vc']] = \
                            [plan_names, pks_context['host']]

                    pks_plan_and_server_info = vc_to_pks_plans_map.get(
                        ovdc_record['vcName'], [])
                    if len(pks_plan_and_server_info) > 0:
                        pks_plans = pks_plan_and_server_info[0]
                        pks_server = pks_plan_and_server_info[1]

                ovdc_dict['pks api server'] = pks_server
                ovdc_dict['available pks plans'] = pks_plans

            ovdcs.append(ovdc_dict)

    return ovdcs