import java.util.ArrayList;
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 org.onap.aai.domain.yang.GenericVnf;
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.controlloop.actorserviceprovider.OperationOutcome;
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.so.SoModelInfo;
public static final String REQ_PARAM_NM = "requestParameters";
public static final String CONFIG_PARAM_NM = "configurationParameters";
- @Getter
- private final SoOperator operator;
+ private final SoConfig config;
+
+ // values extracted from the parameter Target
+ private final String modelCustomizationId;
+ private final String modelInvariantId;
+ private final String modelVersionId;
+
+ private final String vfCountKey;
/**
* Number of "get" requests issued so far, on the current operation attempt.
* Constructs the object.
*
* @param params operation parameters
- * @param operator operator that created this operation
+ * @param config configuration for this operation
*/
- public SoOperation(ControlLoopOperationParams params, SoOperator operator) {
- super(params, operator, SoResponse.class);
- this.operator = operator;
+ public SoOperation(ControlLoopOperationParams params, HttpConfig config) {
+ super(params, config, SoResponse.class);
+ this.config = (SoConfig) config;
+
+ verifyNotNull("Target information", params.getTarget());
+
+ this.modelCustomizationId = params.getTarget().getModelCustomizationId();
+ this.modelInvariantId = params.getTarget().getModelInvariantId();
+ this.modelVersionId = params.getTarget().getModelVersionId();
+
+ vfCountKey = SoConstants.VF_COUNT_PREFIX + "[" + modelCustomizationId + "][" + modelInvariantId + "]["
+ + modelVersionId + "]";
}
/**
getCount = 0;
}
+ /**
+ * Validates that the parameters contain the required target information to extract
+ * the VF count from the custom query.
+ */
+ protected void validateTarget() {
+ verifyNotNull("model-customization-id", modelCustomizationId);
+ verifyNotNull("model-invariant-id", modelInvariantId);
+ verifyNotNull("model-version-id", modelVersionId);
+ }
+
+ private void verifyNotNull(String type, Object value) {
+ if (value == null) {
+ throw new IllegalArgumentException("missing " + type + " for guard payload");
+ }
+ }
+
/**
* Starts the GUARD.
*/
return startGuardAsync();
}
+ /**
+ * Gets the VF Count.
+ *
+ * @return a future to cancel or await the VF Count
+ */
+ @SuppressWarnings("unchecked")
+ protected CompletableFuture<OperationOutcome> 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<OperationOutcome> 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);
+ }
+
+ protected void setVfCount(int vfCount) {
+ params.getContext().setProperty(vfCountKey, vfCount);
+ }
+
/**
* If the response does not indicate that the request has been completed, then sleep a
* bit and issue a "get".
if (rawResponse.getStatus() == 200) {
String requestState = getRequestState(response);
if (COMPLETE.equalsIgnoreCase(requestState)) {
+ successfulCompletion();
return CompletableFuture
.completedFuture(setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response));
}
}
// see if the limit for the number of "gets" has been reached
- if (getCount++ >= operator.getMaxGets()) {
- logger.warn("{}: execeeded 'get' limit {} for {}", getFullName(), operator.getMaxGets(),
- params.getRequestId());
+ if (getCount++ >= getMaxGets()) {
+ logger.warn("{}: execeeded 'get' limit {} for {}", getFullName(), getMaxGets(), params.getRequestId());
setOutcome(outcome, PolicyResult.FAILURE_TIMEOUT);
outcome.setMessage(SO_RESPONSE_CODE + " " + outcome.getMessage());
return CompletableFuture.completedFuture(outcome);
return sleep(getWaitMsGet(), TimeUnit.MILLISECONDS).thenComposeAsync(doGet);
}
+ /**
+ * Invoked when a request completes successfully.
+ */
+ protected void successfulCompletion() {
+ // do nothing
+ }
+
/**
* Issues a "get" request to see if the original request is complete yet.
*
* @return a future that can be used to cancel the "get" request or await its response
*/
private CompletableFuture<OperationOutcome> issueGet(OperationOutcome outcome, SoResponse response) {
- String path = operator.getPathGet() + response.getRequestReferences().getRequestId();
- String url = operator.getClient().getBaseUrl() + path;
+ String path = getPathGet() + response.getRequestReferences().getRequestId();
+ String url = getClient().getBaseUrl() + path;
logger.debug("{}: 'get' count {} for {}", getFullName(), getCount, params.getRequestId());
logMessage(EventType.OUT, CommInfrastructure.REST, url, null);
// TODO should this use "path" or the full "url"?
- return handleResponse(outcome, url, callback -> operator.getClient().get(callback, path, null));
+ return handleResponse(outcome, url, callback -> getClient().get(callback, path, null));
}
/**
/**
* Builds the request parameters from the policy payload.
*/
- protected SoRequestParameters buildRequestParameters() {
+ protected Optional<SoRequestParameters> buildRequestParameters() {
if (params.getPayload() == null) {
- return null;
+ return Optional.empty();
}
- String json = params.getPayload().get(REQ_PARAM_NM);
- if (json == null) {
- return null;
+ Object data = params.getPayload().get(REQ_PARAM_NM);
+ if (data == null) {
+ return Optional.empty();
}
try {
- return coder.decode(json, SoRequestParameters.class);
+ return Optional.of(coder.decode(data.toString(), SoRequestParameters.class));
} catch (CoderException e) {
throw new IllegalArgumentException("invalid payload value: " + REQ_PARAM_NM);
}
/**
* Builds the configuration parameters from the policy payload.
*/
- protected List<Map<String, String>> buildConfigurationParameters() {
+ protected Optional<List<Map<String, String>>> buildConfigurationParameters() {
if (params.getPayload() == null) {
- return null;
+ return Optional.empty();
}
- String json = params.getPayload().get(CONFIG_PARAM_NM);
- if (json == null) {
- return null;
+ Object data = params.getPayload().get(CONFIG_PARAM_NM);
+ if (data == null) {
+ return Optional.empty();
}
try {
@SuppressWarnings("unchecked")
- List<Map<String, String>> result = coder.decode(json, ArrayList.class);
- return result;
+ List<Map<String, String>> result = coder.decode(data.toString(), ArrayList.class);
+ return Optional.of(result);
} catch (CoderException | RuntimeException e) {
throw new IllegalArgumentException("invalid payload value: " + CONFIG_PARAM_NM);
}
* @return the wait time, in milliseconds, between "get" requests
*/
public long getWaitMsGet() {
- return TimeUnit.MILLISECONDS.convert(operator.getWaitSecGet(), TimeUnit.SECONDS);
+ return TimeUnit.MILLISECONDS.convert(getWaitSecGet(), TimeUnit.SECONDS);
+ }
+
+ public int getMaxGets() {
+ return config.getMaxGets();
+ }
+
+ public String getPathGet() {
+ return config.getPathGet();
+ }
+
+ public int getWaitSecGet() {
+ return config.getWaitSecGet();
}
}