X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=models-interactions%2Fmodel-actors%2Factor.so%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fpolicy%2Fcontrolloop%2Factor%2Fso%2FSoOperation.java;h=d8404572a4fa9f797db253241e7cc32bbd6a3676;hb=938005505883cf7a636a8840e20e3dc8a0ad9176;hp=7f8a5c5c436c5c50b65f95bfe35eb4e1572dc265;hpb=8dd5c8fc0dc7a097f1a129d57920a73366b75790;p=policy%2Fmodels.git diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java index 7f8a5c5c4..d8404572a 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java @@ -2,7 +2,9 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020 Wipro Limited. + * Modifications Copyright (C) 2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,37 +24,30 @@ package org.onap.policy.controlloop.actor.so; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import lombok.Getter; import org.onap.aai.domain.yang.CloudRegion; import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ModelVer; import org.onap.aai.domain.yang.ServiceInstance; import org.onap.aai.domain.yang.Tenant; -import org.onap.policy.aai.AaiConstants; -import org.onap.policy.aai.AaiCqResponse; -import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; -import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType; import org.onap.policy.common.gson.GsonMessageBodyHandler; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.StandardCoderObject; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.OperationResult; import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; -import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; -import org.onap.policy.controlloop.policy.PolicyResult; -import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingConfig; import org.onap.policy.so.SoCloudConfiguration; import org.onap.policy.so.SoModelInfo; import org.onap.policy.so.SoRequest; @@ -61,18 +56,14 @@ import org.onap.policy.so.SoRequestParameters; import org.onap.policy.so.SoRequestStatus; import org.onap.policy.so.SoResponse; import org.onap.policy.so.util.SoLocalDateTimeTypeAdapter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * Superclass for SDNC Operators. Note: subclasses should invoke {@link #resetGetCount()} + * Superclass for SDNC Operators. Note: subclasses should invoke {@link #resetPollCount()} * each time they issue an HTTP request. */ public abstract class SoOperation extends HttpOperation { - private static final Logger logger = LoggerFactory.getLogger(SoOperation.class); private static final Coder coder = new SoCoder(); - public static final String PAYLOAD_KEY_VF_COUNT = "vfCount"; public static final String FAILED = "FAILED"; public static final String COMPLETE = "COMPLETE"; public static final int SO_RESPONSE_CODE = 999; @@ -81,140 +72,106 @@ public abstract class SoOperation extends HttpOperation { public static final String REQ_PARAM_NM = "requestParameters"; public static final String CONFIG_PARAM_NM = "configurationParameters"; - private final SoConfig config; - - // values extracted from the parameter Target + /* Values extracted from the parameter Target. These fields are required by any + subclasses that make use of prepareSoModelInfo(). + */ private final String modelCustomizationId; private final String modelInvariantId; private final String modelVersionId; + private final String modelName; + private final String modelVersion; + - private final String vfCountKey; /** - * Number of "get" requests issued so far, on the current operation attempt. + * Constructs the object. + * + * @param params operation parameters + * @param config configuration for this operation + * @param propertyNames names of properties required by this operation */ - @Getter - private int getCount; + protected SoOperation(ControlLoopOperationParams params, HttpPollingConfig config, List propertyNames) { + super(params, config, SoResponse.class, propertyNames); + this.modelCustomizationId = null; + this.modelInvariantId = null; + this.modelVersionId = null; + this.modelVersion = null; + this.modelName = null; + + verifyNotNull("Target information", params.getTargetType()); + } /** * Constructs the object. * * @param params operation parameters * @param config configuration for this operation + * @param propertyNames names of properties required by this operation + * @param targetEntityIds Target Entity information */ - public SoOperation(ControlLoopOperationParams params, HttpConfig config) { - super(params, config, SoResponse.class); - this.config = (SoConfig) config; + protected SoOperation(ControlLoopOperationParams params, HttpPollingConfig config, List propertyNames, + Map targetEntityIds) { + super(params, config, SoResponse.class, propertyNames); - verifyNotNull("Target information", params.getTarget()); + verifyNotNull("Target entity Ids information", targetEntityIds); - this.modelCustomizationId = params.getTarget().getModelCustomizationId(); - this.modelInvariantId = params.getTarget().getModelInvariantId(); - this.modelVersionId = params.getTarget().getModelVersionId(); + this.modelCustomizationId = targetEntityIds + .get(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_CUSTOMIZATION_ID); + this.modelInvariantId = targetEntityIds + .get(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_INVARIANT_ID); + this.modelVersionId = targetEntityIds + .get(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_VERSION_ID); + this.modelVersion = targetEntityIds + .get(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_VERSION); + this.modelName = targetEntityIds + .get(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_NAME); - vfCountKey = SoConstants.VF_COUNT_PREFIX + "[" + modelCustomizationId + "][" + modelInvariantId + "][" - + modelVersionId + "]"; + verifyNotNull("Target information", params.getTargetType()); } - /** - * Subclasses should invoke this before issuing their first HTTP request. - */ - protected void resetGetCount() { - getCount = 0; + @Override + protected void resetPollCount() { + super.resetPollCount(); setSubRequestId(null); } /** - * Validates that the parameters contain the required target information to extract - * the VF count from the custom query. + * Validates that the parameters contain the required target information to construct + * the request. */ protected void validateTarget() { - verifyNotNull("modelCustomizationId", modelCustomizationId); - verifyNotNull("modelInvariantId", modelInvariantId); - verifyNotNull("modelVersionId", modelVersionId); + verifyNotNull(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_CUSTOMIZATION_ID, modelCustomizationId); + verifyNotNull(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_INVARIANT_ID, modelInvariantId); + verifyNotNull(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_VERSION_ID, modelVersionId); } private void verifyNotNull(String type, Object value) { if (value == null) { - throw new IllegalArgumentException("missing " + type + " for guard payload"); + throw new IllegalArgumentException("missing Target." + type); } } - /** - * Starts the GUARD. - */ - @Override - protected CompletableFuture startPreprocessorAsync() { - return startGuardAsync(); - } - - /** - * Gets the VF Count. - * - * @return a future to cancel or await the VF Count - */ - @SuppressWarnings("unchecked") - protected CompletableFuture obtainVfCount() { - if (params.getContext().contains(vfCountKey)) { - // already have the VF count - return null; - } - - // need custom query from which to extract the VF count - ControlLoopOperationParams cqParams = params.toBuilder().actor(AaiConstants.ACTOR_NAME) - .operation(AaiCqResponse.OPERATION).payload(null).retry(null).timeoutSec(null).build(); - - // run Custom Query and then extract the VF count - return sequence(() -> params.getContext().obtain(AaiCqResponse.CONTEXT_KEY, cqParams), this::storeVfCount); - } - - /** - * Stores the VF count. - * - * @return {@code null} - */ - private CompletableFuture storeVfCount() { - if (!params.getContext().contains(vfCountKey)) { - AaiCqResponse cq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); - int vfcount = cq.getVfModuleCount(modelCustomizationId, modelInvariantId, modelVersionId); - - params.getContext().setProperty(vfCountKey, vfcount); - } - - return null; - } - protected int getVfCount() { - return params.getContext().getProperty(vfCountKey); + return getRequiredProperty(OperationProperties.DATA_VF_COUNT, "VF Count"); } protected void setVfCount(int vfCount) { - params.getContext().setProperty(vfCountKey, vfCount); + setProperty(OperationProperties.DATA_VF_COUNT, vfCount); } - /** - * If the response does not indicate that the request has been completed, then sleep a - * bit and issue a "get". - */ @Override - protected CompletableFuture postProcessResponse(OperationOutcome outcome, String url, - Response rawResponse, SoResponse response) { - - // see if the request has "completed", whether or not it was successful + protected Status detmStatus(Response rawResponse, SoResponse response) { if (rawResponse.getStatus() == 200) { String requestState = getRequestState(response); if (COMPLETE.equalsIgnoreCase(requestState)) { extractSubRequestId(response); - successfulCompletion(); - return CompletableFuture - .completedFuture(setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response)); + return Status.SUCCESS; } if (FAILED.equalsIgnoreCase(requestState)) { extractSubRequestId(response); - return CompletableFuture - .completedFuture(setOutcome(outcome, PolicyResult.FAILURE, rawResponse, response)); + return Status.FAILURE; } } @@ -225,18 +182,12 @@ public abstract class SoOperation extends HttpOperation { throw new IllegalArgumentException("missing request ID in response"); } - // see if the limit for the number of "gets" has been reached - if (getCount++ >= getMaxGets()) { - logger.warn("{}: execeeded 'get' limit {} for {}", getFullName(), getMaxGets(), params.getRequestId()); - setOutcome(outcome, PolicyResult.FAILURE_TIMEOUT); - outcome.setResponse(response); - outcome.setMessage(SO_RESPONSE_CODE + " " + outcome.getMessage()); - return CompletableFuture.completedFuture(outcome); - } + return Status.STILL_WAITING; + } - // sleep and then perform a "get" operation - Function> doGet = unused -> issueGet(outcome); - return sleep(getWaitMsGet(), TimeUnit.MILLISECONDS).thenComposeAsync(doGet); + @Override + protected String getPollingPath() { + return super.getPollingPath() + getSubRequestId(); } @Override @@ -254,30 +205,6 @@ public abstract class SoOperation extends HttpOperation { return true; } - /** - * Invoked when a request completes successfully. - */ - protected void successfulCompletion() { - // do nothing - } - - /** - * Issues a "get" request to see if the original request is complete yet. - * - * @param outcome outcome to be populated with the response - * @return a future that can be used to cancel the "get" request or await its response - */ - private CompletableFuture issueGet(OperationOutcome outcome) { - String path = getPathGet() + getSubRequestId(); - String url = getClient().getBaseUrl() + path; - - logger.debug("{}: 'get' count {} for {}", getFullName(), getCount, params.getRequestId()); - - logMessage(EventType.OUT, CommInfrastructure.REST, url, null); - - return handleResponse(outcome, url, callback -> getClient().get(callback, path, null)); - } - /** * Gets the request state of a response. * @@ -311,35 +238,26 @@ public abstract class SoOperation extends HttpOperation { * Prepends the message with the http status code. */ @Override - public OperationOutcome setOutcome(OperationOutcome outcome, PolicyResult result, Response rawResponse, + public OperationOutcome setOutcome(OperationOutcome outcome, OperationResult result, Response rawResponse, SoResponse response) { // set default result and message setOutcome(outcome, result); + int code = (result == OperationResult.FAILURE_TIMEOUT ? SO_RESPONSE_CODE : rawResponse.getStatus()); + outcome.setResponse(response); - outcome.setMessage(rawResponse.getStatus() + " " + outcome.getMessage()); + outcome.setMessage(code + " " + outcome.getMessage()); return outcome; } protected SoModelInfo prepareSoModelInfo() { - Target target = params.getTarget(); - if (target == null) { - throw new IllegalArgumentException("missing Target"); - } - - if (target.getModelCustomizationId() == null || target.getModelInvariantId() == null - || target.getModelName() == null || target.getModelVersion() == null - || target.getModelVersionId() == null) { - throw new IllegalArgumentException("missing VF Module model"); - } - - SoModelInfo soModelInfo = new SoModelInfo(); - soModelInfo.setModelCustomizationId(target.getModelCustomizationId()); - soModelInfo.setModelInvariantId(target.getModelInvariantId()); - soModelInfo.setModelName(target.getModelName()); - soModelInfo.setModelVersion(target.getModelVersion()); - soModelInfo.setModelVersionId(target.getModelVersionId()); + var soModelInfo = new SoModelInfo(); + soModelInfo.setModelCustomizationId(modelCustomizationId); + soModelInfo.setModelInvariantId(modelInvariantId); + soModelInfo.setModelName(modelName); + soModelInfo.setModelVersion(modelVersion); + soModelInfo.setModelVersionId(modelVersionId); soModelInfo.setModelType("vfModule"); return soModelInfo; } @@ -350,7 +268,7 @@ public abstract class SoOperation extends HttpOperation { * @return SO request information */ protected SoRequestInfo constructRequestInfo() { - SoRequestInfo soRequestInfo = new SoRequestInfo(); + var soRequestInfo = new SoRequestInfo(); soRequestInfo.setSource("POLICY"); soRequestInfo.setSuppressRollback(false); soRequestInfo.setRequestorId("policy"); @@ -400,19 +318,33 @@ public abstract class SoOperation extends HttpOperation { } /** - * Construct cloudConfiguration for the SO requestDetails. Overridden for custom - * query. + * Construct cloudConfiguration for the SO requestDetails. * * @param tenantItem tenant item from A&AI named-query response * @return SO cloud configuration */ - protected SoCloudConfiguration constructCloudConfigurationCq(Tenant tenantItem, CloudRegion cloudRegionItem) { - SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration(); - cloudConfiguration.setTenantId(tenantItem.getTenantId()); - cloudConfiguration.setLcpCloudRegionId(cloudRegionItem.getCloudRegionId()); + protected SoCloudConfiguration constructCloudConfiguration(Tenant tenantItem, CloudRegion cloudRegionItem) { + var cloudConfiguration = new SoCloudConfiguration(); + cloudConfiguration.setTenantId(getRequiredText("tenant ID", tenantItem.getTenantId())); + cloudConfiguration.setLcpCloudRegionId(getRequiredText("cloud region ID", cloudRegionItem.getCloudRegionId())); return cloudConfiguration; } + /** + * Verifies that a value is not {@code null}. + * + * @param name value name + * @param value value to check + * @return the value + */ + protected String getRequiredText(String name, String value) { + if (value == null) { + throw new IllegalArgumentException("missing " + name); + } + + return value; + } + /** * Create simple HTTP headers for unauthenticated requests to SO. * @@ -429,67 +361,34 @@ public abstract class SoOperation extends HttpOperation { * IllegalArgumentException if the desired data item is not found. */ - protected GenericVnf getVnfItem(AaiCqResponse aaiCqResponse, SoModelInfo soModelInfo) { - GenericVnf vnf = aaiCqResponse.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId()); - if (vnf == null) { - throw new IllegalArgumentException("missing generic VNF"); - } - - return vnf; + protected GenericVnf getVnfItem() { + return getRequiredProperty(OperationProperties.AAI_VNF, "generic VNF"); } - protected ServiceInstance getServiceInstance(AaiCqResponse aaiCqResponse) { - ServiceInstance vnfService = aaiCqResponse.getServiceInstance(); - if (vnfService == null) { - throw new IllegalArgumentException("missing VNF Service Item"); - } - - return vnfService; - } - - protected Tenant getDefaultTenant(AaiCqResponse aaiCqResponse) { - Tenant tenant = aaiCqResponse.getDefaultTenant(); - if (tenant == null) { - throw new IllegalArgumentException("missing Tenant Item"); - } - - return tenant; + protected ServiceInstance getServiceInstance() { + return getRequiredProperty(OperationProperties.AAI_SERVICE, "VNF Service Item"); } - protected CloudRegion getDefaultCloudRegion(AaiCqResponse aaiCqResponse) { - CloudRegion cloudRegion = aaiCqResponse.getDefaultCloudRegion(); - if (cloudRegion == null) { - throw new IllegalArgumentException("missing Cloud Region"); - } - - return cloudRegion; + protected Tenant getDefaultTenant() { + return getRequiredProperty(OperationProperties.AAI_DEFAULT_TENANT, "Default Tenant Item"); } - // these may be overridden by junit tests - - /** - * Gets the wait time, in milliseconds, between "get" requests. - * - * @return the wait time, in milliseconds, between "get" requests - */ - public long getWaitMsGet() { - return TimeUnit.MILLISECONDS.convert(getWaitSecGet(), TimeUnit.SECONDS); + protected CloudRegion getDefaultCloudRegion() { + return getRequiredProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, "Default Cloud Region"); } - public int getMaxGets() { - return config.getMaxGets(); + protected ModelVer getVnfModel() { + return getRequiredProperty(OperationProperties.AAI_VNF_MODEL, "generic VNF Model"); } - public String getPathGet() { - return config.getPathGet(); + protected ModelVer getServiceModel() { + return getRequiredProperty(OperationProperties.AAI_SERVICE_MODEL, "Service Model"); } - public int getWaitSecGet() { - return config.getWaitSecGet(); - } + // these may be overridden by junit tests @Override - protected Coder makeCoder() { + protected Coder getCoder() { return coder; }