def _get_cluster_info(request_data, op_ctx, **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(op_ctx.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, op_ctx) return broker.get_cluster_info(data=request_data, **kwargs), broker return _get_cluster_and_broker(request_data, op_ctx, **kwargs)
def create_pks_context_for_all_accounts_in_org( op_ctx: ctx.OperationContext): # 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 = server_utils.get_pks_cache() if pks_cache is None: return [] if op_ctx.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( op_ctx.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 = op_ctx.client.get_org() org = Org(op_ctx.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( op_ctx.sysadmin_client, ovdc_name=vdc_name, org_name=op_ctx.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 cluster_create(request_data, op_ctx: ctx.OperationContext): """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() data = req_utils.flatten_request_data(request_data, [RequestKey.INPUT_SPEC]) required = [RequestKey.CLUSTER_NAME] req_utils.validate_payload(data, required) cluster_name = data[RequestKey.CLUSTER_NAME] data['is_org_admin_search'] = True try: _get_cluster_and_broker(data, op_ctx, telemetry=False) raise ClusterAlreadyExistsError(f"Cluster {cluster_name} " f"already exists.") except ClusterNotFoundError: pass sysadmin_client_v33 = op_ctx.get_sysadmin_client( api_version=DEFAULT_API_VERSION) k8s_metadata = \ ovdc_utils.get_ovdc_k8s_provider_metadata( sysadmin_client_v33, org_name=data[RequestKey.ORG_NAME], ovdc_name=data[RequestKey.OVDC_NAME], include_credentials=True, include_nsxt_info=True) broker = _get_broker_from_k8s_metadata(k8s_metadata, op_ctx) data[RequestKey.PKS_PLAN_NAME] = k8s_metadata[PKS_PLANS_KEY][0] data[RequestKey.PKS_EXT_HOST] = \ f"{cluster_name}.{k8s_metadata[PKS_CLUSTER_DOMAIN_KEY]}" cluster = broker.create_cluster(data=data) # Record telemetry data telemetry_handler.record_user_action_details( cse_operation=CseOperation.PKS_CLUSTER_CREATE, cse_params=_get_telemetry_data(data, cluster)) return cluster
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) cse_params[PayloadKey. SOURCE_DESCRIPTION] = thread_local_data.get_thread_local_data( ThreadLocalData.USER_AGENT) # noqa: E501 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 _get_cse_ovdc_list(sysadmin_client: vcd_client.Client, org_vdcs: list) -> list: ovdcs = [] for ovdc in org_vdcs: ovdc_name = ovdc.get('name') org_name = ovdc.get('orgName') ovdc_id = vcd_utils.extract_id(ovdc.get('id')) # obtain the runtimes supported stored in # ovdc metadata k8s_metadata = ovdc_utils.get_ovdc_k8s_provider_metadata( sysadmin_client, ovdc_id=ovdc_id, ovdc_name=ovdc_name, org_name=org_name) k8s_provider = k8s_metadata[K8S_PROVIDER_KEY] ovdc_dict = { OvdcInfoKey.OVDC_NAME: ovdc_name, OvdcInfoKey.ORG_NAME: org_name, OvdcInfoKey.K8S_PROVIDER: k8s_provider } ovdcs.append(ovdc_dict) return ovdcs
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 data = req_utils.flatten_request_data( request_data, [RequestKey.INPUT_SPEC]) required = [ RequestKey.ORG_NAME, RequestKey.OVDC_NAME, RequestKey.K8S_PROVIDER, RequestKey.OVDC_ID ] validated_data = 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_params[PayloadKey.SOURCE_DESCRIPTION] = thread_local_data.get_thread_local_data(ThreadLocalData.USER_AGENT) # noqa: E501 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 sysadmin_client_v33 = \ op_ctx.get_sysadmin_client(api_version=DEFAULT_API_VERSION) try: if k8s_provider == K8sProvider.PKS: if not server_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( sysadmin_client_v33, 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 sysadmin_client_v33, 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( sysadmin_client_v33, 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: logger.SERVER_LOGGER.error(f"Error while updating OVDC: {str(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. :rtype: list """ # NOTE: response sent out by this handler should not be paginated data = req_utils.flatten_request_data( request_data, [RequestKey.QUERY_PARAMS]) defaults = { RequestKey.LIST_PKS_PLANS: False, } validated_data = {**defaults, **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 cse_params[PayloadKey.SOURCE_DESCRIPTION] = thread_local_data.get_thread_local_data(ThreadLocalData.USER_AGENT) # noqa: E501 record_user_action_details(cse_operation=CseOperation.OVDC_LIST, cse_params=cse_params) client_v33 = op_ctx.get_client(api_version=DEFAULT_API_VERSION) if list_pks_plans and not client_v33.is_sysadmin(): raise e.UnauthorizedRequestError( 'Operation denied. Enterprise PKS plans visible only ' 'to System Administrators.') ovdcs = [] org_vdcs = vcd_utils.get_all_ovdcs(client_v33) sysadmin_client_v33 = \ op_ctx.get_sysadmin_client(api_version=DEFAULT_API_VERSION) for ovdc in org_vdcs: ovdc_name = ovdc.get('name') org_name = ovdc.get('orgName') ovdc_id = vcd_utils.extract_id(ovdc.get('id')) k8s_metadata = ovdc_utils.get_ovdc_k8s_provider_metadata( sysadmin_client_v33, ovdc_id=ovdc_id, ovdc_name=ovdc_name, org_name=org_name) k8s_provider = k8s_metadata[K8S_PROVIDER_KEY] ovdc_dict = { OvdcInfoKey.OVDC_NAME: ovdc_name, OvdcInfoKey.ORG_NAME: org_name, OvdcInfoKey.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 qfilter = f"name=={urllib.parse.quote(ovdc_name)};" \ f"orgName=={urllib.parse.quote(org_name)}" q = client_v33.get_typed_query( vcd_client.ResourceType.ADMIN_ORG_VDC.value, query_result_format=vcd_client.QueryResultFormat.RECORDS, # noqa: E501 qfilter=qfilter) # 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[PKSOvdcInfoKey.PKS_API_SERVER] = pks_server ovdc_dict[PKSOvdcInfoKey.AVAILABLE_PKS_PLANS] = pks_plans ovdcs.append(ovdc_dict) return ovdcs
def org_vdc_list(request_data, op_ctx: ctx.OperationContext): """Request handler for ovdc list operation. :return: dictionary containing list of Org VDCs :rtype: dict """ # NOTE: Response sent out by this handler should be paginated data = req_utils.flatten_request_data(request_data, [RequestKey.QUERY_PARAMS]) defaults = { RequestKey.LIST_PKS_PLANS: False, PaginationKey.PAGE_NUMBER: CSE_PAGINATION_FIRST_PAGE_NUMBER, PaginationKey.PAGE_SIZE: CSE_PAGINATION_DEFAULT_PAGE_SIZE } validated_data = {**defaults, **data} page_number = int(validated_data[PaginationKey.PAGE_NUMBER]) page_size = int(validated_data[PaginationKey.PAGE_SIZE]) list_pks_plans = utils.str_to_bool( validated_data[RequestKey.LIST_PKS_PLANS]) # noqa: E501 # Record telemetry data # TODO: enhance telemetry to record the page number and page size data. cse_params = copy.deepcopy(validated_data) cse_params[RequestKey.LIST_PKS_PLANS] = list_pks_plans cse_params[PayloadKey. SOURCE_DESCRIPTION] = thread_local_data.get_thread_local_data( ThreadLocalData.USER_AGENT) # noqa: E501 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.') ovdcs = [] result = \ vcd_utils.get_ovdcs_by_page(op_ctx.client, page=page_number, page_size=page_size) org_vdcs = result[PaginationKey.VALUES] result_total = result[PaginationKey.RESULT_TOTAL] next_page_uri = result.get(PaginationKey.NEXT_PAGE_URI) prev_page_uri = result.get(PaginationKey.PREV_PAGE_URI) for ovdc in org_vdcs: ovdc_name = ovdc.get('name') org_name = ovdc.get('orgName') ovdc_id = vcd_utils.extract_id(ovdc.get('id')) k8s_metadata = ovdc_utils.get_ovdc_k8s_provider_metadata( op_ctx.sysadmin_client, ovdc_id=ovdc_id, ovdc_name=ovdc_name, org_name=org_name) k8s_provider = k8s_metadata[K8S_PROVIDER_KEY] ovdc_dict = { OvdcInfoKey.OVDC_NAME: ovdc_name, OvdcInfoKey.ORG_NAME: org_name, OvdcInfoKey.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 qfilter = f"name=={urllib.parse.quote(ovdc_name)};" \ f"orgName=={urllib.parse.quote(org_name)}" q = op_ctx.client.get_typed_query( vcd_client.ResourceType.ADMIN_ORG_VDC.value, query_result_format=vcd_client.QueryResultFormat. RECORDS, # noqa: E501 qfilter=qfilter) # 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[PKSOvdcInfoKey.PKS_API_SERVER] = pks_server ovdc_dict[PKSOvdcInfoKey.AVAILABLE_PKS_PLANS] = pks_plans ovdcs.append(ovdc_dict) api_path = CseServerOperationInfo.PKS_ORG_VDC_LIST.api_path_format next_page_uri = vcd_utils.create_cse_page_uri(op_ctx.client, api_path, vcd_uri=next_page_uri) prev_page_uri = vcd_utils.create_cse_page_uri(op_ctx.client, api_path, vcd_uri=prev_page_uri) return server_utils.construct_paginated_response( values=ovdcs, result_total=result_total, page_number=page_number, page_size=page_size, next_page_uri=next_page_uri, # noqa: E501 prev_page_uri=prev_page_uri) # noqa: E501