summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordaniel <dc443y@att.com>2017-08-11 11:36:09 -0500
committerdaniel <dc443y@att.com>2017-09-06 17:14:59 -0500
commit7576237fd14304e987eb3c907d481f503dab8232 (patch)
treeddc75f000cb86e3a426cf34d6031efbc14c8735e
parentb2bdc20c1ce3a390dd7928144c2ccb17a98b1363 (diff)
Add APPC LCM Interface
The LCM model code and service provider code is implemented. This model code is now used for the vCPE use case scenario. The vFW use case is still using the legacy APPC API as request by APPC for Policy to use in R1. The APPC service provider now generates a demo legacy APPC request with pg-streams. An A&AI named query is implemented for the vFW use case. The code for obtaining the generic-vnf.vnf-id is not in use until we set up the A&AI simulator to work without having cyclical depenncies inside the POMs. JUnits for the vFW and vCPE use cases are now supported. These JUnits test the complete flow of each scenario. A&AI testing is not supported in the JUnit test yet. These JUnits use a target type of VM as VNF is not supported yet. This will be changed when the Target Lock supports VNF. Amended to fix Sonar blockers. Issue-ID: POLICY-104 Change-Id: I46869c5fd5094919da55ad563d608fe6d4b6fea7 Signed-off-by: Daniel Cruz <dc443y@att.com>
-rw-r--r--controlloop/common/actors/actor.appc/pom.xml30
-rw-r--r--controlloop/common/actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/APPCActorServiceProvider.java81
-rw-r--r--controlloop/common/actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java124
-rw-r--r--controlloop/common/actors/actor.appclcm/pom.xml50
-rw-r--r--controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java293
-rw-r--r--controlloop/common/actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor1
-rw-r--r--controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmServiceProviderTest.java271
-rw-r--r--controlloop/common/actors/pom.xml1
-rw-r--r--controlloop/common/eventmanager/pom.xml18
-rw-r--r--controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java51
-rw-r--r--controlloop/common/eventmanager/src/main/java/org/onap/policy/drools/impl/PolicyEngineJUnitImpl.java9
-rw-r--r--controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java87
-rw-r--r--controlloop/common/model-impl/aai/src/main/java/org/onap/policy/aai/AAINQF199/AAINQF199GenericVNF.java3
-rw-r--r--controlloop/common/model-impl/appc/pom.xml2
-rw-r--r--controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/CommonHeader.java4
-rw-r--r--controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Request.java2
-rw-r--r--controlloop/common/model-impl/appc/src/main/java/org/onap/policy/appc/Response.java2
-rw-r--r--controlloop/common/model-impl/appclcm/pom.xml45
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMCommonHeader.java233
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequest.java161
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMRequestWrapper.java90
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponse.java151
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseCode.java80
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseStatus.java107
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMResponseWrapper.java85
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/LCMWrapper.java187
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/java/org/onap/policy/appclcm/util/Serialization.java101
-rw-r--r--controlloop/common/model-impl/appclcm/src/main/resources/definitions.yaml118
-rw-r--r--controlloop/common/model-impl/appclcm/src/test/java/org/onap/policy/appclcm/AppcLcmTest.java244
-rw-r--r--controlloop/common/model-impl/pom.xml1
-rw-r--r--controlloop/templates/template.demo/pom.xml18
-rw-r--r--controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl123
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java21
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java53
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java4
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java441
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java435
-rw-r--r--controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml23
-rw-r--r--controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml28
-rw-r--r--controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml26
40 files changed, 3703 insertions, 101 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..318d39fbc 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>
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..94b6e1618 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
@@ -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,6 +31,7 @@ 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.ControlLoopOperation;
import org.onap.policy.controlloop.VirtualControlLoopEvent;
@@ -40,7 +42,7 @@ import org.onap.policy.controlloop.actor.appc.APPCActorServiceProvider;
import org.onap.policy.controlloop.actor.vfc.VFCActorServiceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
+import org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider;
public class ControlLoopOperationManager implements Serializable {
@@ -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":
//
@@ -306,7 +314,34 @@ 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;
}
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/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/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..5436b5ebd 100644
--- a/controlloop/templates/template.demo/pom.xml
+++ b/controlloop/templates/template.demo/pom.xml
@@ -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>
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 73d50a5db..71c6e3a29 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
@@ -1,3 +1,23 @@
+/*-
+ * ============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.assertNotNull;
@@ -7,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;
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..8c0b99462 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
@@ -32,14 +32,16 @@ import java.time.Instant;
import java.util.HashMap;
import java.util.UUID;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Ignore;
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;
@@ -47,6 +49,7 @@ 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;
@@ -55,8 +58,22 @@ import org.slf4j.LoggerFactory;
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);
-
+
@Test
public void test() {
try {
@@ -216,8 +233,10 @@ public class ControlLoopXacmlGuardTest {
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");
//
@@ -232,11 +251,12 @@ public class ControlLoopXacmlGuardTest {
//
// 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
//
@@ -248,7 +268,7 @@ public class ControlLoopXacmlGuardTest {
//
// now wait for it to finish
//
- Thread.sleep(5000);
+ Thread.sleep(15000);
//
// Ensure they released the lock
//
@@ -288,6 +308,7 @@ public class ControlLoopXacmlGuardTest {
Object fact = kieSession.getObject(handle);
assertEquals("", "org.onap.policy.controlloop.Params", fact.getClass().getName());
}
+ kieSession.dispose();
}
@@ -307,7 +328,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");
@@ -322,7 +343,7 @@ public class ControlLoopXacmlGuardTest {
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");
@@ -350,7 +371,7 @@ public class ControlLoopXacmlGuardTest {
//
// 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");
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/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