diff options
Diffstat (limited to 'controlloop')
43 files changed, 4020 insertions, 328 deletions
diff --git a/controlloop/common/actors/actor.appc/pom.xml b/controlloop/common/actors/actor.appc/pom.xml index 5f6519a47..2d39ca849 100644 --- a/controlloop/common/actors/actor.appc/pom.xml +++ b/controlloop/common/actors/actor.appc/pom.xml @@ -18,15 +18,45 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>actor.appclcm</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>aai</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>appc</artifactId> <version>1.1.0-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>trafficgenerator</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>events</artifactId> <version>1.1.0-SNAPSHOT</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/controlloop/common/actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/APPCActorServiceProvider.java b/controlloop/common/actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/APPCActorServiceProvider.java index 7cdf99625..e7b7d2371 100644 --- a/controlloop/common/actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/APPCActorServiceProvider.java +++ b/controlloop/common/actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/APPCActorServiceProvider.java @@ -21,16 +21,17 @@ package org.onap.policy.controlloop.actor.appc; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider; import org.onap.policy.appc.CommonHeader; import org.onap.policy.appc.Request; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.policy.Policy; - +import org.onap.policy.vnf.trafficgenerator.PGRequest; +import org.onap.policy.vnf.trafficgenerator.PGStream; +import org.onap.policy.vnf.trafficgenerator.PGStreams; import org.onap.policy.controlloop.actorServiceProvider.spi.Actor; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -43,7 +44,7 @@ public class APPCActorServiceProvider implements Actor { .put("Restart", ImmutableList.of("VM")) .put("Rebuild", ImmutableList.of("VM")) .put("Migrate", ImmutableList.of("VM")) - .put("ModifyConfig", ImmutableList.of("VFC")) + .put("ModifyConfig", ImmutableList.of("VNF")) .build(); private static final ImmutableMap<String, List<String>> payloads = new ImmutableMap.Builder<String, List<String>>() .put("ModifyConfig", ImmutableList.of("generic-vnf.vnf-id")) @@ -69,43 +70,63 @@ public class APPCActorServiceProvider implements Actor { return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); } - + /** + * Constructs an APPC request conforming to the legacy API. + * The legacy API will be deprecated in future releases as + * all legacy functionality is moved into the LCM API. + * + * @param onset + * the event that is reporting the alert for policy + * to perform an action + * @param operation + * the control loop operation specifying the actor, + * operation, target, etc. + * @param policy + * the policy the was specified from the yaml generated + * by CLAMP or through the Policy GUI/API + * @return an APPC request conforming to the legacy API + */ public static Request constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy) { - // - // Construct an APPC request - // + /* + * Construct an APPC request + */ Request request = new Request(); request.CommonHeader = new CommonHeader(); request.CommonHeader.RequestID = onset.requestID; request.CommonHeader.SubRequestID = operation.subRequestId; request.Action = policy.getRecipe(); - // - // TODO: do we need to take care of the target - // + /* + * The target vnf-id may not be the same as the source vnf-id + * specified in the yaml, the target vnf-id is retrieved by + * a named query to A&AI. + */ + String resourceId = policy.getTarget().getResourceID(); + String sourceVnfId = onset.AAI.get("generic-vnf.vnf-id"); + String vnfId = "test"; //AppcLcmActorServiceProvider.vnfNamedQuery(resourceId, sourceVnfId); + + /* + * For now Policy generates the PG Streams as a demo, in the + * future the payload can be provided by CLAMP + */ + request.Payload.put("generic-vnf.vnf-id", vnfId); + + PGRequest pgRequest = new PGRequest(); + pgRequest.pgStreams = new PGStreams(); - // - // Handle the payload - // - if (policy.getPayload() != null && !policy.getPayload().isEmpty()) { - request.Payload = new HashMap<String, Object>(); - // - // Add each payload entry - // - for (Map.Entry<String, String> entry : policy.getPayload().entrySet()) { - // - // TODO: entry key has ref$, value has {xxxx} - // - request.Payload.put(entry.getKey(), entry.getValue()); - } + PGStream pgStream; + for (int i = 0; i < 5; i++) { + pgStream = new PGStream(); + pgStream.streamId = "fw_udp"+(i+1); + pgStream.isEnabled = "true"; + pgRequest.pgStreams.pgStream.add(pgStream); } + request.Payload.put("pg-streams", pgRequest.pgStreams); + /* + * Return the request + */ - request.Payload.put("AICVServerSelfLink", onset.AAI.get("vserver.selflink"));//.AICVServerSelfLink); - request.Payload.put("AICIdentity", onset.AAI.get("cloud-region.identity-url"));//AICIdentity); - // - // Return the request - // return request; } diff --git a/controlloop/common/actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java b/controlloop/common/actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java new file mode 100644 index 000000000..c8179992c --- /dev/null +++ b/controlloop/common/actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java @@ -0,0 +1,124 @@ +/*- + * ============LICENSE_START======================================================= + * AppcServiceProviderTest + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appc; + +import static org.junit.Assert.*; + +import java.time.Instant; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.onap.policy.appc.Request; +import org.onap.policy.appc.util.Serialization; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.ControlLoopTargetType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcServiceProviderTest { + + private static final Logger logger = LoggerFactory.getLogger(AppcServiceProviderTest.class); + + private static VirtualControlLoopEvent onsetEvent; + private static ControlLoopOperation operation; + private static Policy policy; + + static { + /* + * Construct an onset with an AAI subtag containing + * generic-vnf.vnf-id and a target type of VM. + */ + onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.closedLoopControlName = "closedLoopControlName-Test"; + onsetEvent.requestID = UUID.randomUUID(); + onsetEvent.closedLoopEventClient = "tca.instance00001"; + onsetEvent.target_type = ControlLoopTargetType.VF; + onsetEvent.target = "generic-vnf.vnf-id"; + onsetEvent.from = "DCAE"; + onsetEvent.closedLoopAlarmStart = Instant.now(); + onsetEvent.AAI = new HashMap<>(); + onsetEvent.AAI.put("generic-vnf.vnf-id", "fw0001vm001fw001"); + onsetEvent.closedLoopEventStatus = ControlLoopEventStatus.ONSET; + + /* Construct an operation with an APPC actor and ModifyConfig operation. */ + operation = new ControlLoopOperation(); + operation.actor = "APPC"; + operation.operation = "ModifyConfig"; + operation.target = "VM"; + operation.end = Instant.now(); + operation.subRequestId = "1"; + + /* Construct a policy specifying to modify configuration. */ + policy = new Policy(); + policy.setName("Modify Packet Generation Config"); + policy.setDescription("Upon getting the trigger event, modify packet gen config"); + policy.setActor("APPC"); + policy.setTarget(new Target(TargetType.VM)); + policy.setRecipe("ModifyConfig"); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + + } + + @Test + public void constructModifyConfigRequestTest() { + + Request appcRequest = APPCActorServiceProvider.constructRequest(onsetEvent, operation, policy); + + /* The service provider must return a non null APPC request */ + assertNotNull(appcRequest); + + /* A common header is required and cannot be null */ + assertNotNull(appcRequest.getCommonHeader()); + assertEquals(appcRequest.getCommonHeader().RequestID, onsetEvent.requestID); + + /* An action is required and cannot be null */ + assertNotNull(appcRequest.Action); + assertEquals(appcRequest.Action, "ModifyConfig"); + + /* A payload is required and cannot be null */ + assertNotNull(appcRequest.getPayload()); + assertTrue(appcRequest.getPayload().containsKey("generic-vnf.vnf-id")); + assertTrue(appcRequest.getPayload().containsKey("pg-streams")); + + logger.debug("APPC Request: \n" + appcRequest.toString()); + + /* Print out request as json to make sure serialization works */ + String jsonRequest = Serialization.gsonPretty.toJson(appcRequest); + logger.debug("JSON Output: \n" + jsonRequest); + + /* The JSON string must contain the following fields */ + assertTrue(jsonRequest.contains("CommonHeader")); + assertTrue(jsonRequest.contains("Action")); + assertTrue(jsonRequest.contains("ModifyConfig")); + assertTrue(jsonRequest.contains("Payload")); + assertTrue(jsonRequest.contains("generic-vnf.vnf-id")); + assertTrue(jsonRequest.contains("pg-streams")); + } + +} diff --git a/controlloop/common/actors/actor.appclcm/pom.xml b/controlloop/common/actors/actor.appclcm/pom.xml new file mode 100644 index 000000000..6aa5f6439 --- /dev/null +++ b/controlloop/common/actors/actor.appclcm/pom.xml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<project + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>actors</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <artifactId>actor.appclcm</artifactId> + <dependencies> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>actorServiceProvider</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>appclcm</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>aai</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>events</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java b/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java new file mode 100644 index 000000000..c52a7f08e --- /dev/null +++ b/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java @@ -0,0 +1,293 @@ +/*- + * ============LICENSE_START======================================================= + * AppcLcmActorServiceProvider + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appclcm; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import java.util.AbstractMap; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.onap.policy.aai.AAINQF199.AAINQF199InventoryResponseItem; +import org.onap.policy.aai.AAINQF199.AAINQF199Manager; +import org.onap.policy.aai.AAINQF199.AAINQF199Request; +import org.onap.policy.aai.AAINQF199.AAINQF199Response; +import org.onap.policy.appclcm.LCMCommonHeader; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseCode; +import org.onap.policy.appclcm.LCMResponseWrapper; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorServiceProvider.spi.Actor; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmActorServiceProvider implements Actor { + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorServiceProvider.class); + + /* The source vnf-id provided from the DCAE onset */ + private static final String DCAE_VNF_ID = "generic-vnf.vnf-id"; + + /* To be used in future releases to restart a single vm */ + private static final String APPC_VM_ID = "vm-id"; + + /* To be used in future releases when LCM ConfigModify is used */ + private static final String APPC_REQUEST_PARAMS = "request-parameters"; + private static final String APPC_CONFIG_PARAMS = "configuration-parameters"; + + private static final ImmutableList<String> recipes = ImmutableList.of("Restart", "Rebuild", "Migrate", + "ConfigModify"); + private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>() + .put("Restart", ImmutableList.of("VM")).put("Rebuild", ImmutableList.of("VM")) + .put("Migrate", ImmutableList.of("VM")).put("ConfigModify", ImmutableList.of("VNF")).build(); + private static final ImmutableMap<String, List<String>> payloads = new ImmutableMap.Builder<String, List<String>>() + .put("Restart", ImmutableList.of(APPC_VM_ID)) + .put("ConfigModify", ImmutableList.of(APPC_REQUEST_PARAMS, APPC_CONFIG_PARAMS)).build(); + + @Override + public String actor() { + return "APPC"; + } + + @Override + public List<String> recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List<String> recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List<String> recipePayloads(String recipe) { + return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); + } + + /** + * Constructs an A&AI Named Query using a source vnf-id to determine + * the vnf-id of the target entity specified in the policy to act upon. + * + * @param resourceId + * the id of the target from the sdc catalog + * + * @param sourceVnfId + * the vnf id of the source entity reporting the alert + * + * @return the target entities vnf id to act upon + */ + public static String vnfNamedQuery(String resourceId, String sourceVnfId) { + String targetVnfId = ""; + AAINQF199Request aaiRequest = new AAINQF199Request(); + UUID requestId = UUID.randomUUID(); + + aaiRequest.queryParameters.namedQuery.namedQueryUUID = requestId; + + Map<String, Map<String, String>> filter = new HashMap<String, Map<String, String>>(); + + Map<String, String> filterItem = new HashMap<String, String>(); + filterItem.put("vnf-id", sourceVnfId); + + filter.put("generic-vnf", filterItem); + + aaiRequest.instanceFilters.instanceFilter.add(filter); + + //TODO: What is the url to use? + AAINQF199Response aaiResponse = AAINQF199Manager.postQuery("http://localhost:6666", "policy", "policy", aaiRequest, requestId); + + //TODO: What if the resourceId never matches? + for (AAINQF199InventoryResponseItem item: aaiResponse.inventoryResponseItems) { + if (item.genericVNF.modelInvariantId.equals(resourceId)) { + targetVnfId = item.genericVNF.vnfID; + } + } + + return targetVnfId; + } + + /** + * Constructs an APPC request conforming to the lcm API. + * The actual request is constructed and then placed in a + * wrapper object used to send through DMAAP. + * + * @param onset + * the event that is reporting the alert for policy + * to perform an action + * @param operation + * the control loop operation specifying the actor, + * operation, target, etc. + * @param policy + * the policy the was specified from the yaml generated + * by CLAMP or through the Policy GUI/API + * @return an APPC request conforming to the lcm API using the DMAAP wrapper + */ + public static LCMRequestWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, + Policy policy) { + + /* Construct an APPC request using LCM Model */ + + /* + * The actual LCM request is placed in a wrapper used to send + * through dmaap. The current version is 2.0 as of R1. + */ + LCMRequestWrapper dmaapRequest = new LCMRequestWrapper(); + dmaapRequest.setVersion("2.0"); + dmaapRequest.setCorrelationId(onset.requestID + "-" + operation.subRequestId); + dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); + dmaapRequest.setType("request"); + + /* This is the actual request that is placed in the dmaap wrapper. */ + LCMRequest appcRequest = new LCMRequest(); + + /* The common header is a required field for all APPC requests. */ + LCMCommonHeader requestCommonHeader = new LCMCommonHeader(); + requestCommonHeader.setOriginatorId(onset.requestID.toString()); + requestCommonHeader.setRequestId(onset.requestID); + requestCommonHeader.setSubRequestId(operation.subRequestId); + + appcRequest.setCommonHeader(requestCommonHeader); + + /* + * Action Identifiers are required for APPC LCM requests. + * For R1, the recipes supported by Policy only require + * a vnf-id. + */ + HashMap<String, String> requestActionIdentifiers = new HashMap<>(); + requestActionIdentifiers.put("vnf-id", onset.AAI.get(DCAE_VNF_ID)); + appcRequest.setActionIdentifiers(requestActionIdentifiers); + + /* + * An action is required for all APPC requests, this will + * be the recipe specified in the policy. + */ + appcRequest.setAction(policy.getRecipe().toLowerCase()); + + /* + * For R1, the payloads will not be required for the Restart, + * Rebuild, or Migrate recipes. APPC will populate the payload + * based on A&AI look up of the vnd-id provided in the action + * identifiers. + */ + if ("Restart".equalsIgnoreCase(policy.getRecipe()) || "Rebuild".equalsIgnoreCase(policy.getRecipe()) + || "Migrate".equalsIgnoreCase(policy.getRecipe())) { + appcRequest.setPayload(null); + } + + /* + * Once the LCM request is constructed, add it into the + * body of the dmaap wrapper. + */ + dmaapRequest.setBody(appcRequest); + + /* Return the request to be sent through dmaap. */ + return dmaapRequest; + } + + /** + * Parses the operation attempt using the subRequestId + * of APPC response. + * + * @param subRequestId + * the sub id used to send to APPC, Policy sets + * this using the operation attempt + * + * @return the current operation attempt + */ + public static Integer parseOperationAttempt(String subRequestId) { + Integer operationAttempt; + try { + operationAttempt = Integer.parseInt(subRequestId); + } catch (NumberFormatException e) { + logger.debug("A NumberFormatException was thrown due to error in parsing the operation attempt"); + return null; + } + return operationAttempt; + } + + /** + * Processes the APPC LCM response sent from APPC. Determines + * if the APPC operation was successful/unsuccessful and maps + * this to the corresponding Policy result. + * + * @param dmaapResponse + * the dmaap wrapper message that contains the + * actual APPC reponse inside the body field + * + * @return an key-value pair that contains the Policy result + * and APPC response message + */ + public static SimpleEntry<PolicyResult, String> processResponse(LCMResponseWrapper dmaapResponse) { + /* The actual APPC response is inside the wrapper's body field. */ + LCMResponse appcResponse = dmaapResponse.getBody(); + + /* The message returned in the APPC response. */ + String message; + + /* The Policy result determined from the APPC Response. */ + PolicyResult result; + + /* If there is no status, Policy cannot determine if the request was successful. */ + if (appcResponse.getStatus() == null) { + message = "Policy was unable to parse APP-C response status field (it was null)."; + return new AbstractMap.SimpleEntry<>(PolicyResult.FAILURE_EXCEPTION, message); + } + + /* If there is no code, Policy cannot determine if the request was successful. */ + String responseValue = LCMResponseCode.toResponseValue(appcResponse.getStatus().getCode()); + if (responseValue == null) { + message = "Policy was unable to parse APP-C response status code field."; + return new AbstractMap.SimpleEntry<>(PolicyResult.FAILURE_EXCEPTION, message); + } + + /* Save the APPC response's message for Policy noticiation message. */ + message = appcResponse.getStatus().getMessage(); + + /* Maps the APPC response result to a Policy result. */ + switch (responseValue) { + case LCMResponseCode.ACCEPTED: + /* Nothing to do if code is accept, continue processing */ + result = null; + break; + case LCMResponseCode.SUCCESS: + result = PolicyResult.SUCCESS; + break; + case LCMResponseCode.FAILURE: + result = PolicyResult.FAILURE; + break; + case LCMResponseCode.REJECT: + case LCMResponseCode.ERROR: + default: + result = PolicyResult.FAILURE_EXCEPTION; + } + return new AbstractMap.SimpleEntry<>(result, message); + } + +} diff --git a/controlloop/common/actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/controlloop/common/actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor new file mode 100644 index 000000000..403ad9859 --- /dev/null +++ b/controlloop/common/actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor @@ -0,0 +1 @@ +org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider
\ No newline at end of file diff --git a/controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmServiceProviderTest.java b/controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmServiceProviderTest.java new file mode 100644 index 000000000..f1df440a8 --- /dev/null +++ b/controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmServiceProviderTest.java @@ -0,0 +1,271 @@ +/*- + * ============LICENSE_START======================================================= + * AppcServiceProviderTest + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appclcm; + +import static org.junit.Assert.*; + +import java.time.Instant; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.onap.policy.appclcm.LCMCommonHeader; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseWrapper; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.ControlLoopTargetType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmServiceProviderTest { + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmServiceProviderTest.class); + + private static VirtualControlLoopEvent onsetEvent; + private static ControlLoopOperation operation; + private static Policy policy; + private static LCMRequestWrapper dmaapRequest; + private static LCMResponseWrapper dmaapResponse; + + static { + /* + * Construct an onset with an AAI subtag containing + * generic-vnf.vnf-id and a target type of VM. + */ + onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.closedLoopControlName = "closedLoopControlName-Test"; + onsetEvent.requestID = UUID.randomUUID(); + onsetEvent.closedLoopEventClient = "tca.instance00001"; + onsetEvent.target_type = ControlLoopTargetType.VM; + onsetEvent.target = "generic-vnf.vnf-id"; + onsetEvent.from = "DCAE"; + onsetEvent.closedLoopAlarmStart = Instant.now(); + onsetEvent.AAI = new HashMap<>(); + onsetEvent.AAI.put("generic-vnf.vnf-id", "fw0001vm001fw001"); + onsetEvent.closedLoopEventStatus = ControlLoopEventStatus.ONSET; + + /* Construct an operation with an APPC actor and restart operation. */ + operation = new ControlLoopOperation(); + operation.actor = "APPC"; + operation.operation = "Restart"; + operation.target = "VM"; + operation.end = Instant.now(); + operation.subRequestId = "1"; + + /* Construct a policy specifying to restart vm. */ + policy = new Policy(); + policy.setName("Restart the VM"); + policy.setDescription("Upon getting the trigger event, restart the VM"); + policy.setActor("APPC"); + policy.setTarget(new Target(TargetType.VM)); + policy.setRecipe("Restart"); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + + /* A sample DMAAP request wrapper. */ + dmaapRequest = new LCMRequestWrapper(); + dmaapRequest.setCorrelationId(onsetEvent.requestID.toString() + "-" + "1"); + dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); + dmaapRequest.setType("request"); + + /* A sample DMAAP response wrapper */ + dmaapResponse = new LCMResponseWrapper(); + dmaapResponse.setCorrelationId(onsetEvent.requestID.toString() + "-" + "1"); + dmaapResponse.setRpcName(policy.getRecipe().toLowerCase()); + dmaapResponse.setType("response"); + + /* A sample APPC LCM request. */ + LCMRequest appcRequest = new LCMRequest(); + + /* The following code constructs a sample APPC LCM Request */ + appcRequest.setAction("restart"); + + HashMap<String, String> actionIdentifiers = new HashMap<>(); + actionIdentifiers.put("vnf-id", "trial-vnf-003"); + + appcRequest.setActionIdentifiers(actionIdentifiers); + + LCMCommonHeader commonHeader = new LCMCommonHeader(); + commonHeader.setRequestId(onsetEvent.requestID); + commonHeader.setSubRequestId("1"); + commonHeader.setOriginatorId(onsetEvent.requestID.toString()); + + appcRequest.setCommonHeader(commonHeader); + + appcRequest.setPayload(null); + + dmaapRequest.setBody(appcRequest); + + /* The following code constructs a sample APPC LCM Response */ + LCMResponse appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("Restart Successful"); + + dmaapResponse.setBody(appcResponse); + } + + /** + * A test to construct an APPC LCM restart request. + */ + @Test + public void constructRestartRequestTest() { + + LCMRequestWrapper dmaapRequest = AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, policy); + + /* The service provider must return a non null DMAAP request wrapper */ + assertNotNull(dmaapRequest); + + /* The DMAAP wrapper's type field must be request */ + assertEquals(dmaapRequest.getType(), "request"); + + /* The DMAAP wrapper's body field cannot be null */ + assertNotNull(dmaapRequest.getBody()); + + LCMRequest appcRequest = dmaapRequest.getBody(); + + /* A common header is required and cannot be null */ + assertNotNull(appcRequest.getCommonHeader()); + assertEquals(appcRequest.getCommonHeader().getRequestId(), onsetEvent.requestID); + + /* An action is required and cannot be null */ + assertNotNull(appcRequest.getAction()); + assertEquals(appcRequest.getAction(), "restart"); + + /* Action Identifiers are required and cannot be null */ + assertNotNull(appcRequest.getActionIdentifiers()); + assertNotNull(appcRequest.getActionIdentifiers().get("vnf-id")); + + logger.debug("APPC Request: \n" + appcRequest.toString()); + } + + /** + * A test to process a successful APPC restart response. + */ + @Test + public void processRestartResponseSuccessTest() { + AbstractMap.SimpleEntry<PolicyResult, String> result = AppcLcmActorServiceProvider + .processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.SUCCESS); + assertEquals(result.getValue(), "Restart Successful"); + } + + /** + * A test to map APPC response results to corresponding Policy results + */ + @Test + public void appcToPolicyResultTest() { + + AbstractMap.SimpleEntry<PolicyResult, String> result; + + /* If APPC accepts, PolicyResult is null */ + dmaapResponse.getBody().getStatus().setCode(100); + dmaapResponse.getBody().getStatus().setMessage("ACCEPTED"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), null); + + /* If APPC is successful, PolicyResult is success */ + dmaapResponse.getBody().getStatus().setCode(400); + dmaapResponse.getBody().getStatus().setMessage("SUCCESS"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.SUCCESS); + + /* If APPC returns an error, PolicyResult is failure exception */ + dmaapResponse.getBody().getStatus().setCode(200); + dmaapResponse.getBody().getStatus().setMessage("ERROR"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + /* If APPC rejects, PolicyResult is failure exception */ + dmaapResponse.getBody().getStatus().setCode(300); + dmaapResponse.getBody().getStatus().setMessage("REJECT"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + /* Test multiple reject codes */ + dmaapResponse.getBody().getStatus().setCode(306); + dmaapResponse.getBody().getStatus().setMessage("REJECT"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + dmaapResponse.getBody().getStatus().setCode(313); + dmaapResponse.getBody().getStatus().setMessage("REJECT"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + /* If APPC returns failure, PolicyResult is failure */ + dmaapResponse.getBody().getStatus().setCode(401); + dmaapResponse.getBody().getStatus().setMessage("FAILURE"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE); + + /* Test multiple failure codes */ + dmaapResponse.getBody().getStatus().setCode(406); + dmaapResponse.getBody().getStatus().setMessage("FAILURE"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE); + + dmaapResponse.getBody().getStatus().setCode(450); + dmaapResponse.getBody().getStatus().setMessage("FAILURE"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE); + + /* If APPC returns partial success, PolicyResult is failure exception */ + dmaapResponse.getBody().getStatus().setCode(500); + dmaapResponse.getBody().getStatus().setMessage("PARTIAL SUCCESS"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + /* If APPC returns partial failure, PolicyResult is failure exception */ + dmaapResponse.getBody().getStatus().setCode(501); + dmaapResponse.getBody().getStatus().setMessage("PARTIAL FAILURE"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + /* Test multiple partial failure codes */ + dmaapResponse.getBody().getStatus().setCode(599); + dmaapResponse.getBody().getStatus().setMessage("PARTIAL FAILURE"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + dmaapResponse.getBody().getStatus().setCode(550); + dmaapResponse.getBody().getStatus().setMessage("PARTIAL FAILURE"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + + /* If APPC code is unknown to Policy, PolicyResult is failure exception */ + dmaapResponse.getBody().getStatus().setCode(700); + dmaapResponse.getBody().getStatus().setMessage("UNKNOWN"); + result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + assertEquals(result.getKey(), PolicyResult.FAILURE_EXCEPTION); + } + + +} diff --git a/controlloop/common/actors/pom.xml b/controlloop/common/actors/pom.xml index e99fbb09f..1f38e90b1 100644 --- a/controlloop/common/actors/pom.xml +++ b/controlloop/common/actors/pom.xml @@ -15,6 +15,7 @@ <module>actorServiceProvider</module> <module>actor.appc</module> <module>actor.vfc</module> + <module>actor.appclcm</module> <module>actor.mso</module> <module>actor.test</module> </modules> diff --git a/controlloop/common/eventmanager/pom.xml b/controlloop/common/eventmanager/pom.xml index 8447ff74d..44086a68d 100644 --- a/controlloop/common/eventmanager/pom.xml +++ b/controlloop/common/eventmanager/pom.xml @@ -60,6 +60,12 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>actor.appclcm</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>guard</artifactId> <version>1.1.0-SNAPSHOT</version> <scope>provided</scope> @@ -83,6 +89,18 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>appclcm</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>trafficgenerator</artifactId> + <version>1.1.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> @@ -106,5 +124,6 @@ <version>1.1.0-SNAPSHOT</version> <scope>provided</scope> </dependency> + </dependencies> </project> diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java index 09f69fb0b..3c264ab24 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,6 +23,7 @@ package org.onap.policy.controlloop.eventmanager; import java.io.Serializable; import java.sql.Timestamp; import java.time.Instant; +import java.util.AbstractMap; import java.util.LinkedList; import javax.persistence.EntityManager; @@ -30,31 +31,32 @@ import javax.persistence.Persistence; import org.onap.policy.appc.Response; import org.onap.policy.appc.ResponseCode; +import org.onap.policy.appclcm.LCMResponseWrapper; import org.onap.policy.controlloop.ControlLoopEvent; +import org.onap.policy.controlloop.ControlLoopException; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.ControlLoopException; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.PolicyResult; import org.onap.policy.controlloop.actor.appc.APPCActorServiceProvider; import org.onap.policy.controlloop.actor.vfc.VFCActorServiceProvider; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - +import org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider; public class ControlLoopOperationManager implements Serializable { - + /** - * + * */ private static final long serialVersionUID = -3773199283624595410L; private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationManager.class); @Override public String toString() { - return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy=" + return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy=" + (policy != null ? policy.getId() : "null") + ", attempts=" + attempts - + ", policyResult=" + policyResult + + ", policyResult=" + policyResult + ", currentOperation=" + currentOperation + ", operationHistory=" + operationHistory + "]"; } @@ -92,17 +94,17 @@ public class ControlLoopOperationManager implements Serializable { public ControlLoopOperation operation = new ControlLoopOperation(); public PolicyResult policyResult = null; public int attempt = 0; - + @Override public String toString() { return "Operation [attempt=" + attempt + ", policyResult=" + policyResult + ", operation=" + operation + "]"; } } - + private String guardApprovalStatus = "NONE";//"NONE", "PERMIT", "DENY" private Object operationRequest; - + public Object getOperationRequest() { return operationRequest; } @@ -113,14 +115,14 @@ public class ControlLoopOperationManager implements Serializable { public void setGuardApprovalStatus(String guardApprovalStatus) { this.guardApprovalStatus = guardApprovalStatus; } - - - public ControlLoopOperationManager(/*ATTControlLoopEvent*/ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException { + + + public ControlLoopOperationManager(ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException { this.onset = onset; this.policy = policy; this.guardApprovalStatus = "NONE"; this.eventManager = em; - + // // Let's make a sanity check // @@ -139,7 +141,7 @@ public class ControlLoopOperationManager implements Serializable { throw new ControlLoopException("ControlLoopEventManager: policy has an unknown actor."); } } - + public Object startOperation(/*VirtualControlLoopEvent*/ControlLoopEvent onset) { // // They shouldn't call us if we currently running something @@ -196,16 +198,22 @@ public class ControlLoopOperationManager implements Serializable { // switch (policy.getActor()) { case "APPC": - //Request request = APPCActorServiceProvider.constructRequest(onset, operation.operation, this.policy); - this.operationRequest = APPCActorServiceProvider.constructRequest((VirtualControlLoopEvent)onset, operation.operation, this.policy); + /* + * If the recipe is ModifyConfig, a legacy APPC + * request is constructed. Otherwise an LCMRequest + * is constructed. + */ + if ("ModifyConfig".equalsIgnoreCase(policy.getRecipe())) { + + this.operationRequest = APPCActorServiceProvider.constructRequest((VirtualControlLoopEvent)onset, operation.operation, this.policy); + } + else { + this.operationRequest = AppcLcmActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset, operation.operation, this.policy); + } // // Save the operation // this.currentOperation = operation; - //System.out.print("************* BEFORE STORING....."); - //this.storeOperationInDataBase("startOperation"); - //System.out.print("************* AFTER STORING....."); - // return operationRequest; case "MSO": // @@ -221,7 +229,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public PolicyResult onResponse(Object response) { // // Which response is it? @@ -306,10 +314,37 @@ public class ControlLoopOperationManager implements Serializable { } return PolicyResult.FAILURE; } - } + } + else if (response instanceof LCMResponseWrapper) { + + LCMResponseWrapper dmaapResponse = (LCMResponseWrapper) response; + + /* + * Parse out the operation attempt using the subrequestid + */ + Integer operationAttempt = AppcLcmActorServiceProvider.parseOperationAttempt(dmaapResponse.getBody().getCommonHeader().getSubRequestId()); + if (operationAttempt == null) { + this.completeOperation(operationAttempt, "Policy was unable to parse APP-C SubRequestID (it was null).", PolicyResult.FAILURE_EXCEPTION); + } + + /* + * Process the APPCLCM response to see what PolicyResult + * should be returned + */ + AbstractMap.SimpleEntry<PolicyResult, String> result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); + + if (result.getKey() != null) { + this.completeOperation(operationAttempt, result.getValue(), result.getKey()); + if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) { + return null; + } + return result.getKey(); + } + return null; + } return null; } - + public Integer getOperationTimeout() { // // Sanity check @@ -321,7 +356,7 @@ public class ControlLoopOperationManager implements Serializable { logger.debug("getOperationTimeout returning {}", this.policy.getTimeout()); return this.policy.getTimeout(); } - + public String getOperationTimeoutString(int defaultTimeout) { Integer to = this.getOperationTimeout(); if (to == null || to == 0) { @@ -329,11 +364,11 @@ public class ControlLoopOperationManager implements Serializable { } return to.toString() + "s"; } - + public PolicyResult getOperationResult() { return this.policyResult; } - + public String getOperationMessage() { if (this.currentOperation != null && this.currentOperation.operation != null) { return this.currentOperation.operation.toMessage(); @@ -343,7 +378,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public String getOperationMessage(String guardResult) { if (this.currentOperation != null && this.currentOperation.operation != null) { return this.currentOperation.operation.toMessage()+ ", Guard result: " + guardResult; @@ -353,7 +388,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public String getOperationHistory() { if (this.currentOperation != null && this.currentOperation.operation != null) { return this.currentOperation.operation.toHistory(); @@ -363,23 +398,23 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public LinkedList<ControlLoopOperation> getHistory() { LinkedList<ControlLoopOperation> history = new LinkedList<ControlLoopOperation>(); for (Operation op : this.operationHistory) { history.add(new ControlLoopOperation(op.operation)); - + } return history; } - + public void setOperationHasTimedOut() { // // // this.completeOperation(this.attempts, "Operation timed out", PolicyResult.FAILURE_TIMEOUT); } - + public void setOperationHasGuardDeny() { // // @@ -434,11 +469,11 @@ public class ControlLoopOperationManager implements Serializable { // return true; } - + public boolean isOperationRunning() { return (this.currentOperation != null); } - + private boolean isRetriesMaxedOut() { if (policy.getRetry() == null || policy.getRetry() == 0) { // @@ -449,19 +484,23 @@ public class ControlLoopOperationManager implements Serializable { } return (this.attempts > policy.getRetry()); } - + private void storeOperationInDataBase(){ - + + String OpsHistPU = System.getProperty("OperationsHistoryPU"); + if(OpsHistPU == null || !OpsHistPU.equals("TestOperationsHistoryPU")){ + OpsHistPU = "OperationsHistoryPU"; + } EntityManager em; try{ - em = Persistence.createEntityManagerFactory("OperationsHistoryPU").createEntityManager();//emf.createEntityManager(); + em = Persistence.createEntityManagerFactory(OpsHistPU).createEntityManager(); }catch(Exception e){ logger.error("storeOperationInDataBase threw: ", e); - return; + return; } - - OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry(); - + + OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry(); + newEntry.closedLoopName = this.onset.closedLoopControlName; newEntry.requestId = this.onset.requestID.toString(); newEntry.actor = this.currentOperation.operation.actor; @@ -472,17 +511,17 @@ public class ControlLoopOperationManager implements Serializable { newEntry.endtime = new Timestamp(this.currentOperation.operation.end.toEpochMilli()); newEntry.message = this.currentOperation.operation.message; newEntry.outcome = this.currentOperation.operation.outcome; - + em.getTransaction().begin(); em.persist(newEntry); em.getTransaction().commit(); - + em.close(); } - - + + private void completeOperation(Integer attempt, String message, PolicyResult result) { if (attempt == null) { logger.debug("attempt cannot be null (i.e. subRequestID)"); @@ -521,7 +560,7 @@ public class ControlLoopOperationManager implements Serializable { } } logger.debug("Could not find associated operation"); - + } - + } diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/drools/impl/PolicyEngineJUnitImpl.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/drools/impl/PolicyEngineJUnitImpl.java index bb5cec8da..aed72815c 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/drools/impl/PolicyEngineJUnitImpl.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/drools/impl/PolicyEngineJUnitImpl.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Queue; import org.onap.policy.appc.Request; +import org.onap.policy.appclcm.LCMRequestWrapper; import org.onap.policy.controlloop.ControlLoopNotification; import org.onap.policy.controlloop.util.Serialization; import org.slf4j.Logger; @@ -49,6 +50,10 @@ public class PolicyEngineJUnitImpl implements PolicyEngine { Request request = (Request) obj; logger.debug("Request: {} subrequst {}", request.Action, request.CommonHeader.SubRequestID); } + else if (obj instanceof LCMRequestWrapper) { + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj; + logger.debug("Request: {} subrequest {}", dmaapRequest.getBody().getAction(), dmaapRequest.getBody().getCommonHeader().getSubRequestId()); + } // // Does the bus exist? // @@ -57,7 +62,7 @@ public class PolicyEngineJUnitImpl implements PolicyEngine { // // Create the bus // - busMap.put(busType, new HashMap<String, Queue<Object>>()); + busMap.put(busType, new HashMap<>()); } // // Get the bus @@ -71,7 +76,7 @@ public class PolicyEngineJUnitImpl implements PolicyEngine { // // Create the topic // - topicMap.put(topic, new LinkedList<Object>()); + topicMap.put(topic, new LinkedList<>()); } // // Get the topic queue diff --git a/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml b/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml index f007c4951..27c64b60a 100644 --- a/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml +++ b/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml @@ -1,22 +1,22 @@ <?xml version="1.0" encoding="UTF-8" ?> -<persistence xmlns="http://java.sun.com/xml/ns/persistence" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/persistence - http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> - - <persistence-unit name="OperationsHistoryPU" transaction-type="RESOURCE_LOCAL"> - <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> - <!-- <jar-file>packedEntity.jar</jar-file>--> - <class>org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry</class> - <properties> - <property name="eclipselink.ddl-generation" value="create-tables"/> - <property name="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver" /> - <!-- <property name="javax.persistence.jdbc.url" value="jdbc:mariadb://localhost:7779/policy"/>--> - <property name="javax.persistence.jdbc.url" value="jdbc:mariadb://localhost:3306/policy"/> - <property name="javax.persistence.jdbc.user" value="root"/> - <property name="javax.persistence.jdbc.password" value="aaaa"/> - <property name="eclipselink.logging.level" value="INFO" /> - </properties> - </persistence-unit> - +<persistence version="2.1" + xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> + + <persistence-unit name="OperationsHistoryPU" + transaction-type="RESOURCE_LOCAL"> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <!-- <jar-file>packedEntity.jar</jar-file> --> + <class>org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry</class> + <properties> + <property name="eclipselink.ddl-generation" value="create-tables" /> + <property name="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver" /> + <property name="javax.persistence.jdbc.url" value="jdbc:mariadb://localhost:3306/policy" /> + <property name="javax.persistence.jdbc.user" value="root" /> + <property name="javax.persistence.jdbc.password" value="aaaa" /> + <property name="eclipselink.logging.level" value="WARNING" /> + </properties> + </persistence-unit> + + </persistence> diff --git a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java index 6116d987e..90f61e0c9 100644 --- a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java +++ b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java @@ -30,10 +30,10 @@ import java.util.HashMap; import java.util.UUID; import org.junit.Test; -import org.onap.policy.appc.Request; -import org.onap.policy.appc.Response; -import org.onap.policy.appc.ResponseCode; -import org.onap.policy.appc.ResponseValue; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseWrapper; import org.onap.policy.controlloop.ControlLoopEventStatus; import org.onap.policy.controlloop.VirtualControlLoopEvent; @@ -53,7 +53,7 @@ public class ControlLoopOperationManagerTest { onset.requestID = UUID.randomUUID(); onset.target = "vserver.selflink"; onset.closedLoopAlarmStart = Instant.now(); - onset.AAI = new HashMap<String, String>(); + onset.AAI = new HashMap<>(); onset.AAI.put("cloud-region.identity-url", "foo"); onset.AAI.put("vserver.selflink", "bar"); onset.AAI.put("vserver.is-closed-loop-disabled", "false"); @@ -91,20 +91,24 @@ public class ControlLoopOperationManagerTest { Object request = manager.startOperation(onset); logger.debug("{}",manager); assertNotNull(request); - assertTrue(request instanceof Request); - assertTrue(((Request)request).CommonHeader.SubRequestID.contentEquals("1")); + assertTrue(request instanceof LCMRequestWrapper); + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) request; + LCMRequest appcRequest = dmaapRequest.getBody(); + assertTrue(appcRequest.getCommonHeader().getSubRequestId().contentEquals("1")); assertFalse(manager.isOperationComplete()); assertTrue(manager.isOperationRunning()); // // Accept // - Response response = new Response((Request) request); - response.Status.Code = ResponseCode.ACCEPT.getValue(); - response.Status.Value = ResponseValue.ACCEPT.toString(); + LCMResponseWrapper dmaapResponse = new LCMResponseWrapper(); + LCMResponse appcResponse = new LCMResponse((LCMRequest) appcRequest); + appcResponse.getStatus().setCode(100); + appcResponse.getStatus().setMessage("ACCEPT"); + dmaapResponse.setBody(appcResponse); // // // - PolicyResult result = manager.onResponse(response); + PolicyResult result = manager.onResponse(dmaapResponse); logger.debug("{}",manager); assertTrue(result == null); assertFalse(manager.isOperationComplete()); @@ -112,11 +116,11 @@ public class ControlLoopOperationManagerTest { // // Now we are going to Fail it // - response = new Response((Request) request); - response.Status.Code = ResponseCode.FAILURE.getValue(); - response.Status.Value = ResponseValue.FAILURE.toString(); - response.Status.Description = "AppC failed for some reason"; - result = manager.onResponse(response); + appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(401); + appcResponse.getStatus().setMessage("AppC failed for some reason"); + dmaapResponse.setBody(appcResponse); + result = manager.onResponse(dmaapResponse); logger.debug("{}",manager); assertTrue(result.equals(PolicyResult.FAILURE)); assertFalse(manager.isOperationComplete()); @@ -127,21 +131,24 @@ public class ControlLoopOperationManagerTest { request = manager.startOperation(onset); logger.debug("{}",manager); assertNotNull(request); - assertTrue(request instanceof Request); - assertTrue(((Request)request).CommonHeader.SubRequestID.contentEquals("2")); + assertTrue(request instanceof LCMRequestWrapper); + dmaapRequest = (LCMRequestWrapper) request; + appcRequest = dmaapRequest.getBody(); + assertTrue(appcRequest.getCommonHeader().getSubRequestId().contentEquals("2")); assertFalse(manager.isOperationComplete()); assertTrue(manager.isOperationRunning()); // // // - response = new Response((Request) request); + appcResponse = new LCMResponse((LCMRequest) appcRequest); logger.debug("{}",manager); - response.Status.Code = ResponseCode.ACCEPT.getValue(); - response.Status.Value = ResponseValue.ACCEPT.toString(); + appcResponse.getStatus().setCode(100); + appcResponse.getStatus().setMessage("ACCEPT"); + dmaapResponse.setBody(appcResponse); // // // - result = manager.onResponse(response); + result = manager.onResponse(dmaapResponse); logger.debug("{}",manager); assertTrue(result == null); assertFalse(manager.isOperationComplete()); @@ -149,11 +156,11 @@ public class ControlLoopOperationManagerTest { // // Now we are going to Fail it // - response = new Response((Request) request); - response.Status.Code = ResponseCode.FAILURE.getValue(); - response.Status.Value = ResponseValue.FAILURE.toString(); - response.Status.Description = "AppC failed for some reason"; - result = manager.onResponse(response); + appcResponse = new LCMResponse((LCMRequest) appcRequest); + appcResponse.getStatus().setCode(401); + appcResponse.getStatus().setMessage("AppC failed for some reason"); + dmaapResponse.setBody(appcResponse); + result = manager.onResponse(dmaapResponse); logger.debug("{}",manager); assertTrue(result.equals(PolicyResult.FAILURE)); // @@ -199,20 +206,24 @@ public class ControlLoopOperationManagerTest { Object request = manager.startOperation(onset); logger.debug("{}",manager); assertNotNull(request); - assertTrue(request instanceof Request); - assertTrue(((Request)request).CommonHeader.SubRequestID.contentEquals("1")); + assertTrue((request) instanceof LCMRequestWrapper); + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) request; + LCMRequest appcRequest = dmaapRequest.getBody(); + assertTrue((appcRequest).getCommonHeader().getSubRequestId().contentEquals("1")); assertFalse(manager.isOperationComplete()); assertTrue(manager.isOperationRunning()); // // Accept // - Response response = new Response((Request) request); - response.Status.Code = ResponseCode.ACCEPT.getValue(); - response.Status.Value = ResponseValue.ACCEPT.toString(); + LCMResponseWrapper dmaapResponse = new LCMResponseWrapper(); + LCMResponse appcResponse = new LCMResponse(appcRequest); + dmaapResponse.setBody(appcResponse); + appcResponse.getStatus().setCode(100); + appcResponse.getStatus().setMessage("ACCEPT"); // // // - PolicyResult result = manager.onResponse(response); + PolicyResult result = manager.onResponse(dmaapResponse); logger.debug("{}",manager); assertTrue(result == null); assertFalse(manager.isOperationComplete()); @@ -229,11 +240,11 @@ public class ControlLoopOperationManagerTest { // // Now we are going to Fail the previous request // - response = new Response((Request) request); - response.Status.Code = ResponseCode.FAILURE.getValue(); - response.Status.Value = ResponseValue.FAILURE.toString(); - response.Status.Description = "AppC failed for some reason"; - result = manager.onResponse(response); + appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(401); + appcResponse.getStatus().setMessage("AppC failed for some reason"); + dmaapResponse.setBody(appcResponse); + result = manager.onResponse(dmaapResponse); logger.debug("{}",manager); // // diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java index 9382203d1..d35726a64 100644 --- a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,7 +21,9 @@ package org.onap.policy.guard; import java.math.BigInteger; +import java.sql.Timestamp; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Properties; @@ -33,56 +35,59 @@ import javax.persistence.NonUniqueResultException; import javax.persistence.Persistence; import javax.persistence.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; import com.att.research.xacml.api.pip.PIPException; import com.att.research.xacml.api.pip.PIPFinder; import com.att.research.xacml.api.pip.PIPRequest; import com.att.research.xacml.api.pip.PIPResponse; import com.att.research.xacml.std.IdentifierImpl; import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.datatypes.DataTypes; import com.att.research.xacml.std.pip.StdMutablePIPResponse; import com.att.research.xacml.std.pip.StdPIPRequest; import com.att.research.xacml.std.pip.StdPIPResponse; import com.att.research.xacml.std.pip.engines.StdConfigurableEngine; -import com.att.research.xacml.api.Attribute; -import com.att.research.xacml.api.AttributeValue; -import com.att.research.xacml.api.Identifier; -import com.att.research.xacml.std.datatypes.DataTypes; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class PIPEngineGetHistory extends StdConfigurableEngine{ + private interface DateUtil{ + public long getMs(); + public DateUtil init(String sqlValUnit) throws Exception; + } - private static final Logger logger = LoggerFactory.getLogger(PIPEngineGetHistory.class); - + public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB"; - + // // Base issuer string. The issuer in the policy will also contain time window information // E.g., "com:att:research:xacml:guard:historydb:tw:10:min" // public static final String DEFAULT_ISSUER = "com:att:research:xacml:guard:historydb"; - + private static final PIPRequest PIP_REQUEST_ACTOR = new StdPIPRequest( - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"), - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:actor:actor-id"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:actor:actor-id"), new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string")); - + private static final PIPRequest PIP_REQUEST_RECIPE = new StdPIPRequest( - new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:action"), - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:operation:operation-id"), + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:action"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:operation:operation-id"), new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string")); - + private static final PIPRequest PIP_REQUEST_TARGET = new StdPIPRequest( - new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:target:target-id"), + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:target:target-id"), new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string")); - + private void addIntegerAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, int value, PIPRequest pipRequest) { AttributeValue<BigInteger> attributeValue = null; try { @@ -95,14 +100,14 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } - - + + public PIPEngineGetHistory() { super(); // TODO Auto-generated constructor stub } - - + + @Override public Collection<PIPRequest> attributesRequired() { @@ -120,7 +125,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { // TODO Auto-generated method stub logger.debug("Entering FeqLimiter PIP"); - + /* * First check to see if the issuer is set and then match it */ @@ -139,7 +144,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ return StdPIPResponse.PIP_RESPONSE_EMPTY; } } - + String[] s1 = string.split("tw:"); String[] s2 = s1[1].split(":"); String timeWindowVal = s2[0];// number [of minutes, hours, days...] @@ -148,24 +153,24 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ String actor = getActor(pipFinder).iterator().next(); String operation = getRecipe(pipFinder).iterator().next(); String target = getTarget(pipFinder).iterator().next(); - + String timeWindow = timeWindowVal + " " + timeWindowScale; - + logger.debug("Going to query DB about: {} {} {} {}", actor, operation, target, timeWindow); int countFromDB = getCountFromDB(actor, operation, target, timeWindow); - + StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse(); - + this.addIntegerAttribute(stdPIPResponse, - new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), - new IdentifierImpl("com:att:research:xacml:test:sql:resource:operations:count"), + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), + new IdentifierImpl("com:att:research:xacml:test:sql:resource:operations:count"), countFromDB, pipRequest); - + return new StdPIPResponse(stdPIPResponse); } - - + + @Override public void configure(String id, Properties properties) throws PIPException { super.configure(id, properties); @@ -178,33 +183,35 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } - - + + private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) { PIPResponse pipResponse = null; try { pipResponse = pipFinder.getMatchingAttributes(pipRequest, this); - if ((pipResponse != null) - && (pipResponse.getStatus() != null) - && (!pipResponse.getStatus().isOk())) { + if (pipResponse != null) { + if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString()); pipResponse = null; - } - if ((pipResponse != null) - && (pipResponse.getAttributes() != null) - && (pipResponse.getAttributes().isEmpty())) { + } + if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString()); logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus()); pipResponse = null; } + if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { + logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus()); + pipResponse = null; + } + } } catch (PIPException ex) { logger.error("getAttribute threw:", ex); } return pipResponse; } - - + + private Set<String> getActor(PIPFinder pipFinder) { /* * Get the AT&T UID from either the subject id or the attuid property @@ -213,7 +220,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ if (pipResponseATTUID == null) { return null; } - + /* * Iterate over all of the returned results and do the LDAP requests */ @@ -230,7 +237,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } } - + return setATTUIDs; } @@ -242,7 +249,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ if (pipResponseATTUID == null) { return null; } - + /* * Iterate over all of the returned results and do the LDAP requests */ @@ -259,11 +266,11 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } } - + return setATTUIDs; } - - + + private Set<String> getTarget(PIPFinder pipFinder) { /* * Get the AT&T UID from either the subject id or the attuid property @@ -272,7 +279,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ if (pipResponseATTUID == null) { return null; } - + /* * Iterate over all of the returned results and do the LDAP requests */ @@ -289,32 +296,93 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } } - + return setATTUIDs; } - + private static int getCountFromDB(String actor, String operation, String target, String timeWindow){ - - EntityManager em; + + EntityManager em = null; + String OpsHistPU = System.getProperty("OperationsHistoryPU"); + if(OpsHistPU == null || !OpsHistPU.equals("TestOperationsHistoryPU")){ + OpsHistPU = "OperationsHistoryPU"; + } try{ - em = Persistence.createEntityManagerFactory("OperationsHistoryPU").createEntityManager(); - }catch(Exception e){ - logger.error("getCountFromDB threw: ", e); + em = Persistence.createEntityManagerFactory(OpsHistPU).createEntityManager(); + }catch(Exception ex){ + logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", OpsHistPU); + logger.error("getCountFromDB threw: ", ex); + } + + DateUtil dateUtil = new DateUtil(){ + private long ms = 0; + private double multiplier = 0; + + @Override + public DateUtil init(String sqlValUnit) throws Exception{ + String[] split = sqlValUnit.split(" "); + if(split.length != 2){ + throw new Exception("Invalid Value Unit pair for SQL"); + } + + ms = Long.parseLong(split[0]); + + if("SECOND".compareToIgnoreCase(split[1]) == 0){ + multiplier = 1000; + } + else if("MINUTE".compareToIgnoreCase(split[1]) == 0){ + multiplier = 60000; + } + else if("HOUR".compareToIgnoreCase(split[1]) == 0){ + multiplier = 3.6e+6; + } + else if("DAY".compareToIgnoreCase(split[1]) == 0){ + multiplier = 8.64e+7; + } + else if("WEEK".compareToIgnoreCase(split[1]) == 0){ + multiplier = 6.048e+8; + } + else if("MONTH".compareToIgnoreCase(split[1]) == 0){ + multiplier = 2.628e+9; + } + else if("QUARTER".compareToIgnoreCase(split[1]) == 0){ + multiplier = 2.628e+9 * 3; + } + else if("YEAR".compareToIgnoreCase(split[1]) == 0){ + multiplier = 3.154e+10; + } + else{ + logger.error("{} not supported", split[1]); + } + + ms *= multiplier; + return this; + } + public long getMs(){ + return ms; + } + }; + + long now = new Date().getTime(); + long diff; + try { + diff = now - dateUtil.init(timeWindow).getMs(); + } catch (Exception ex) { + System.err.println("PIP thread got Exception " + ex.getLocalizedMessage()); return -1; } - + String sql = "select count(*) as count from operationshistory10 where outcome<>'Failure_Guard'" - + " and actor=:actor" - + " and operation=:operation" - + " and target=:target" - + " and endtime between date_sub(now(),interval :timeWindow) and now()"; - - Query nq = em.createNativeQuery(sql); - nq = nq.setParameter("actor", actor); - nq = nq.setParameter("operation", operation); - nq = nq.setParameter("target", target); - nq = nq.setParameter("timeWindow", timeWindow); - + + " and actor= ?" + + " and operation= ?" + + " and target= ?" + + " and endtime between '" + new Timestamp(diff) + "' and '" + new Timestamp(now) + "'"; + + Query nq = em.createNativeQuery(sql); + nq.setParameter(1, actor); + nq.setParameter(2, operation); + nq.setParameter(3, target); + int ret = -1; try{ ret = ((Number)nq.getSingleResult()).intValue(); @@ -323,12 +391,12 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ logger.error("getCountFromDB threw: ", ex); return -1; } - + em.close(); - - return ret; - + + return ret; + } -}
\ No newline at end of file +} diff --git a/controlloop/common/model-impl/aai/src/main/java/org/onap/policy/aai/AAINQF199/AAINQF199GenericVNF.java b/controlloop/common/model-impl/aai/src/main/java/org/onap/policy/aai/AAINQF199/AAINQF199GenericVNF.java index 8d667bb75..eb19ad95e 100644 --- a/controlloop/common/model-impl/aai/src/main/java/org/onap/policy/aai/AAINQF199/AAINQF199GenericVNF.java +++ b/controlloop/common/model-impl/aai/src/main/java/org/onap/policy/aai/AAINQF199/AAINQF199GenericVNF.java @@ -75,6 +75,9 @@ public class AAINQF199GenericVNF implements Serializable { @SerializedName("persona-model-version") public String personaModelVersion; + + @SerializedName("model-invariant-id") + public String modelInvariantId; public AAINQF199GenericVNF() { } diff --git a/controlloop/common/model-impl/appc/pom.xml b/controlloop/common/model-impl/appc/pom.xml index ae6ff0f5f..fc99a19ed 100644 --- a/controlloop/common/model-impl/appc/pom.xml +++ b/controlloop/common/model-impl/appc/pom.xml @@ -33,7 +33,7 @@ <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> - <scope>provided</scope> + <scope>test</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> diff --git a/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/CommonHeader.java b/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/CommonHeader.java index 4df25ecc5..1e92744ef 100644 --- a/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/CommonHeader.java +++ b/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/CommonHeader.java @@ -36,8 +36,8 @@ public class CommonHeader implements Serializable { public String OriginatorID; public UUID RequestID; public String SubRequestID; - public Collection<String> RequestTrack = new ArrayList<String>(); - public Collection<Map<String, String>> Flags = new ArrayList<Map<String, String>>(); + public Collection<String> RequestTrack = new ArrayList<>(); + public Collection<Map<String, String>> Flags = new ArrayList<>(); public CommonHeader() { diff --git a/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Request.java b/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Request.java index fbf0d8ee5..a9634a7b2 100644 --- a/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Request.java +++ b/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Request.java @@ -32,7 +32,7 @@ public class Request implements Serializable{ public String Action; public String TargetID; public String ObjectID; - public Map<String, Object> Payload = new HashMap<String, Object>(); + public Map<String, Object> Payload = new HashMap<>(); public Request() { diff --git a/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Response.java b/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Response.java index f9f494625..0aeb1d483 100644 --- a/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Response.java +++ b/controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Response.java @@ -30,7 +30,7 @@ public class Response implements Serializable { public CommonHeader CommonHeader; public ResponseStatus Status = new ResponseStatus(); - public Map<String, Object> Payload = new HashMap<String, Object>(); + public Map<String, Object> Payload = new HashMap<>(); public Response() { diff --git a/controlloop/common/model-impl/appclcm/pom.xml b/controlloop/common/model-impl/appclcm/pom.xml new file mode 100644 index 000000000..a882cb46c --- /dev/null +++ b/controlloop/common/model-impl/appclcm/pom.xml @@ -0,0 +1,45 @@ +<!-- + ============LICENSE_START======================================================= + Drools PDP Application Models + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>appclcm</artifactId> + + <parent> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>model-impl</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.5</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMCommonHeader.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMCommonHeader.java new file mode 100644 index 000000000..e2f520ad8 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMCommonHeader.java @@ -0,0 +1,233 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import java.io.Serializable; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.google.gson.annotations.SerializedName; + +public class LCMCommonHeader implements Serializable { + + private static final long serialVersionUID = 6581963539127062114L; + + @SerializedName(value="timestamp") + private Instant timeStamp = Instant.now(); + + @SerializedName(value="api-ver") + private String apiVer="5.00"; + + @SerializedName(value="originator-id") + private String originatorId; + + @SerializedName(value="request-id") + private UUID requestId; + + @SerializedName(value="sub-request-id") + private String subRequestId; + + @SerializedName(value="flags") + private Map<String, String> flags = new HashMap<>(); + + public LCMCommonHeader() { + + } + + /** + * Used to copy a common header. + * + * @param commonHeader + * a header that is defined by the lcm api guide that contains + * information about the request (requestId, flags, etc.) + */ + public LCMCommonHeader(LCMCommonHeader commonHeader) { + this.originatorId = commonHeader.originatorId; + this.requestId = commonHeader.requestId; + this.subRequestId = commonHeader.subRequestId; + if (commonHeader.flags != null) { + this.flags.putAll(commonHeader.flags); + } + } + + /** + * @return the timeStamp + */ + public Instant getTimeStamp() { + return timeStamp; + } + + /** + * @param timeStamp the timeStamp to set + */ + public void setTimeStamp(Instant timeStamp) { + this.timeStamp = timeStamp; + } + + /** + * @return the apiVer + */ + public String getApiVer() { + return apiVer; + } + + /** + * @param apiVer the apiVer to set + */ + public void setApiVer(String apiVer) { + this.apiVer = apiVer; + } + + /** + * @return the originatorId + */ + public String getOriginatorId() { + return originatorId; + } + + /** + * @param originatorId the originatorId to set + */ + public void setOriginatorId(String originatorId) { + this.originatorId = originatorId; + } + + /** + * @return the requestId + */ + public UUID getRequestId() { + return requestId; + } + + /** + * @param requestId the requestId to set + */ + public void setRequestId(UUID requestId) { + this.requestId = requestId; + } + + /** + * @return the subRequestId + */ + public String getSubRequestId() { + return subRequestId; + } + + /** + * @param subRequestId the subRequestId to set + */ + public void setSubRequestId(String subRequestId) { + this.subRequestId = subRequestId; + } + + /** + * @return the flags + */ + public Map<String, String> getFlags() { + return flags; + } + + /** + * @param flags the flags to set + */ + public void setFlags(Map<String, String> flags) { + this.flags = flags; + } + + @Override + public String toString() { + return "CommonHeader [timeStamp=" + timeStamp + ", apiVer=" + apiVer + ", originatorId=" + originatorId + + ", requestId=" + requestId + ", subRequestId=" + subRequestId + ", flags=" + flags + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((apiVer == null) ? 0 : apiVer.hashCode()); + result = prime * result + ((flags == null) ? 0 : flags.hashCode()); + result = prime * result + ((originatorId == null) ? 0 : originatorId.hashCode()); + result = prime * result + ((requestId == null) ? 0 : requestId.hashCode()); + result = prime * result + ((subRequestId == null) ? 0 : subRequestId.hashCode()); + result = prime * result + ((timeStamp == null) ? 0 : timeStamp.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMCommonHeader other = (LCMCommonHeader) obj; + if (apiVer == null) { + if (other.apiVer != null) { + return false; + } + } else if (!apiVer.equals(other.apiVer)) { + return false; + } + if (flags == null) { + if (other.flags != null) { + return false; + } + } else if (!flags.equals(other.flags)) { + return false; + } + if (originatorId == null) { + if (other.originatorId != null) { + return false; + } + } else if (!originatorId.equals(other.originatorId)) { + return false; + } + if (requestId == null) { + if (other.requestId != null) { + return false; + } + } else if (!requestId.equals(other.requestId)) { + return false; + } + if (subRequestId == null) { + if (other.subRequestId != null) { + return false; + } + } else if (!subRequestId.equals(other.subRequestId)) { + return false; + } + if (timeStamp == null) { + if (other.timeStamp != null) { + return false; + } + } else if (!timeStamp.equals(other.timeStamp)) { + return false; + } + return true; + } + +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequest.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequest.java new file mode 100644 index 000000000..51db7fef0 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequest.java @@ -0,0 +1,161 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import java.io.Serializable; +import java.util.Map; + +import com.google.gson.annotations.SerializedName; + +public class LCMRequest implements Serializable { + + private static final long serialVersionUID = 219375564922846624L; + + @SerializedName(value="common-header") + private LCMCommonHeader commonHeader; + + @SerializedName(value="action") + private String action; + + @SerializedName(value="action-identifiers") + private Map<String, String> actionIdentifiers; + + @SerializedName(value="payload") + private String payload; + + public LCMRequest() { + + } + + public LCMCommonHeader getCommonHeader() { + return commonHeader; + } + + /** + * @return the action + */ + public String getAction() { + return action; + } + + /** + * @param action the action to set + */ + public void setAction(String action) { + this.action = action; + } + + /** + * @return the actionIdentifiers + */ + public Map<String, String> getActionIdentifiers() { + return actionIdentifiers; + } + + /** + * @param actionIdentifiers the actionIdentifiers to set + */ + public void setActionIdentifiers(Map<String, String> actionIdentifiers) { + this.actionIdentifiers = actionIdentifiers; + } + + /** + * @return the payload + */ + public String getPayload() { + return payload; + } + + /** + * @param payload the payload to set + */ + public void setPayload(String payload) { + this.payload = payload; + } + + /** + * @param commonHeader the commonHeader to set + */ + public void setCommonHeader(LCMCommonHeader commonHeader) { + this.commonHeader = commonHeader; + } + + @Override + public String toString() { + return "Request [commonHeader=" + commonHeader + ", action=" + action + ", actionIdentifiers=" + + actionIdentifiers + ", payload=" + payload + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((commonHeader == null) ? 0 : commonHeader.hashCode()); + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + ((actionIdentifiers == null) ? 0 : actionIdentifiers.hashCode()); + result = prime * result + ((payload == null) ? 0 : payload.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMRequest other = (LCMRequest) obj; + if (commonHeader == null) { + if (other.commonHeader != null) { + return false; + } + } else if (!commonHeader.equals(other.commonHeader)) { + return false; + } + if (action == null) { + if (other.action != null) { + return false; + } + } else if (!action.equals(other.action)) { + return false; + } + if (actionIdentifiers == null) { + if (other.actionIdentifiers != null) { + return false; + } + } else if (!actionIdentifiers.equals(other.actionIdentifiers)) { + return false; + } + if (payload == null) { + if (other.payload != null) { + return false; + } + } else if (!payload.equals(other.payload)) { + return false; + } + return true; + } + +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequestWrapper.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequestWrapper.java new file mode 100644 index 000000000..ea7e6762f --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequestWrapper.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + +public class LCMRequestWrapper extends LCMWrapper implements Serializable { + + private static final long serialVersionUID = 424866914715980798L; + + @SerializedName(value="body") + private LCMRequest body; + + public LCMRequestWrapper() { + super(); + } + + public LCMRequestWrapper(LCMRequest request) { + body = request; + } + + /** + * @return the body + */ + public LCMRequest getBody() { + return body; + } + + /** + * @param body the body to set + */ + public void setBody(LCMRequest body) { + this.body = body; + } + + @Override + public String toString() { + return "RequestWrapper [body=" + body + ", toString()=" + super.toString() + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((body == null) ? 0 : body.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMRequestWrapper other = (LCMRequestWrapper) obj; + if (body == null) { + if (other.body != null) { + return false; + } + } else if (!body.equals(other.body)) { + return false; + } + return true; + } + +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponse.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponse.java new file mode 100644 index 000000000..003dc573b --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponse.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + +public class LCMResponse implements Serializable { + + private static final long serialVersionUID = 6332508597287669750L; + + @SerializedName(value = "common-header") + private LCMCommonHeader commonHeader; + + @SerializedName(value = "status") + private LCMResponseStatus status = new LCMResponseStatus(); + + @SerializedName(value = "payload") + private String payload; + + public LCMResponse() { + + } + + /** + * Constructs a response using the common header of the request since they + * will be the same. + * + * @param request + * an appc lcm request object specified by the lcm api guide + */ + public LCMResponse(LCMRequest request) { + this.commonHeader = new LCMCommonHeader(request.getCommonHeader()); + String requestPayload = request.getPayload(); + if (requestPayload != null) { + // this.payload.putAll(request.payload); + this.payload = requestPayload; + } + } + + /** + * @return the commonHeader + */ + public LCMCommonHeader getCommonHeader() { + return commonHeader; + } + + /** + * @param commonHeader the commonHeader to set + */ + public void setCommonHeader(LCMCommonHeader commonHeader) { + this.commonHeader = commonHeader; + } + + /** + * @return the status + */ + public LCMResponseStatus getStatus() { + return status; + } + + /** + * @param status the status to set + */ + public void setStatus(LCMResponseStatus status) { + this.status = status; + } + + /** + * @return the payload + */ + public String getPayload() { + return payload; + } + + /** + * @param payload the payload to set + */ + public void setPayload(String payload) { + this.payload = payload; + } + + @Override + public String toString() { + return "Response [commonHeader=" + commonHeader + ", status=" + status + ", payload=" + payload + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((commonHeader == null) ? 0 : commonHeader.hashCode()); + result = prime * result + ((payload == null) ? 0 : payload.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMResponse other = (LCMResponse) obj; + if (commonHeader == null) { + if (other.commonHeader != null) { + return false; + } + } else if (!commonHeader.equals(other.commonHeader)) { + return false; + } + if (payload == null) { + if (other.payload != null) { + return false; + } + } else if (!payload.equals(other.payload)) { + return false; + } + if (status == null) { + if (other.status != null) { + return false; + } + } else if (!status.equals(other.status)) { + return false; + } + return true; + } +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseCode.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseCode.java new file mode 100644 index 000000000..484e793e2 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseCode.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +public class LCMResponseCode { + + /* These fields define the key to the response code value. */ + public static final String ACCEPTED = "ACCEPTED"; + public static final String ERROR = "ERROR"; + public static final String REJECT = "REJECT"; + public static final String SUCCESS = "SUCCESS"; + public static final String FAILURE = "FAILURE"; + public static final String PARTIAL_SUCCESS = "PARTIAL SUCCESS"; + public static final String PARTIAL_FAILURE = "PARTIAL FAILURE"; + + private Integer code; + + private LCMResponseCode(int code) { + this.code = code; + } + + public int getCode() { + return this.code; + } + + public String toString() { + return Integer.toString(this.code); + } + + /** + * Translates the code to a string value that represents the meaning of the code. + * + * @param code + * the numeric value that is returned by APPC based on success, + * failure, etc. of the action requested + * @return the string value equivalent of the APPC response code + */ + public static String toResponseValue(int code) { + if (code == 100) { + return ACCEPTED; + } + else if (code == 200) { + return ERROR; + } + else if (code >= 300 && code <= 313) { + return REJECT; + } + else if (code == 400) { + return SUCCESS; + } + else if (code == 450 || (code >= 401 && code <= 406)) { + return FAILURE; + } + else if (code == 500) { + return PARTIAL_SUCCESS; + } + else if (code >= 501 && code <= 599) { + return PARTIAL_FAILURE; + } + return null; + } +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseStatus.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseStatus.java new file mode 100644 index 000000000..131e331bf --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseStatus.java @@ -0,0 +1,107 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + +public class LCMResponseStatus implements Serializable { + + private static final long serialVersionUID = 974891505135467199L; + + @SerializedName(value="code") + private int code; + + @SerializedName(value="message") + private String message; + + public LCMResponseStatus() { + + } + + /** + * @return the code + */ + public int getCode() { + return code; + } + + /** + * @param code the code to set + */ + public void setCode(int code) { + this.code = code; + } + + /** + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * @param message the message to set + */ + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "ResponseStatus [code=" + code + ", message=" + message + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + code; + result = prime * result + ((message == null) ? 0 : message.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMResponseStatus other = (LCMResponseStatus) obj; + if (code != other.code) { + return false; + } + if (message == null) { + if (other.message != null) { + return false; + } + } else if (!message.equals(other.message)) { + return false; + } + return true; + } + +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseWrapper.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseWrapper.java new file mode 100644 index 000000000..7d9062979 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseWrapper.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + +public class LCMResponseWrapper extends LCMWrapper implements Serializable { + + private static final long serialVersionUID = 463937813781086802L; + + @SerializedName(value="body") + private LCMResponse body; + + public LCMResponseWrapper() { + super(); + } + + /** + * @return the body + */ + public LCMResponse getBody() { + return body; + } + + /** + * @param body the body to set + */ + public void setBody(LCMResponse body) { + this.body = body; + } + + @Override + public String toString() { + return "ResponseWrapper [body=" + body + ", toString()=" + super.toString() + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((body == null) ? 0 : body.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMResponseWrapper other = (LCMResponseWrapper) obj; + if (body == null) { + if (other.body != null) { + return false; + } + } else if (!body.equals(other.body)) { + return false; + } + return true; + } +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMWrapper.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMWrapper.java new file mode 100644 index 000000000..c9f72c2e2 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMWrapper.java @@ -0,0 +1,187 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + +public class LCMWrapper implements Serializable { + + private static final long serialVersionUID = 753005805432396532L; + + @SerializedName(value="version") + private String version; + + @SerializedName(value="cambria-partition") + private String cambriaPartition; + + @SerializedName(value="rpc-name") + private String rpcName; + + @SerializedName(value="correlation-id") + private String correlationId; + + @SerializedName(value="type") + private String type; + + public LCMWrapper() { + + } + + /** + * @return the version + */ + public String getVersion() { + return version; + } + + /** + * @param version the version to set + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * @return the cambriaPartition + */ + public String getCambriaPartition() { + return cambriaPartition; + } + + /** + * @param cambriaPartition the cambriaPartition to set + */ + public void setCambriaPartition(String cambriaPartition) { + this.cambriaPartition = cambriaPartition; + } + + /** + * @return the rpcName + */ + public String getRpcName() { + return rpcName; + } + + /** + * @param rpcName the rpcName to set + */ + public void setRpcName(String rpcName) { + this.rpcName = rpcName; + } + + /** + * @return the correlationId + */ + public String getCorrelationId() { + return correlationId; + } + + /** + * @param correlationId the correlationId to set + */ + public void setCorrelationId(String correlationId) { + this.correlationId = correlationId; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + @Override + public String toString() { + return "Wrapper [version=" + version + ", cambriaPartition=" + cambriaPartition + ", rpcName=" + rpcName + + ", correlationId=" + correlationId + ", type=" + type + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((cambriaPartition == null) ? 0 : cambriaPartition.hashCode()); + result = prime * result + ((correlationId == null) ? 0 : correlationId.hashCode()); + result = prime * result + ((rpcName == null) ? 0 : rpcName.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LCMWrapper other = (LCMWrapper) obj; + if (cambriaPartition == null) { + if (other.cambriaPartition != null) { + return false; + } + } else if (!cambriaPartition.equals(other.cambriaPartition)) { + return false; + } + if (correlationId == null) { + if (other.correlationId != null) { + return false; + } + } else if (!correlationId.equals(other.correlationId)) { + return false; + } + if (rpcName == null) { + if (other.rpcName != null) { + return false; + } + } else if (!rpcName.equals(other.rpcName)) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + if (version == null) { + if (other.version != null) { + return false; + } + } else if (!version.equals(other.version)) { + return false; + } + return true; + } + +} diff --git a/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/util/Serialization.java b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/util/Serialization.java new file mode 100644 index 000000000..7187ab1e7 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/util/Serialization.java @@ -0,0 +1,101 @@ +/*- + * ============LICENSE_START======================================================= + * appc + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm.util; + +import java.lang.reflect.Type; +import java.time.Instant; + +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMResponse; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public final class Serialization { + + public static class RequestAdapter implements JsonSerializer<LCMRequest>, JsonDeserializer<LCMRequest> { + + @Override + public JsonElement serialize(LCMRequest src, Type typeOfSrc, JsonSerializationContext context) { + JsonElement requestJson = gsonPretty.toJsonTree(src, LCMRequest.class); + JsonObject input = new JsonObject(); + input.add("input", requestJson); + + return input; + } + + @Override + public LCMRequest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + LCMRequest request = gsonPretty.fromJson(json.getAsJsonObject().get("input"), LCMRequest.class); + return request; + } + } + + public static class ResponseAdapter implements JsonSerializer<LCMResponse>, JsonDeserializer<LCMResponse> { + + @Override + public JsonElement serialize(LCMResponse src, Type typeOfSrc, JsonSerializationContext context) { + JsonElement responseJson = gsonPretty.toJsonTree(src, LCMResponse.class); + JsonObject output = new JsonObject(); + output.add("output", responseJson); + return output; + } + + @Override + public LCMResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + LCMResponse response = gsonPretty.fromJson(json.getAsJsonObject().get("output"), LCMResponse.class); + return response; + } + } + + public static class InstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> { + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return Instant.parse(json.getAsString()); + } + + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.toString()); + } + + } + + public static final Gson gsonPretty = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting() + .registerTypeAdapter(Instant.class, new InstantAdapter()).create(); + + public static final Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting() + .registerTypeAdapter(LCMRequest.class, new RequestAdapter()) + .registerTypeAdapter(LCMResponse.class, new ResponseAdapter()).create(); + +} diff --git a/controlloop/common/model-impl/appclcm/src/main/resources/definitions.yaml b/controlloop/common/model-impl/appclcm/src/main/resources/definitions.yaml new file mode 100644 index 000000000..680a9929c --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/main/resources/definitions.yaml @@ -0,0 +1,118 @@ +### +# ============LICENSE_START======================================================= +# appc +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +Request: + type: object + properties: + CommonHeader: + type: object + properties: + TimeStamp: + type: string + APIver: + type: string + value: '1.01' + OriginatorID: + type: string + RequestID: + type: string + pattern: "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + SubRequestID: + type: string + Flags: + type: object + required: + - TimeStamp + - APIver + - OriginatorID + - RequestID + Action: + type: string + enum: + - Audit + - ActionStatus + - BlockAudits + - Configure + - HealthCheck + - Install + - LiveUpgrade + - Migrate + - ModifyConfig + - Query + - Rebuild + - Reconfigure + - Restart + - Rollback + - Scale + - Start + - Stop + - Sync + - Terminate + - Test + - Upgrade + TargetID: + type: string + ObjectID: + type: string + Payload: + type: object + required: + - CommonHeader + - Action + - TargetID +Response: + type: object + properties: + CommonHeader: + type: object + properties: + TimeStamp: + type: string + APIver: + type: string + OriginatorID: + type: string + RequestID: + type: string + SubRequestID: + type: string + Flags: + type: object + required: + - TimeStamp + - APIver + - OriginatorID + - RequestID + Status: + type: object + properties: + Code: + type: integer + Value: + type: string + required: + - Code + - Value + Payload: + type: object + required: + - CommonHeader + - Status + diff --git a/controlloop/common/model-impl/appclcm/src/test/java/org/onap/policy/appclcm/AppcLcmTest.java b/controlloop/common/model-impl/appclcm/src/test/java/org/onap/policy/appclcm/AppcLcmTest.java new file mode 100644 index 000000000..41bafe498 --- /dev/null +++ b/controlloop/common/model-impl/appclcm/src/test/java/org/onap/policy/appclcm/AppcLcmTest.java @@ -0,0 +1,244 @@ +/*- + * ============LICENSE_START======================================================= + * appclcm + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.appclcm; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.onap.policy.appclcm.util.Serialization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmTest { + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmTest.class); + + private static LCMRequestWrapper dmaapRequest; + private static LCMResponseWrapper dmaapResponse; + + static { + /* + * Construct an APPCLCM Request to be Serialized + */ + dmaapRequest = new LCMRequestWrapper(); + dmaapRequest.setCorrelationId("664be3d2-6c12-4f4b-a3e7-c349acced200" + "-" + "1"); + dmaapRequest.setRpcName("restart"); + dmaapRequest.setType("request"); + + dmaapResponse = new LCMResponseWrapper(); + dmaapResponse.setCorrelationId("664be3d2-6c12-4f4b-a3e7-c349acced200" + "-" + "1"); + dmaapResponse.setRpcName("restart"); + dmaapResponse.setType("response"); + + LCMRequest appcRequest = new LCMRequest(); + + appcRequest.setAction("restart"); + + HashMap<String, String> actionIdentifiers = new HashMap<>(); + actionIdentifiers.put("vnf-id", "trial-vnf-003"); + actionIdentifiers.put("vserver-id", "08f6c1f9-99e7-49f3-a662-c62b9f200d79"); + + appcRequest.setActionIdentifiers(actionIdentifiers); + + LCMCommonHeader commonHeader = new LCMCommonHeader(); + commonHeader.setRequestId(UUID.fromString("664be3d2-6c12-4f4b-a3e7-c349acced200")); + commonHeader.setSubRequestId("1"); + commonHeader.setOriginatorId("664be3d2-6c12-4f4b-a3e7-c349acced200"); + + appcRequest.setCommonHeader(commonHeader); + + appcRequest.setPayload(null); + + dmaapRequest.setBody(appcRequest); + + /* + * Construct an APPCLCM Response to be Serialized + */ + LCMResponse appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("Restart Successful"); + appcResponse.setPayload(null); + + dmaapResponse.setBody(appcResponse); + } + + @Test + public void testRequestSerialization() { + + /* + * Use the gson serializer to obtain json + */ + String jsonRequest = Serialization.gson.toJson(dmaapRequest, LCMRequestWrapper.class); + assertNotNull(jsonRequest); + + /* + * The serializer should have added an extra + * sub-tag called "input" that wraps the request + */ + assertTrue(jsonRequest.contains("input")); + + /* + * The common-header, request-id, and + * sub-request-id should exist + */ + assertTrue(jsonRequest.contains("common-header")); + assertTrue(jsonRequest.contains("request-id")); + assertTrue(jsonRequest.contains("sub-request-id")); + + /* + * action-identifiers should exist and contain + * a vnf-id + */ + assertTrue(jsonRequest.contains("action-identifiers")); + assertTrue(jsonRequest.contains("vnf-id")); + + /* + * The action sub-tag should exist + */ + assertTrue(jsonRequest.contains("action")); + + logger.debug("Request as JSON: " + jsonRequest + "\n\n"); + } + + @Test + public void testRequestDeserialization() { + + /* + * Convert the LCM request object into json + * so we have a string of json to use for testing + */ + String jsonRequest = Serialization.gson.toJson(dmaapRequest, LCMRequestWrapper.class); + + /* + * Use the serializer to convert the json string + * into a java object + */ + LCMRequestWrapper dmaapRequest = Serialization.gson.fromJson(jsonRequest, LCMRequestWrapper.class); + assertNotNull(dmaapRequest); + + /* + * The type of the DMAAP wrapper should be request + */ + assertEquals(dmaapRequest.getType(), "request"); + + /* + * The DMAAP wrapper must have a body as that is + * the true APPC request + */ + assertNotNull(dmaapRequest.getBody()); + LCMRequest appcRequest = dmaapRequest.getBody(); + assertNotNull(appcRequest); + + /* + * The common header should not be null + */ + assertNotNull(appcRequest.getCommonHeader()); + + /* + * The action should not be null and should be + * set to restart + */ + assertNotNull(appcRequest.getAction()); + assertEquals(appcRequest.getAction(), "restart"); + + /* + * The action-identifiers should not be null + * and should contain a vnf-id + */ + assertNotNull(appcRequest.getActionIdentifiers()); + assertNotNull(appcRequest.getActionIdentifiers().get("vnf-id")); + + logger.debug("Request as a Java Object: \n" + appcRequest.toString() + "\n\n"); + } + + @Test + public void testResponseSerialization() { + + /* + * Use the serializer to convert the object into json + */ + String jsonResponse = Serialization.gson.toJson(dmaapResponse, LCMResponseWrapper.class); + assertNotNull(jsonResponse); + + /* + * The serializer should have added an extra + * sub-tag called "input" that wraps the request + */ + assertTrue(jsonResponse.contains("output")); + + /* + * The response should contain a common-header, + * request-id, sub-request-id, and status + */ + assertTrue(jsonResponse.contains("common-header")); + assertTrue(jsonResponse.contains("request-id")); + assertTrue(jsonResponse.contains("sub-request-id")); + assertTrue(jsonResponse.contains("status")); + + logger.debug("Response as JSON: " + jsonResponse + "\n\n"); + } + + @Test + public void testResponseDeserialization() { + /* + * Convert the LCM response object into json + * so we have a string of json to use for testing + */ + String jsonResponse = Serialization.gson.toJson(dmaapResponse, LCMResponseWrapper.class); + + /* + * Use the serializer to convert the json string + * into a java object + */ + LCMResponseWrapper dmaapResponse = Serialization.gson.fromJson(jsonResponse, LCMResponseWrapper.class); + assertNotNull(dmaapResponse); + + /* + * The type of the DMAAP wrapper should be response + */ + assertEquals(dmaapResponse.getType(), "response"); + + /* + * The DMAAP wrapper must have a body as that is + * the true APPC response + */ + assertNotNull(dmaapResponse.getBody()); + LCMResponse appcResponse = dmaapResponse.getBody(); + assertNotNull(appcResponse); + + /* + * The common header should not be null + */ + assertNotNull(appcResponse.getCommonHeader()); + + /* + * The status should not be null and the + * status code should be 400 + */ + assertNotNull(appcResponse.getStatus()); + assertEquals(appcResponse.getStatus().getCode(), 400); + + logger.debug("Response as a Java Object: \n" + appcResponse.toString() + "\n\n"); + } +} diff --git a/controlloop/common/model-impl/pom.xml b/controlloop/common/model-impl/pom.xml index 5d18e4916..e96befbf7 100644 --- a/controlloop/common/model-impl/pom.xml +++ b/controlloop/common/model-impl/pom.xml @@ -35,6 +35,7 @@ <modules> <module>aai</module> <module>appc</module> + <module>appclcm</module> <module>events</module> <module>mso</module> <module>rest</module> diff --git a/controlloop/templates/template.demo/pom.xml b/controlloop/templates/template.demo/pom.xml index c0aef2074..eb85f7fdc 100644 --- a/controlloop/templates/template.demo/pom.xml +++ b/controlloop/templates/template.demo/pom.xml @@ -7,9 +7,9 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -67,6 +67,18 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>appclcm</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>trafficgenerator</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>vfc</artifactId> <version>${project.version}</version> <scope>provided</scope> @@ -151,6 +163,12 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>actor.appclcm</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>actor.vfc</artifactId> <version>${project.version}</version> <scope>provided</scope> @@ -179,5 +197,11 @@ <version>${project.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>[1.4.186,)</version> + <scope>test</scope> + </dependency> </dependencies> -</project>
\ No newline at end of file +</project> diff --git a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl index 276e64b7d..aa1f1e977 100644 --- a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl +++ b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl @@ -32,6 +32,11 @@ import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager; import org.onap.policy.appc.Request; import org.onap.policy.appc.Response; import org.onap.policy.appc.CommonHeader; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponseWrapper; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMCommonHeader; import org.onap.policy.vfc.VFCRequest; import org.onap.policy.vfc.VFCManager; import org.onap.policy.guard.PolicyGuard; @@ -490,7 +495,7 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED" case "APPC": - if (request instanceof Request) { + if (request instanceof Request || request instanceof LCMRequestWrapper) { Engine.deliver("UEB", "APPC-CL", request); } break; @@ -771,6 +776,122 @@ rule "${policyName}.APPC.RESPONSE.CLEANUP" // retract($response); end + +/* +* +* This rule responds to APPC Response Events using the new LCM interface provided by appc +* +*/ +rule "${policyName}.APPC.LCM.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $lock : TargetLock (requestID == $event.requestID) + $response : LCMResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.requestID ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + Logger.metrics($response); + // + // Get the result of the operation + // + PolicyResult policyResult = $operation.onResponse($response); + if (policyResult != null) { + Logger.info("operation finished with result: " + policyResult); + // + // This Operation has completed, construct a notification showing our results. (DB write - end operation) + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + if (policyResult.equals(PolicyResult.SUCCESS)) { + notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } else { + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // We must also retract the timer object + // NOTE: We could write a Rule to do this + // + retract($opTimer); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } + } else { + // + // Its not finished yet (i.e. expecting more Response objects) + // + // Or possibly it is a leftover response that we timed the request out previously + // + } + // + // We are going to retract these objects from memory + // + retract($response); +end + +/* +* +* Clean Up any lingering LCM reponses +* +*/ +rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $response : LCMResponseWrapper($id : getBody().getCommonHeader().getRequestId ) + not ( VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + // + // Retract it + // + retract($response); +end + /* * * This is the timer that manages the timeout for an individual operation. diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java index 3bdeca1fc..3bddbc50d 100644 --- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,7 +27,6 @@ import java.util.UUID; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.aai.AAIGETResponse; import org.onap.policy.aai.AAINQF199.AAINQF199Manager; @@ -36,7 +35,7 @@ import org.onap.policy.aai.AAINQF199.AAINQF199Response; import org.onap.policy.drools.http.server.HttpServletServer; public class AaiSimulatorTest { - + @BeforeClass public static void setUpSimulator() { try { @@ -45,12 +44,12 @@ public class AaiSimulatorTest { fail(e.getMessage()); } } - + @AfterClass public static void tearDownSimulator() { HttpServletServer.factory.destroy(); } - + @Test public void testGet() { AAIGETResponse response = AAINQF199Manager.getQuery("http://localhost:6666", "testUser", "testPass", UUID.randomUUID(), "5e49ca06-2972-4532-9ed4-6d071588d792"); diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java index 23f03f7e8..d1fa4fc10 100644 --- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,49 +32,74 @@ import java.time.Instant; import java.util.HashMap; import java.util.UUID; -import org.junit.Ignore; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.rule.FactHandle; -import org.onap.policy.appc.Request; -import org.onap.policy.appc.Response; -import org.onap.policy.appc.ResponseCode; -import org.onap.policy.appc.ResponseValue; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseWrapper; import org.onap.policy.controlloop.ControlLoopEventStatus; import org.onap.policy.controlloop.ControlLoopNotificationType; - import org.onap.policy.controlloop.VirtualControlLoopEvent; import org.onap.policy.controlloop.VirtualControlLoopNotification; import org.onap.policy.controlloop.policy.ControlLoopPolicy; import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.http.server.HttpServletServer; import org.onap.policy.drools.impl.PolicyEngineJUnitImpl; import org.onap.policy.guard.PolicyGuard; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -//import org.onap.policy.controlloop.policy.guard.ControlLoopGuard; + public class ControlLoopXacmlGuardTest { + @BeforeClass + public static void setUpSimulator() { + try { + Util.buildAaiSim(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + } + + @AfterClass + public static void tearDownSimulator() { + HttpServletServer.factory.destroy(); + } + private static final Logger logger = LoggerFactory.getLogger(ControlLoopXacmlGuardTest.class); - + private static final String OPSHISTPUPROP = "OperationsHistoryPU"; + @BeforeClass + public static void setPUProp(){ + System.setProperty(OPSHISTPUPROP, "TestOperationsHistoryPU"); + } + @AfterClass + public static void restorePUProp(){ + System.setProperty(OPSHISTPUPROP, OPSHISTPUPROP); + } + + @Test public void test() { try { - this.runTest("src/main/resources/ControlLoop_Template_xacml_guard.drl", + this.runTest("src/main/resources/ControlLoop_Template_xacml_guard.drl", "src/test/resources/yaml/policy_ControlLoop_Service123.yaml", - "service=Service123;resource=Res123;type=operational", - "CL_SERV123_8888", + "service=Service123;resource=Res123;type=operational", + "CL_SERV123_8888", "org.onap.closed_loop.Service123:VNFS:0.0.1"); } catch (IOException e) { e.printStackTrace(); fail(e.getMessage()); } } - - public void runTest(String droolsTemplate, - String yamlFile, - String policyScope, - String policyName, + + public void runTest(String droolsTemplate, + String yamlFile, + String policyScope, + String policyName, String policyVersion) throws IOException { // // Pull info from the yaml @@ -88,20 +113,21 @@ public class ControlLoopXacmlGuardTest { // // Build a container // - final KieSession kieSession = Util.buildContainer(droolsTemplate, - pair.a.getControlLoop().getControlLoopName(), - policyScope, - policyName, - policyVersion, + final KieSession kieSession = Util.buildContainer(droolsTemplate, + pair.a.getControlLoop().getControlLoopName(), + policyScope, + policyName, + policyVersion, URLEncoder.encode(pair.b, "UTF-8")); - - + + + logger.debug("============"); logger.debug(URLEncoder.encode(pair.b, "UTF-8")); logger.debug("============"); - + final PolicyEngineJUnitImpl engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine"); - + // // Initial fire of rules // @@ -115,17 +141,17 @@ public class ControlLoopXacmlGuardTest { @Override public void run() { try { - - + + // // Let's use a unique ID for the request and // a unique trigger source. // UUID requestID = UUID.randomUUID(); String triggerSourceName = "foobartriggersource36"; - + Object obj = null; - + sendGoodEvents(kieSession, pair.a, requestID, triggerSourceName); obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); @@ -134,9 +160,9 @@ public class ControlLoopXacmlGuardTest { // // Give the control loop a little time to acquire the lock and publish the request // - Thread.sleep(2000); - - + Thread.sleep(4000); + + // "About to query Guard" notification (Querying about Restart) obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); @@ -144,18 +170,18 @@ public class ControlLoopXacmlGuardTest { logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - Thread.sleep(2000); + + Thread.sleep(4000); // "Response from Guard" notification obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - + + if(true == ((VirtualControlLoopNotification)obj).message.contains("Guard result: Deny")){ - + // "About to query Guard" notification (Querying about Rebuild) obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); @@ -163,19 +189,19 @@ public class ControlLoopXacmlGuardTest { logger.debug("Rule: {} Message", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - Thread.sleep(2000); - + + Thread.sleep(4000); + // "Response from Guard" notification obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - + + if(true == ((VirtualControlLoopNotification)obj).message.contains("Guard result: Deny")){ - + // "About to query Guard" notification (Querying about Migrate) obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); @@ -183,25 +209,25 @@ public class ControlLoopXacmlGuardTest { logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - Thread.sleep(2000); - + + Thread.sleep(4000); + // "Response from Guard" notification obj = engine.subscribe("UEB", "POLICY-CL-MGT"); assertNotNull(obj); logger.debug("Rule: " + ((VirtualControlLoopNotification)obj).policyName +" Message: " + ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - + + if(true == ((VirtualControlLoopNotification)obj).message.contains("Guard result: Deny")){ //All the 3 operations were Denied by Guard - Thread.sleep(30000); - - } + Thread.sleep(60000); + + } } } - + // // In case one of the operations was permitted by Guard // @@ -211,14 +237,16 @@ public class ControlLoopXacmlGuardTest { logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); assertTrue(obj instanceof VirtualControlLoopNotification); assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); - - Thread.sleep(500); - + + Thread.sleep(1000); + obj = engine.subscribe("UEB", "APPC-CL"); assertNotNull(obj); - assertTrue(obj instanceof Request); - assertTrue(((Request)obj).CommonHeader.SubRequestID.equals("1")); - + assertTrue(obj instanceof LCMRequestWrapper); + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj; + LCMRequest appcRequest = dmaapRequest.getBody(); + assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1")); + logger.debug("\n============ APP-C Got request!!! ===========\n"); // // Ok - let's simulate ACCEPT @@ -227,20 +255,21 @@ public class ControlLoopXacmlGuardTest { // // now wait for it to finish // - Thread.sleep(500); - + Thread.sleep(1000); + // // Now we are going to success it // - Response response = new Response((Request) obj); - response.Status.Code = ResponseCode.SUCCESS.getValue(); - response.Status.Value = ResponseValue.SUCCESS.toString(); - response.Status.Description = "AppC success"; - kieSession.insert(response); + LCMResponseWrapper dmaapResponse = new LCMResponseWrapper(); + LCMResponse appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("AppC success"); + dmaapResponse.setBody(appcResponse); + kieSession.insert(dmaapResponse); // // Give it some time to process // - Thread.sleep(2000); + Thread.sleep(4000); // // Insert the abatement event // @@ -248,16 +277,16 @@ public class ControlLoopXacmlGuardTest { // // now wait for it to finish // - Thread.sleep(5000); + Thread.sleep(15000); // // Ensure they released the lock // assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID)); - + } - - - + + + } catch (InterruptedException e) { logger.error("Test thread got InterruptedException ", e.getLocalizedMessage()); } catch (AssertionError e) { @@ -269,7 +298,7 @@ public class ControlLoopXacmlGuardTest { } kieSession.halt(); } - + }).start(); // // Start firing rules @@ -283,16 +312,17 @@ public class ControlLoopXacmlGuardTest { // See if there is anything left in memory // assertEquals(1, kieSession.getFactCount()); - + for (FactHandle handle : kieSession.getFactHandles()) { Object fact = kieSession.getObject(handle); assertEquals("", "org.onap.policy.controlloop.Params", fact.getClass().getName()); } + kieSession.dispose(); } - - - + + + public static void dumpFacts(KieSession kieSession) { logger.debug("Fact Count: {}", kieSession.getFactCount()); for (FactHandle handle : kieSession.getFactHandles()) { @@ -307,7 +337,7 @@ public class ControlLoopXacmlGuardTest { event.target = "vserver.vserver-name"; event.closedLoopAlarmStart = Instant.now().minusSeconds(5); event.closedLoopAlarmEnd = Instant.now(); - event.AAI = new HashMap<String, String>(); + event.AAI = new HashMap<>(); event.AAI.put("cloud-region.identity-url", "foo"); event.AAI.put("vserver.selflink", "bar"); event.AAI.put("vserver.is-closed-loop-disabled", "false"); @@ -315,24 +345,24 @@ public class ControlLoopXacmlGuardTest { event.closedLoopEventStatus = ControlLoopEventStatus.ABATED; kieSession.insert(event); } - + protected void sendGoodEvents(KieSession kieSession, ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { VirtualControlLoopEvent event = new VirtualControlLoopEvent(); event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); event.requestID = requestID; event.target = "vserver.vserver-name"; event.closedLoopAlarmStart = Instant.now(); - event.AAI = new HashMap<String, String>(); + event.AAI = new HashMap<>(); event.AAI.put("cloud-region.identity-url", "foo"); event.AAI.put("vserver.selflink", "bar"); event.AAI.put("vserver.is-closed-loop-disabled", "false"); event.AAI.put("vserver.vserver-name", "testGenericVnfName"); event.closedLoopEventStatus = ControlLoopEventStatus.ONSET; kieSession.insert(event); - Thread.sleep(1000); - + Thread.sleep(2000); + } - + protected void sendBadEvents(KieSession kieSession, ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { // // Insert a bad Event @@ -340,50 +370,50 @@ public class ControlLoopXacmlGuardTest { VirtualControlLoopEvent event = new VirtualControlLoopEvent(); event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // add the request id // event.requestID = requestID; kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // add some aai // - event.AAI = new HashMap<String, String>(); + event.AAI = new HashMap<>(); event.AAI.put("cloud-region.identity-url", "foo"); event.AAI.put("vserver.selflink", "bar"); event.AAI.put("vserver.vserver-name", "vmfoo"); kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // set a valid status // event.closedLoopEventStatus = ControlLoopEventStatus.ONSET; kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // add a trigger sourcename // kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // add is closed-loop-disabled // event.AAI.put("vserver.is-closed-loop-disabled", "true"); kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // now enable // event.AAI.put("vserver.is-closed-loop-disabled", "false"); kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); // // Add target, but bad. // event.target = "VM_BLAH"; kieSession.insert(event); - Thread.sleep(250); + Thread.sleep(500); } } diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java index 61be1535e..502ef7c1d 100644 --- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java @@ -239,6 +239,10 @@ public final class Util { "src/main/resources/frequency_limiter_template.xml", "src/test/resources/xacml/autogenerated_frequency_limiter_migrate.xml"); + PolicyGuardYamlToXacml.fromYamlToXacml("src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml", + "src/main/resources/frequency_limiter_template.xml", + "src/test/resources/xacml/autogenerated_frequency_limiter_modifyconfig.xml"); + PolicyGuardYamlToXacml.fromYamlToXacmlBlacklist("src/test/resources/yaml/policy_guard_appc_restart_blacklist.yaml", "src/main/resources/blacklist_template.xml", "src/test/resources/xacml/autogenerated_blacklist.xml"); diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java new file mode 100644 index 000000000..a34ee6cd1 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java @@ -0,0 +1,441 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.template.demo; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.URLEncoder; +import java.time.Instant; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseWrapper; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.impl.PolicyEngineJUnitImpl; +import org.onap.policy.guard.PolicyGuard; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VCPEControlLoopTest { + + private static final Logger logger = LoggerFactory.getLogger(VCPEControlLoopTest.class); + + private KieSession kieSession; + private Util.Pair<ControlLoopPolicy, String> pair; + private PolicyEngineJUnitImpl engine; + + @Test + public void successTest() { + + /* + * Start the kie session + */ + try { + kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl", + "src/test/resources/yaml/policy_ControlLoop_vCPE.yaml", + "service=ServiceTest;resource=ResourceTest;type=operational", + "CL_vCPE", + "org.onap.closed_loop.ServiceTest:VNFS:1.0.0"); + } catch (IOException e) { + e.printStackTrace(); + logger.debug("Could not create kieSession"); + fail("Could not create kieSession"); + } + + /* + * Create a thread to continuously fire rules + * until main thread calls halt + */ + new Thread( new Runnable() { + @Override + public void run() { + kieSession.fireUntilHalt(); + } + } ).start(); + + /* + * Create a unique requestId and a unique trigger source + */ + UUID requestID = UUID.randomUUID(); + String triggerSourceName = "foobartriggersource36"; + + /* + * This will be the object returned from the PolicyEngine + */ + Object obj = null; + + /* + * Simulate an onset event the policy engine will + * receive from DCAE to kick off processing through + * the rules. + */ + try { + sendOnset(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("Unable to send onset event"); + fail("Unable to send onset event"); + } + + /* + * Pull the object that was sent out to DMAAP and make + * sure it is a ControlLoopNoticiation of type active + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE)); + + /* + * Give the control loop time to acquire a lock + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The fact should be ready to query guard now to see + * if a ModifyConfig recipe is allowed + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("\n\n####################### GOING TO QUERY GUARD about Restart!!!!!!"); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * Make sure the object is an instance of a ControlLoopNotification + * and is of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The guard response should be received at this point + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The object should be a ControlLoopNotification with type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + /* + * See if Guard permits this action, if it does + * not then the test should fail + */ + if (((VirtualControlLoopNotification)obj).message.contains("Guard result: Permit")) { + + /* + * A notification should be sent out of the Policy + * Engine at this point, it will be of type operation + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* A notification should be sent out of the Policy + * Engine at this point, it will be of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Obtain the request sent from the Policy Engine + */ + obj = engine.subscribe("UEB", "APPC-CL"); + assertNotNull(obj); + + /* + * The request should be of type LCMRequestWrapper + * and the subrequestid should be 1 + */ + assertTrue(obj instanceof LCMRequestWrapper); + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj; + LCMRequest appcRequest = dmaapRequest.getBody(); + assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1")); + + logger.debug("\n============ APPC received the request!!! ===========\n"); + + /* + * Give some time for processing + */ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Simulate a success response from APPC and insert + * the response into the working memory + */ + LCMResponseWrapper dmaapResponse = new LCMResponseWrapper(); + LCMResponse appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("AppC success"); + dmaapResponse.setBody(appcResponse); + kieSession.insert(dmaapResponse); + + /* + * Give time for processing + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Make sure the next notification is delivered + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be + * an OPERATION_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS)); + + /* + * Now simulate the abatement sent from DCAE + */ + try { + sendAbatement(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e1) { + e1.printStackTrace(); + logger.debug("Abatement could not be sent"); + fail("Abatement could not be sent"); + } + + /* + * Give time to finish processing + */ + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * This should be the final notification from the Policy Engine + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be of type FINAL_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS)); + + /* + * One final check to make sure the lock is released + */ + assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID)); + } + else { + fail("Operation Denied by Guard"); + } + + /* + * This will stop the thread that is firing the rules + */ + kieSession.halt(); + + /* + * The only fact in memory should be Params + */ + assertEquals(1, kieSession.getFactCount()); + + /* + * Print what's left in memory + */ + dumpFacts(kieSession); + + /* + * Gracefully shut down the kie session + */ + kieSession.dispose(); + } + + /** + * This method will start a kie session and instantiate + * the Policy Engine. + * + * @param droolsTemplate + * the DRL rules file + * @param yamlFile + * the yaml file containing the policies + * @param policyScope + * scope for policy + * @param policyName + * name of the policy + * @param policyVersion + * version of the policy + * @return the kieSession to be used to insert facts + * @throws IOException + */ + private KieSession startSession(String droolsTemplate, + String yamlFile, + String policyScope, + String policyName, + String policyVersion) throws IOException { + + /* + * Load policies from yaml + */ + pair = Util.loadYaml(yamlFile); + assertNotNull(pair); + assertNotNull(pair.a); + assertNotNull(pair.a.getControlLoop()); + assertNotNull(pair.a.getControlLoop().getControlLoopName()); + assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0); + + /* + * Construct a kie session + */ + final KieSession kieSession = Util.buildContainer(droolsTemplate, + pair.a.getControlLoop().getControlLoopName(), + policyScope, + policyName, + policyVersion, + URLEncoder.encode(pair.b, "UTF-8")); + + /* + * Retrieve the Policy Engine + */ + engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine"); + + logger.debug("============"); + logger.debug(URLEncoder.encode(pair.b, "UTF-8")); + logger.debug("============"); + + return kieSession; + } + + /** + * This method is used to simulate event messages from DCAE + * that start the control loop (onset message). + * + * @param policy the controlLoopName comes from the policy + * @param requestID the requestId for this event + * @param triggerSourceName + * @throws InterruptedException + */ + protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("vserver.vserver-name", "testGenericVnfName"); + event.AAI.put("generic-vnf.vnf-id", "testGenericVnfId"); + event.closedLoopEventStatus = ControlLoopEventStatus.ONSET; + kieSession.insert(event); + Thread.sleep(1000); + } + + /** + * This method is used to simulate event messages from DCAE + * that end the control loop (abatement message). + * + * @param policy the controlLoopName comes from the policy + * @param requestID the requestId for this event + * @param triggerSourceName + * @throws InterruptedException + */ + protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now().minusSeconds(5); + event.closedLoopAlarmEnd = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("generic-vnf.vnf-name", "testGenericVnfName"); + event.closedLoopEventStatus = ControlLoopEventStatus.ABATED; + kieSession.insert(event); + } + + /** + * This method will dump all the facts in the working memory. + * + * @param kieSession the session containing the facts + */ + public void dumpFacts(KieSession kieSession) { + logger.debug("Fact Count: {}", kieSession.getFactCount()); + for (FactHandle handle : kieSession.getFactHandles()) { + logger.debug("FACT: {}", handle); + } + } +} diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java new file mode 100644 index 000000000..25920e8b5 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java @@ -0,0 +1,435 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.template.demo; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.URLEncoder; +import java.time.Instant; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.onap.policy.appc.Request; +import org.onap.policy.appc.Response; +import org.onap.policy.appc.ResponseCode; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.impl.PolicyEngineJUnitImpl; +import org.onap.policy.guard.PolicyGuard; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VFWControlLoopTest { + + private static final Logger logger = LoggerFactory.getLogger(VFWControlLoopTest.class); + + private KieSession kieSession; + private Util.Pair<ControlLoopPolicy, String> pair; + private PolicyEngineJUnitImpl engine; + + @Test + public void successTest() { + + /* + * Start the kie session + */ + try { + kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl", + "src/test/resources/yaml/policy_ControlLoop_vFW.yaml", + "service=ServiceDemo;resource=Res1Demo;type=operational", + "CL_vFW", + "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0"); + } catch (IOException e) { + e.printStackTrace(); + logger.debug("Could not create kieSession"); + fail("Could not create kieSession"); + } + + /* + * Create a thread to continuously fire rules + * until main thread calls halt + */ + new Thread( new Runnable() { + @Override + public void run() { + kieSession.fireUntilHalt(); + } + } ).start(); + + /* + * Create a unique requestId and a unique trigger source + */ + UUID requestID = UUID.randomUUID(); + String triggerSourceName = "foobartriggersource36"; + + /* + * This will be the object returned from the PolicyEngine + */ + Object obj = null; + + /* + * Simulate an onset event the policy engine will + * receive from DCAE to kick off processing through + * the rules + */ + try { + sendOnset(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("Unable to send onset event"); + fail("Unable to send onset event"); + } + + /* + * Pull the object that was sent out to DMAAP and make + * sure it is a ControlLoopNoticiation of type active + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE)); + + /* + * Give the control loop time to acquire a lock + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The fact should be ready to query guard now to see + * if a ModifyConfig recipe is allowed + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("\n\n####################### GOING TO QUERY GUARD about ModifyConfig!!!!!!"); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * Make sure the object is an instance of a ControlLoopNotification + * and is of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The guard response should be received at this point + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The object should be a ControlLoopNotification with type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + /* + * See if Guard permits this action, if it does + * not then the test should fail + */ + if (((VirtualControlLoopNotification)obj).message.contains("Guard result: Permit")) { + + /* + * Obtain the ControlLoopNoticiation, it should be of type operation + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * A notification should be sent out of the Policy + * Engine at this point, it will be of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Obtain the request sent from the Policy Engine + */ + obj = engine.subscribe("UEB", "APPC-CL"); + assertNotNull(obj); + + /* + * The request should be of type Request + * and the subrequestid should be 1 + */ + assertTrue(obj instanceof Request); + assertTrue(((Request)obj).getCommonHeader().SubRequestID.equals("1")); + + logger.debug("\n============ APPC received the request!!! ===========\n"); + + /* + * Give some time for processing + */ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Simulate a success response from APPC and insert + * the response into the working memory + */ + Response appcResponse = new Response((Request)obj); + appcResponse.getStatus().Code = ResponseCode.SUCCESS.getValue(); + appcResponse.getStatus().Description = "AppC success"; + kieSession.insert(appcResponse); + + /* + * Give time for processing + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Make sure the next notification is delivered + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be + * an OPERATION_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS)); + + /* + * Now simulate the abatement sent from DCAE + */ + try { + sendAbatement(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e1) { + e1.printStackTrace(); + logger.debug("Abatement could not be sent"); + fail("Abatement could not be sent"); + } + + /* + * Give time to finish processing + */ + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * This should be the final notification from the Policy Engine + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be of type FINAL_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS)); + + /* + * One final check to make sure the lock is released + */ + assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID)); + } + else { + fail("Operation Denied by Guard"); + } + + /* + * This will stop the thread that is firing the rules + */ + kieSession.halt(); + + /* + * The only fact in memory should be Params + */ + assertEquals(1, kieSession.getFactCount()); + + /* + * Print what's left in memory + */ + dumpFacts(kieSession); + + /* + * Gracefully shut down the kie session + */ + kieSession.dispose(); + } + + /** + * This method will start a kie session and instantiate + * the Policy Engine. + * + * @param droolsTemplate + * the DRL rules file + * @param yamlFile + * the yaml file containing the policies + * @param policyScope + * scope for policy + * @param policyName + * name of the policy + * @param policyVersion + * version of the policy + * @return the kieSession to be used to insert facts + * @throws IOException + */ + private KieSession startSession(String droolsTemplate, + String yamlFile, + String policyScope, + String policyName, + String policyVersion) throws IOException { + + /* + * Load policies from yaml + */ + pair = Util.loadYaml(yamlFile); + assertNotNull(pair); + assertNotNull(pair.a); + assertNotNull(pair.a.getControlLoop()); + assertNotNull(pair.a.getControlLoop().getControlLoopName()); + assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0); + + /* + * Construct a kie session + */ + final KieSession kieSession = Util.buildContainer(droolsTemplate, + pair.a.getControlLoop().getControlLoopName(), + policyScope, + policyName, + policyVersion, + URLEncoder.encode(pair.b, "UTF-8")); + + /* + * Retrieve the Policy Engine + */ + engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine"); + + logger.debug("============"); + logger.debug(URLEncoder.encode(pair.b, "UTF-8")); + logger.debug("============"); + + return kieSession; + } + + /** + * This method is used to simulate event messages from DCAE + * that start the control loop (onset message). + * + * @param policy the controlLoopName comes from the policy + * @param requestID the requestId for this event + * @param triggerSourceName + * @throws InterruptedException + */ + protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("vserver.vserver-name", "testGenericVnfName"); + event.closedLoopEventStatus = ControlLoopEventStatus.ONSET; + kieSession.insert(event); + Thread.sleep(2000); + } + + /** + * This method is used to simulate event messages from DCAE + * that end the control loop (abatement message). + * + * @param policy the controlLoopName comes from the policy + * @param requestID the requestId for this event + * @param triggerSourceName + * @throws InterruptedException + */ + protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now().minusSeconds(5); + event.closedLoopAlarmEnd = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("generic-vnf.vnf-name", "testGenericVnfName"); + event.closedLoopEventStatus = ControlLoopEventStatus.ABATED; + kieSession.insert(event); + } + + /** + * This method will dump all the facts in the working memory. + * + * @param kieSession the session containing the facts + */ + public void dumpFacts(KieSession kieSession) { + logger.debug("Fact Count: {}", kieSession.getFactCount()); + for (FactHandle handle : kieSession.getFactHandles()) { + logger.debug("FACT: {}", handle); + } + } +} diff --git a/controlloop/templates/template.demo/src/test/resources/META-INF/persistence.xml b/controlloop/templates/template.demo/src/test/resources/META-INF/persistence.xml new file mode 100644 index 000000000..c3740d0b2 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="2.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
+
+ <!-- In-mem DB for junit -->
+ <persistence-unit name="TestOperationsHistoryPU"
+ transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry</class>
+ <properties>
+ <property name="eclipselink.ddl-generation" value="create-tables" />
+ <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
+ <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test" />
+ <property name="javax.persistence.jdbc.user" value="sa" />
+ <property name="javax.persistence.jdbc.password" value="" />
+ <property name="eclipselink.logging.level" value="ALL" />
+ </properties>
+ </persistence-unit>
+
+
+</persistence>
diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml new file mode 100644 index 000000000..de2ece4ed --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml @@ -0,0 +1,23 @@ +controlLoop: + version: 2.0.0 + controlLoopName: ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e + trigger_policy: unique-policy-id-1-restart + timeout: 3600 + abatement: true + +policies: + - id: unique-policy-id-1-restart + name: Restart the VM + description: + actor: APPC + recipe: Restart + target: + type: VM + retry: 3 + timeout: 1200 + success: final_success + failure: final_failure + failure_timeout: final_failure_timeout + failure_retries: final_failure_retries + failure_exception: final_failure_exception + failure_guard: final_failure_guard diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml new file mode 100644 index 000000000..e78b1ca33 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml @@ -0,0 +1,28 @@ +controlLoop: + version: 2.0.0 + controlLoopName: ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a + services: + - serviceInvariantUUID: 5cfe6f4a-41bc-4247-8674-ebd4b98e35cc + serviceUUID: 0f40bba5-986e-4b3c-803f-ddd1b7b25f24 + serviceName: 57e66ea7-0ed6-45c7-970f + trigger_policy: unique-policy-id-1-modifyConfig + timeout: 1200 + abatement: true + +policies: + - id: unique-policy-id-1-modifyConfig + name: modify packet gen config + description: + actor: APPC + recipe: ModifyConfig + target: + resourceID: Eace933104d443b496b8.nodes.heat.vpg + type: VM + retry: 0 + timeout: 300 + success: final_success + failure: final_failure + failure_timeout: final_failure_timeout + failure_retries: final_failure_retries + failure_exception: final_failure_exception + failure_guard: final_failure_guard diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml new file mode 100644 index 000000000..a94d4f231 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml @@ -0,0 +1,26 @@ +guard: + version: 2.0.0 + +guards: + - id: unique_guard_6 + name: APPC 6 ModifyConfig + description: | + We only allow 2 ModifyConfig over 10 minute window during the day time hours (avoid midnight to 5am) + match_parameters: + controlLoopName: ControlLoop-Service123-cbed919f-2212-4ef7-8051-fe6308da1bda + actor: APPC + recipe: ModifyConfig + targets: + - s1 + - s2 + - foobartriggersource36 + - s3 + - testGenericVnfName + limit_constraints: + - freq_limit_per_target: 1 + time_window: + value: 10 + units: minute + active_time_range: + start: 00:00:00-05:00 + end: 23:59:59-05:00
\ No newline at end of file |