From c6012167b9692eb38bcb479f233543e93c51c998 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Thu, 2 Jul 2020 09:30:52 -0400 Subject: Rename XxxActorServiceProvider to XxxActor Renamed the actors and their test classes. Addressed review comments: - some license dates Issue-ID: POLICY-2684 Change-Id: Ic9d83e146ef36bb305496d541166cb9f80544025 Signed-off-by: Jim Hahn --- .../policy/controlloop/actor/aai/AaiActor.java | 44 ++ .../actor/aai/AaiActorServiceProvider.java | 44 -- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/aai/AaiActorServiceProviderTest.java | 53 --- .../policy/controlloop/actor/aai/AaiActorTest.java | 53 +++ .../policy/controlloop/actor/appc/AppcActor.java | 165 ++++++++ .../actor/appc/AppcActorServiceProvider.java | 165 -------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../controlloop/actor/appc/AppcActorTest.java | 259 ++++++++++++ .../actor/appc/AppcServiceProviderTest.java | 259 ------------ .../controlloop/actor/appclcm/AppcLcmActor.java | 310 ++++++++++++++ .../actor/appclcm/AppcLcmActorServiceProvider.java | 310 -------------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../appclcm/AppcLcmActorServiceProviderTest.java | 457 -------------------- .../actor/appclcm/AppcLcmActorTest.java | 457 ++++++++++++++++++++ .../policy/controlloop/actor/cds/CdsActor.java | 288 +++++++++++++ .../actor/cds/CdsActorServiceProvider.java | 288 ------------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/cds/CdsActorServiceProviderTest.java | 262 ------------ .../policy/controlloop/actor/cds/CdsActorTest.java | 262 ++++++++++++ .../policy/controlloop/actor/guard/GuardActor.java | 40 ++ .../actor/guard/GuardActorServiceProvider.java | 40 -- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/guard/GuardActorServiceProviderTest.java | 48 --- .../controlloop/actor/guard/GuardActorTest.java | 48 +++ .../policy/controlloop/actor/sdnc/SdncActor.java | 223 ++++++++++ .../actor/sdnc/SdncActorServiceProvider.java | 223 ---------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/sdnc/SdncActorServiceProviderTest.java | 124 ------ .../controlloop/actor/sdnc/SdncActorTest.java | 124 ++++++ .../policy/controlloop/actor/sdnr/SdnrActor.java | 304 ++++++++++++++ .../actor/sdnr/SdnrActorServiceProvider.java | 304 -------------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/sdnr/SdnrActorServiceProviderTest.java | 203 --------- .../controlloop/actor/sdnr/SdnrActorTest.java | 203 +++++++++ .../onap/policy/controlloop/actor/so/SoActor.java | 462 +++++++++++++++++++++ .../actor/so/SoActorServiceProvider.java | 462 --------------------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/so/SoActorServiceProviderTest.java | 253 ----------- .../policy/controlloop/actor/so/SoActorTest.java | 252 +++++++++++ .../policy/controlloop/actor/vfc/VfcActor.java | 141 +++++++ .../actor/vfc/VfcActorServiceProvider.java | 141 ------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../actor/vfc/VfcActorServiceProviderTest.java | 149 ------- .../policy/controlloop/actor/vfc/VfcActorTest.java | 149 +++++++ 45 files changed, 3793 insertions(+), 3794 deletions(-) create mode 100644 models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActor.java delete mode 100644 models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorTest.java create mode 100644 models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActor.java delete mode 100644 models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java create mode 100644 models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcActorTest.java delete mode 100644 models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java delete mode 100644 models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java create mode 100644 models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActor.java delete mode 100644 models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorTest.java create mode 100644 models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActor.java delete mode 100644 models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorTest.java create mode 100644 models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActor.java delete mode 100644 models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorTest.java create mode 100644 models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActor.java delete mode 100644 models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorTest.java create mode 100644 models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActor.java delete mode 100644 models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorTest.java create mode 100644 models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActor.java delete mode 100644 models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorTest.java diff --git a/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActor.java b/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActor.java new file mode 100644 index 000000000..e8d1241f7 --- /dev/null +++ b/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActor.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.aai; + +import org.onap.policy.aai.AaiConstants; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams; + +/** + * A&AI Actor. + */ +public class AaiActor extends HttpActor { + public static final String NAME = AaiConstants.ACTOR_NAME; + + /** + * Constructs the object. + */ + public AaiActor() { + super(NAME, HttpActorParams.class); + + addOperator(new HttpOperator(NAME, AaiCustomQueryOperation.NAME, AaiCustomQueryOperation::new)); + addOperator(new HttpOperator(NAME, AaiGetTenantOperation.NAME, AaiGetTenantOperation::new)); + addOperator(new HttpOperator(NAME, AaiGetPnfOperation.NAME, AaiGetPnfOperation::new)); + } +} diff --git a/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProvider.java b/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProvider.java deleted file mode 100644 index 0fe70b7ea..000000000 --- a/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2020 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.aai; - -import org.onap.policy.aai.AaiConstants; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams; - -/** - * A&AI Actor. - */ -public class AaiActorServiceProvider extends HttpActor { - public static final String NAME = AaiConstants.ACTOR_NAME; - - /** - * Constructs the object. - */ - public AaiActorServiceProvider() { - super(NAME, HttpActorParams.class); - - addOperator(new HttpOperator(NAME, AaiCustomQueryOperation.NAME, AaiCustomQueryOperation::new)); - addOperator(new HttpOperator(NAME, AaiGetTenantOperation.NAME, AaiGetTenantOperation::new)); - addOperator(new HttpOperator(NAME, AaiGetPnfOperation.NAME, AaiGetPnfOperation::new)); - } -} diff --git a/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index 6a52e3f17..eb6ec902e 100644 --- a/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.aai.AaiActorServiceProvider +org.onap.policy.controlloop.actor.aai.AaiActor diff --git a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java deleted file mode 100644 index 97a8491b2..000000000 --- a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2020 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.aai; - -import static org.junit.Assert.assertEquals; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; -import org.junit.Test; -import org.onap.policy.controlloop.actor.test.BasicActor; - -public class AaiActorServiceProviderTest extends BasicActor { - - @Test - public void testAaiActorServiceProvider() { - final AaiActorServiceProvider prov = new AaiActorServiceProvider(); - - // verify that it has the operators we expect - List expected = new LinkedList<>(); - expected.add(AaiCustomQueryOperation.NAME); - expected.add(AaiGetTenantOperation.NAME); - expected.add(AaiGetPnfOperation.NAME); - - Collections.sort(expected); - - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - - // verify that it all plugs into the ActorService - verifyActorService(AaiActorServiceProvider.NAME, "service.yaml"); - } -} diff --git a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorTest.java b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorTest.java new file mode 100644 index 000000000..e56a55139 --- /dev/null +++ b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorTest.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.aai; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.Test; +import org.onap.policy.controlloop.actor.test.BasicActor; + +public class AaiActorTest extends BasicActor { + + @Test + public void testAaiActorServiceProvider() { + final AaiActor prov = new AaiActor(); + + // verify that it has the operators we expect + List expected = new LinkedList<>(); + expected.add(AaiCustomQueryOperation.NAME); + expected.add(AaiGetTenantOperation.NAME); + expected.add(AaiGetPnfOperation.NAME); + + Collections.sort(expected); + + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + + // verify that it all plugs into the ActorService + verifyActorService(AaiActor.NAME, "service.yaml"); + } +} diff --git a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActor.java b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActor.java new file mode 100644 index 000000000..8634fbf6a --- /dev/null +++ b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActor.java @@ -0,0 +1,165 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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 com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.onap.policy.appc.CommonHeader; +import org.onap.policy.appc.Request; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AppcActor extends BidirectionalTopicActor { + public static final String NAME = "APPC"; + + private static final Logger logger = LoggerFactory.getLogger(AppcActor.class); + + // TODO old code: remove lines down to **HERE** + + private static final StandardCoder coder = new StandardCoder(); + + // Strings for targets + private static final String TARGET_VM = "VM"; + private static final String TARGET_VNF = "VNF"; + + // Strings for recipes + private static final String RECIPE_RESTART = "Restart"; + private static final String RECIPE_REBUILD = "Rebuild"; + private static final String RECIPE_MIGRATE = "Migrate"; + private static final String RECIPE_MODIFY = "ModifyConfig"; + + private static final ImmutableList recipes = + ImmutableList.of(RECIPE_RESTART, RECIPE_REBUILD, RECIPE_MIGRATE, RECIPE_MODIFY); + private static final ImmutableMap> targets = new ImmutableMap.Builder>() + .put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).put(RECIPE_REBUILD, ImmutableList.of(TARGET_VM)) + .put(RECIPE_MIGRATE, ImmutableList.of(TARGET_VM)).put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)) + .build(); + private static final ImmutableMap> payloads = new ImmutableMap.Builder>() + .put(RECIPE_MODIFY, ImmutableList.of("generic-vnf.vnf-id")).build(); + + // **HERE** + + /** + * Constructs the object. + */ + public AppcActor() { + super(NAME, BidirectionalTopicActorParams.class); + + addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS, + ModifyConfigOperation::new)); + } + + // TODO old code: remove lines down to **HERE** + + @Override + public String actor() { + return NAME; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + 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, + String targetVnf) { + /* + * Construct an APPC request + */ + Request request = new Request(); + request.setCommonHeader(new CommonHeader()); + request.getCommonHeader().setRequestId(onset.getRequestId()); + request.getCommonHeader().setSubRequestId(operation.getSubRequestId()); + request.setAction(policy.getRecipe().substring(0, 1).toUpperCase() + policy.getRecipe().substring(1)); + + // convert policy payload strings to objects + if (policy.getPayload() == null) { + logger.info("no APPC payload specified for policy {}", policy.getName()); + } else { + convertPayload(policy.getPayload(), request.getPayload()); + } + + // add/replace specific values + request.getPayload().put("generic-vnf.vnf-id", targetVnf); + + /* + * Return the request + */ + + return request; + } + + /** + * Converts a payload. The original value is assumed to be a JSON string, which is + * decoded into an object. + * + * @param source source from which to get the values + * @param target where to place the decoded values + */ + private static void convertPayload(Map source, Map target) { + for (Entry ent : source.entrySet()) { + try { + target.put(ent.getKey(), coder.decode(ent.getValue(), Object.class)); + + } catch (CoderException e) { + logger.warn("cannot decode JSON value {}: {}", ent.getKey(), ent.getValue(), e); + } + } + } + + // **HERE** +} diff --git a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java deleted file mode 100644 index 0a03957ec..000000000 --- a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java +++ /dev/null @@ -1,165 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * APPCActorServiceProvider - * ================================================================================ - * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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 com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import org.onap.policy.appc.CommonHeader; -import org.onap.policy.appc.Request; -import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.common.utils.coder.StandardCoder; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; -import org.onap.policy.controlloop.policy.Policy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class AppcActorServiceProvider extends BidirectionalTopicActor { - public static final String NAME = "APPC"; - - private static final Logger logger = LoggerFactory.getLogger(AppcActorServiceProvider.class); - - // TODO old code: remove lines down to **HERE** - - private static final StandardCoder coder = new StandardCoder(); - - // Strings for targets - private static final String TARGET_VM = "VM"; - private static final String TARGET_VNF = "VNF"; - - // Strings for recipes - private static final String RECIPE_RESTART = "Restart"; - private static final String RECIPE_REBUILD = "Rebuild"; - private static final String RECIPE_MIGRATE = "Migrate"; - private static final String RECIPE_MODIFY = "ModifyConfig"; - - private static final ImmutableList recipes = - ImmutableList.of(RECIPE_RESTART, RECIPE_REBUILD, RECIPE_MIGRATE, RECIPE_MODIFY); - private static final ImmutableMap> targets = new ImmutableMap.Builder>() - .put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).put(RECIPE_REBUILD, ImmutableList.of(TARGET_VM)) - .put(RECIPE_MIGRATE, ImmutableList.of(TARGET_VM)).put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)) - .build(); - private static final ImmutableMap> payloads = new ImmutableMap.Builder>() - .put(RECIPE_MODIFY, ImmutableList.of("generic-vnf.vnf-id")).build(); - - // **HERE** - - /** - * Constructs the object. - */ - public AppcActorServiceProvider() { - super(NAME, BidirectionalTopicActorParams.class); - - addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS, - ModifyConfigOperation::new)); - } - - // TODO old code: remove lines down to **HERE** - - @Override - public String actor() { - return NAME; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - 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, - String targetVnf) { - /* - * Construct an APPC request - */ - Request request = new Request(); - request.setCommonHeader(new CommonHeader()); - request.getCommonHeader().setRequestId(onset.getRequestId()); - request.getCommonHeader().setSubRequestId(operation.getSubRequestId()); - request.setAction(policy.getRecipe().substring(0, 1).toUpperCase() + policy.getRecipe().substring(1)); - - // convert policy payload strings to objects - if (policy.getPayload() == null) { - logger.info("no APPC payload specified for policy {}", policy.getName()); - } else { - convertPayload(policy.getPayload(), request.getPayload()); - } - - // add/replace specific values - request.getPayload().put("generic-vnf.vnf-id", targetVnf); - - /* - * Return the request - */ - - return request; - } - - /** - * Converts a payload. The original value is assumed to be a JSON string, which is - * decoded into an object. - * - * @param source source from which to get the values - * @param target where to place the decoded values - */ - private static void convertPayload(Map source, Map target) { - for (Entry ent : source.entrySet()) { - try { - target.put(ent.getKey(), coder.decode(ent.getValue(), Object.class)); - - } catch (CoderException e) { - logger.warn("cannot decode JSON value {}: {}", ent.getKey(), ent.getValue(), e); - } - } - } - - // **HERE** -} diff --git a/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index f1002a301..313b668d1 100644 --- a/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.appc.AppcActorServiceProvider \ No newline at end of file +org.onap.policy.controlloop.actor.appc.AppcActor diff --git a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcActorTest.java b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcActorTest.java new file mode 100644 index 000000000..47773f23f --- /dev/null +++ b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcActorTest.java @@ -0,0 +1,259 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.time.Instant; +import java.util.Arrays; +import java.util.HashMap; +import java.util.UUID; +import java.util.stream.Collectors; +import org.junit.AfterClass; +import org.junit.BeforeClass; +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.ResponseStatus; +import org.onap.policy.appc.util.Serialization; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +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.actor.test.BasicActor; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.simulators.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcActorTest extends BasicActor { + + private static final String GENERIC_VNF_ID = "generic-vnf.vnf-id"; + + private static final String MODIFY_CONFIG = "ModifyConfig"; + + private static final String JSON_OUTPUT = "JSON Output: \n"; + + private static final Logger logger = LoggerFactory.getLogger(AppcActorTest.class); + + private static final VirtualControlLoopEvent onsetEvent; + private static final ControlLoopOperation operation; + private static final Policy policy; + + private static final String KEY1 = "my-keyA"; + private static final String KEY2 = "my-keyB"; + private static final String SUBKEY = "sub-key"; + + private static final String VALUE1 = "'my-value'".replace('\'', '"'); + private static final String VALUE2 = "{'sub-key':20}".replace('\'', '"'); + private static final String SUBVALUE = "20"; + + static { + /* + * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a + * target type of VM. + */ + onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); + onsetEvent.setRequestId(UUID.randomUUID()); + onsetEvent.setClosedLoopEventClient("tca.instance00001"); + onsetEvent.setTargetType(ControlLoopTargetType.VNF); + onsetEvent.setTarget("generic-vnf.vnf-name"); + onsetEvent.setFrom("DCAE"); + onsetEvent.setClosedLoopAlarmStart(Instant.now()); + onsetEvent.setAai(new HashMap<>()); + onsetEvent.getAai().put("generic-vnf.vnf-name", "fw0001vm001fw001"); + onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); + + /* Construct an operation with an APPC actor and ModifyConfig operation. */ + operation = new ControlLoopOperation(); + operation.setActor("APPC"); + operation.setOperation(MODIFY_CONFIG); + operation.setTarget("VNF"); + operation.setEnd(Instant.now()); + operation.setSubRequestId("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.VNF)); + policy.getTarget().setResourceID("Eace933104d443b496b8.nodes.heat.vpg"); + policy.setRecipe(MODIFY_CONFIG); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + + } + + /** + * Set up before test class. + * + * @throws Exception if the A&AI simulator cannot be started + */ + @BeforeClass + public static void setUpSimulator() throws Exception { + Util.buildAaiSim(); + } + + /** + * Tear down after test class. + */ + @AfterClass + public static void tearDownSimulator() { + HttpServletServerFactoryInstance.getServerFactory().destroy(); + } + + @Test + public void testConstructor() { + AppcActor prov = new AppcActor(); + assertEquals(0, prov.getSequenceNumber()); + + // verify that it has the operators we expect + var expected = Arrays.asList(ModifyConfigOperation.NAME).stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(AppcActor.NAME, "service.yaml"); + } + + @Test + public void testConstructModifyConfigRequest() { + policy.setPayload(new HashMap<>()); + policy.getPayload().put(KEY1, VALUE1); + policy.getPayload().put(KEY2, VALUE2); + + Request appcRequest; + appcRequest = AppcActor.constructRequest(onsetEvent, operation, policy, "vnf01"); + + /* 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().getRequestId(), onsetEvent.getRequestId()); + + /* An action is required and cannot be null */ + assertNotNull(appcRequest.getAction()); + assertEquals(MODIFY_CONFIG, appcRequest.getAction()); + + /* A payload is required and cannot be null */ + assertNotNull(appcRequest.getPayload()); + assertTrue(appcRequest.getPayload().containsKey(GENERIC_VNF_ID)); + assertNotNull(appcRequest.getPayload().get(GENERIC_VNF_ID)); + assertTrue(appcRequest.getPayload().containsKey(KEY1)); + assertTrue(appcRequest.getPayload().containsKey(KEY2)); + + 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 + jsonRequest); + + /* The JSON string must contain the following fields */ + assertTrue(jsonRequest.contains("CommonHeader")); + assertTrue(jsonRequest.contains("Action")); + assertTrue(jsonRequest.contains(MODIFY_CONFIG)); + assertTrue(jsonRequest.contains("Payload")); + assertTrue(jsonRequest.contains(GENERIC_VNF_ID)); + assertTrue(jsonRequest.contains(KEY1)); + assertTrue(jsonRequest.contains(KEY2)); + assertTrue(jsonRequest.contains(SUBKEY)); + assertTrue(jsonRequest.contains(SUBVALUE)); + assertFalse(jsonRequest.contains(SUBVALUE + ".0")); + + Response appcResponse = new Response(appcRequest); + appcResponse.setStatus(new ResponseStatus()); + appcResponse.getStatus().setCode(ResponseCode.SUCCESS.getValue()); + appcResponse.getStatus().setDescription("AppC success"); + /* Print out request as json to make sure serialization works */ + String jsonResponse = Serialization.gsonPretty.toJson(appcResponse); + logger.debug(JSON_OUTPUT + jsonResponse); + } + + @Test + public void testConstructModifyConfigRequest_NullPayload() { + + Request appcRequest; + appcRequest = AppcActor.constructRequest(onsetEvent, operation, policy, "vnf01"); + + /* 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().getRequestId(), onsetEvent.getRequestId()); + + /* An action is required and cannot be null */ + assertNotNull(appcRequest.getAction()); + assertEquals(MODIFY_CONFIG, appcRequest.getAction()); + + /* A payload is required and cannot be null */ + assertNotNull(appcRequest.getPayload()); + assertTrue(appcRequest.getPayload().containsKey(GENERIC_VNF_ID)); + assertNotNull(appcRequest.getPayload().get(GENERIC_VNF_ID)); + + 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 + jsonRequest); + + /* The JSON string must contain the following fields */ + assertTrue(jsonRequest.contains("CommonHeader")); + assertTrue(jsonRequest.contains("Action")); + assertTrue(jsonRequest.contains(MODIFY_CONFIG)); + assertTrue(jsonRequest.contains("Payload")); + assertTrue(jsonRequest.contains(GENERIC_VNF_ID)); + + Response appcResponse = new Response(appcRequest); + appcResponse.setStatus(new ResponseStatus()); + appcResponse.getStatus().setCode(ResponseCode.SUCCESS.getValue()); + appcResponse.getStatus().setDescription("AppC success"); + /* Print out request as json to make sure serialization works */ + String jsonResponse = Serialization.gsonPretty.toJson(appcResponse); + logger.debug(JSON_OUTPUT + jsonResponse); + } + + @Test + public void testMethods() { + AppcActor sp = new AppcActor(); + + assertEquals("APPC", sp.actor()); + assertEquals(4, sp.recipes().size()); + assertEquals("VM", sp.recipeTargets("Restart").get(0)); + assertEquals(0, sp.recipePayloads("Restart").size()); + } +} diff --git a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java deleted file mode 100644 index 0fd3a8a42..000000000 --- a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java +++ /dev/null @@ -1,259 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * AppcServiceProviderTest - * ================================================================================ - * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.time.Instant; -import java.util.Arrays; -import java.util.HashMap; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.AfterClass; -import org.junit.BeforeClass; -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.ResponseStatus; -import org.onap.policy.appc.util.Serialization; -import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; -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.actor.test.BasicActor; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.Target; -import org.onap.policy.controlloop.policy.TargetType; -import org.onap.policy.simulators.Util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AppcServiceProviderTest extends BasicActor { - - private static final String GENERIC_VNF_ID = "generic-vnf.vnf-id"; - - private static final String MODIFY_CONFIG = "ModifyConfig"; - - private static final String JSON_OUTPUT = "JSON Output: \n"; - - private static final Logger logger = LoggerFactory.getLogger(AppcServiceProviderTest.class); - - private static final VirtualControlLoopEvent onsetEvent; - private static final ControlLoopOperation operation; - private static final Policy policy; - - private static final String KEY1 = "my-keyA"; - private static final String KEY2 = "my-keyB"; - private static final String SUBKEY = "sub-key"; - - private static final String VALUE1 = "'my-value'".replace('\'', '"'); - private static final String VALUE2 = "{'sub-key':20}".replace('\'', '"'); - private static final String SUBVALUE = "20"; - - static { - /* - * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a - * target type of VM. - */ - onsetEvent = new VirtualControlLoopEvent(); - onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); - onsetEvent.setRequestId(UUID.randomUUID()); - onsetEvent.setClosedLoopEventClient("tca.instance00001"); - onsetEvent.setTargetType(ControlLoopTargetType.VNF); - onsetEvent.setTarget("generic-vnf.vnf-name"); - onsetEvent.setFrom("DCAE"); - onsetEvent.setClosedLoopAlarmStart(Instant.now()); - onsetEvent.setAai(new HashMap<>()); - onsetEvent.getAai().put("generic-vnf.vnf-name", "fw0001vm001fw001"); - onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); - - /* Construct an operation with an APPC actor and ModifyConfig operation. */ - operation = new ControlLoopOperation(); - operation.setActor("APPC"); - operation.setOperation(MODIFY_CONFIG); - operation.setTarget("VNF"); - operation.setEnd(Instant.now()); - operation.setSubRequestId("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.VNF)); - policy.getTarget().setResourceID("Eace933104d443b496b8.nodes.heat.vpg"); - policy.setRecipe(MODIFY_CONFIG); - policy.setPayload(null); - policy.setRetry(2); - policy.setTimeout(300); - - } - - /** - * Set up before test class. - * - * @throws Exception if the A&AI simulator cannot be started - */ - @BeforeClass - public static void setUpSimulator() throws Exception { - Util.buildAaiSim(); - } - - /** - * Tear down after test class. - */ - @AfterClass - public static void tearDownSimulator() { - HttpServletServerFactoryInstance.getServerFactory().destroy(); - } - - @Test - public void testConstructor() { - AppcActorServiceProvider prov = new AppcActorServiceProvider(); - assertEquals(0, prov.getSequenceNumber()); - - // verify that it has the operators we expect - var expected = Arrays.asList(ModifyConfigOperation.NAME).stream().sorted().collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - } - - @Test - public void testActorService() { - // verify that it all plugs into the ActorService - verifyActorService(AppcActorServiceProvider.NAME, "service.yaml"); - } - - @Test - public void testConstructModifyConfigRequest() { - policy.setPayload(new HashMap<>()); - policy.getPayload().put(KEY1, VALUE1); - policy.getPayload().put(KEY2, VALUE2); - - Request appcRequest; - appcRequest = AppcActorServiceProvider.constructRequest(onsetEvent, operation, policy, "vnf01"); - - /* 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().getRequestId(), onsetEvent.getRequestId()); - - /* An action is required and cannot be null */ - assertNotNull(appcRequest.getAction()); - assertEquals(MODIFY_CONFIG, appcRequest.getAction()); - - /* A payload is required and cannot be null */ - assertNotNull(appcRequest.getPayload()); - assertTrue(appcRequest.getPayload().containsKey(GENERIC_VNF_ID)); - assertNotNull(appcRequest.getPayload().get(GENERIC_VNF_ID)); - assertTrue(appcRequest.getPayload().containsKey(KEY1)); - assertTrue(appcRequest.getPayload().containsKey(KEY2)); - - 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 + jsonRequest); - - /* The JSON string must contain the following fields */ - assertTrue(jsonRequest.contains("CommonHeader")); - assertTrue(jsonRequest.contains("Action")); - assertTrue(jsonRequest.contains(MODIFY_CONFIG)); - assertTrue(jsonRequest.contains("Payload")); - assertTrue(jsonRequest.contains(GENERIC_VNF_ID)); - assertTrue(jsonRequest.contains(KEY1)); - assertTrue(jsonRequest.contains(KEY2)); - assertTrue(jsonRequest.contains(SUBKEY)); - assertTrue(jsonRequest.contains(SUBVALUE)); - assertFalse(jsonRequest.contains(SUBVALUE + ".0")); - - Response appcResponse = new Response(appcRequest); - appcResponse.setStatus(new ResponseStatus()); - appcResponse.getStatus().setCode(ResponseCode.SUCCESS.getValue()); - appcResponse.getStatus().setDescription("AppC success"); - /* Print out request as json to make sure serialization works */ - String jsonResponse = Serialization.gsonPretty.toJson(appcResponse); - logger.debug(JSON_OUTPUT + jsonResponse); - } - - @Test - public void testConstructModifyConfigRequest_NullPayload() { - - Request appcRequest; - appcRequest = AppcActorServiceProvider.constructRequest(onsetEvent, operation, policy, "vnf01"); - - /* 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().getRequestId(), onsetEvent.getRequestId()); - - /* An action is required and cannot be null */ - assertNotNull(appcRequest.getAction()); - assertEquals(MODIFY_CONFIG, appcRequest.getAction()); - - /* A payload is required and cannot be null */ - assertNotNull(appcRequest.getPayload()); - assertTrue(appcRequest.getPayload().containsKey(GENERIC_VNF_ID)); - assertNotNull(appcRequest.getPayload().get(GENERIC_VNF_ID)); - - 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 + jsonRequest); - - /* The JSON string must contain the following fields */ - assertTrue(jsonRequest.contains("CommonHeader")); - assertTrue(jsonRequest.contains("Action")); - assertTrue(jsonRequest.contains(MODIFY_CONFIG)); - assertTrue(jsonRequest.contains("Payload")); - assertTrue(jsonRequest.contains(GENERIC_VNF_ID)); - - Response appcResponse = new Response(appcRequest); - appcResponse.setStatus(new ResponseStatus()); - appcResponse.getStatus().setCode(ResponseCode.SUCCESS.getValue()); - appcResponse.getStatus().setDescription("AppC success"); - /* Print out request as json to make sure serialization works */ - String jsonResponse = Serialization.gsonPretty.toJson(appcResponse); - logger.debug(JSON_OUTPUT + jsonResponse); - } - - @Test - public void testMethods() { - AppcActorServiceProvider sp = new AppcActorServiceProvider(); - - assertEquals("APPC", sp.actor()); - assertEquals(4, sp.recipes().size()); - assertEquals("VM", sp.recipeTargets("Restart").get(0)); - assertEquals(0, sp.recipePayloads("Restart").size()); - } -} diff --git a/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java b/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java new file mode 100644 index 000000000..04ef55aeb --- /dev/null +++ b/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java @@ -0,0 +1,310 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications copyright (c) 2018 Nokia + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.Set; +import org.onap.policy.appclcm.AppcLcmBody; +import org.onap.policy.appclcm.AppcLcmCommonHeader; +import org.onap.policy.appclcm.AppcLcmDmaapWrapper; +import org.onap.policy.appclcm.AppcLcmInput; +import org.onap.policy.appclcm.AppcLcmOutput; +import org.onap.policy.appclcm.AppcLcmResponseCode; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.appc.AppcOperation; +import org.onap.policy.controlloop.actor.appc.ModifyConfigOperation; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmActor extends BidirectionalTopicActor { + + /* + * Confirmed by Daniel, should be 'APPC'. + * The actor name defined in the yaml for both legacy operations and lcm operations is still “APPC”. Perhaps in a + * future review it would be better to distinguish them as two separate actors in the yaml but it should be okay for + * now. + */ + public static final String NAME = "APPC"; + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmActor.class); + + /* To be used in future releases to restart a single vm */ + private static final String APPC_VM_ID = "vm-id"; + + // Strings for targets + private static final String TARGET_VM = "VM"; + private static final String TARGET_VNF = "VNF"; + + // Strings for recipes + private static final String RECIPE_RESTART = AppcLcmConstants.OPERATION_RESTART; + private static final String RECIPE_REBUILD = AppcLcmConstants.OPERATION_REBUILD; + private static final String RECIPE_MIGRATE = AppcLcmConstants.OPERATION_MIGRATE; + private static final String RECIPE_MODIFY = AppcLcmConstants.OPERATION_CONFIG_MODIFY; + + /* 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 Set recipes = AppcLcmConstants.OPERATION_NAMES; + private static final ImmutableMap> targets = new ImmutableMap.Builder>() + .put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).put(RECIPE_REBUILD, ImmutableList.of(TARGET_VM)) + .put(RECIPE_MIGRATE, ImmutableList.of(TARGET_VM)).put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); + private static final ImmutableMap> payloads = + new ImmutableMap.Builder>().put(RECIPE_RESTART, ImmutableList.of(APPC_VM_ID)) + .put(RECIPE_MODIFY, ImmutableList.of(APPC_REQUEST_PARAMS, APPC_CONFIG_PARAMS)).build(); + + /** + * Constructs the object. + */ + public AppcLcmActor() { + super(NAME, BidirectionalTopicActorParams.class); + + // add LCM operations first as they take precedence + for (String opname : AppcLcmConstants.OPERATION_NAMES) { + addOperator(new BidirectionalTopicOperator(NAME, opname, this, AppcLcmOperation.SELECTOR_KEYS, + AppcLcmOperation::new)); + } + + // add legacy operations + addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS, + ModifyConfigOperation::new)); + } + + /** + * This actor should take precedence. + */ + @Override + public int getSequenceNumber() { + return -1; + } + + @Override + public String actor() { + return NAME; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); + } + + /** + * 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 AppcLcmDmaapWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, + Policy policy, String targetVnf) { + + /* 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. + */ + AppcLcmRecipeFormatter lcmRecipeFormatter = new AppcLcmRecipeFormatter(policy.getRecipe()); + + AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); + dmaapRequest.setVersion("2.0"); + dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); + dmaapRequest.setRpcName(lcmRecipeFormatter.getUrlRecipe()); + dmaapRequest.setType("request"); + + /* This is the actual request that is placed in the dmaap wrapper. */ + final AppcLcmInput appcRequest = new AppcLcmInput(); + + /* The common header is a required field for all APPC requests. */ + AppcLcmCommonHeader requestCommonHeader = new AppcLcmCommonHeader(); + requestCommonHeader.setOriginatorId(onset.getRequestId().toString()); + requestCommonHeader.setRequestId(onset.getRequestId()); + requestCommonHeader.setSubRequestId(operation.getSubRequestId()); + + appcRequest.setCommonHeader(requestCommonHeader); + + /* + * Action Identifiers are required for APPC LCM requests. For R1, the recipes supported by + * Policy only require a vnf-id. + */ + HashMap requestActionIdentifiers = new HashMap<>(); + requestActionIdentifiers.put("vnf-id", targetVnf); + + appcRequest.setActionIdentifiers(requestActionIdentifiers); + + /* + * An action is required for all APPC requests, this will be the recipe specified in the + * policy. + */ + appcRequest.setAction(lcmRecipeFormatter.getBodyRecipe()); + + /* + * 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 (recipeSupportsPayload(policy.getRecipe()) && payloadSupplied(policy.getPayload())) { + appcRequest.setPayload(parsePayload(policy.getPayload())); + } else { + appcRequest.setPayload(null); + } + + /* + * The APPC request must be wrapped in an input object. + */ + AppcLcmBody body = new AppcLcmBody(); + body.setInput(appcRequest); + + /* + * Once the LCM request is constructed, add it into the body of the dmaap wrapper. + */ + dmaapRequest.setBody(body); + + /* Return the request to be sent through dmaap. */ + return dmaapRequest; + } + + private static boolean payloadSupplied(Map payload) { + return payload != null && !payload.isEmpty(); + } + + private static boolean recipeSupportsPayload(String recipe) { + return !RECIPE_RESTART.equalsIgnoreCase(recipe) && !RECIPE_REBUILD.equalsIgnoreCase(recipe) + && !RECIPE_MIGRATE.equalsIgnoreCase(recipe); + } + + private static String parsePayload(Map payload) { + StringBuilder payloadString = new StringBuilder("{"); + payload.forEach( + (key, value) -> payloadString.append("\"").append(key).append("\": ").append(value).append(",")); + return payloadString.substring(0, payloadString.length() - 1) + "}"; + } + + /** + * 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 processResponse(AppcLcmDmaapWrapper dmaapResponse) { + AppcLcmBody appcBody = dmaapResponse.getBody(); + if (appcBody == null) { + throw new NullPointerException("APPC Body is null"); + } + + /* The actual APPC response is inside the dmaap wrapper's body.input field. */ + AppcLcmOutput appcResponse = appcBody.getOutput(); + if (appcResponse == null) { + throw new NullPointerException("APPC Response is null"); + } + + /* 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 = AppcLcmResponseCode.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 notification message. */ + message = appcResponse.getStatus().getMessage(); + + /* Maps the APPC response result to a Policy result. */ + switch (responseValue) { + case AppcLcmResponseCode.ACCEPTED: + /* Nothing to do if code is accept, continue processing */ + result = null; + break; + case AppcLcmResponseCode.SUCCESS: + result = PolicyResult.SUCCESS; + break; + case AppcLcmResponseCode.FAILURE: + result = PolicyResult.FAILURE; + break; + case AppcLcmResponseCode.REJECT: + case AppcLcmResponseCode.ERROR: + default: + result = PolicyResult.FAILURE_EXCEPTION; + } + return new AbstractMap.SimpleEntry<>(result, message); + } +} diff --git a/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java b/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java deleted file mode 100644 index 393ce0ccb..000000000 --- a/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java +++ /dev/null @@ -1,310 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. - * Modifications copyright (c) 2018 Nokia - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.Set; -import org.onap.policy.appclcm.AppcLcmBody; -import org.onap.policy.appclcm.AppcLcmCommonHeader; -import org.onap.policy.appclcm.AppcLcmDmaapWrapper; -import org.onap.policy.appclcm.AppcLcmInput; -import org.onap.policy.appclcm.AppcLcmOutput; -import org.onap.policy.appclcm.AppcLcmResponseCode; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.appc.AppcOperation; -import org.onap.policy.controlloop.actor.appc.ModifyConfigOperation; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; -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 extends BidirectionalTopicActor { - - /* - * Confirmed by Daniel, should be 'APPC'. - * The actor name defined in the yaml for both legacy operations and lcm operations is still “APPC”. Perhaps in a - * future review it would be better to distinguish them as two separate actors in the yaml but it should be okay for - * now. - */ - public static final String NAME = "APPC"; - - private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorServiceProvider.class); - - /* To be used in future releases to restart a single vm */ - private static final String APPC_VM_ID = "vm-id"; - - // Strings for targets - private static final String TARGET_VM = "VM"; - private static final String TARGET_VNF = "VNF"; - - // Strings for recipes - private static final String RECIPE_RESTART = AppcLcmConstants.OPERATION_RESTART; - private static final String RECIPE_REBUILD = AppcLcmConstants.OPERATION_REBUILD; - private static final String RECIPE_MIGRATE = AppcLcmConstants.OPERATION_MIGRATE; - private static final String RECIPE_MODIFY = AppcLcmConstants.OPERATION_CONFIG_MODIFY; - - /* 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 Set recipes = AppcLcmConstants.OPERATION_NAMES; - private static final ImmutableMap> targets = new ImmutableMap.Builder>() - .put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).put(RECIPE_REBUILD, ImmutableList.of(TARGET_VM)) - .put(RECIPE_MIGRATE, ImmutableList.of(TARGET_VM)).put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); - private static final ImmutableMap> payloads = - new ImmutableMap.Builder>().put(RECIPE_RESTART, ImmutableList.of(APPC_VM_ID)) - .put(RECIPE_MODIFY, ImmutableList.of(APPC_REQUEST_PARAMS, APPC_CONFIG_PARAMS)).build(); - - /** - * Constructs the object. - */ - public AppcLcmActorServiceProvider() { - super(NAME, BidirectionalTopicActorParams.class); - - // add LCM operations first as they take precedence - for (String opname : AppcLcmConstants.OPERATION_NAMES) { - addOperator(new BidirectionalTopicOperator(NAME, opname, this, AppcLcmOperation.SELECTOR_KEYS, - AppcLcmOperation::new)); - } - - // add legacy operations - addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS, - ModifyConfigOperation::new)); - } - - /** - * This actor should take precedence. - */ - @Override - public int getSequenceNumber() { - return -1; - } - - @Override - public String actor() { - return NAME; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); - } - - /** - * 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 AppcLcmDmaapWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, - Policy policy, String targetVnf) { - - /* 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. - */ - AppcLcmRecipeFormatter lcmRecipeFormatter = new AppcLcmRecipeFormatter(policy.getRecipe()); - - AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); - dmaapRequest.setVersion("2.0"); - dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); - dmaapRequest.setRpcName(lcmRecipeFormatter.getUrlRecipe()); - dmaapRequest.setType("request"); - - /* This is the actual request that is placed in the dmaap wrapper. */ - final AppcLcmInput appcRequest = new AppcLcmInput(); - - /* The common header is a required field for all APPC requests. */ - AppcLcmCommonHeader requestCommonHeader = new AppcLcmCommonHeader(); - requestCommonHeader.setOriginatorId(onset.getRequestId().toString()); - requestCommonHeader.setRequestId(onset.getRequestId()); - requestCommonHeader.setSubRequestId(operation.getSubRequestId()); - - appcRequest.setCommonHeader(requestCommonHeader); - - /* - * Action Identifiers are required for APPC LCM requests. For R1, the recipes supported by - * Policy only require a vnf-id. - */ - HashMap requestActionIdentifiers = new HashMap<>(); - requestActionIdentifiers.put("vnf-id", targetVnf); - - appcRequest.setActionIdentifiers(requestActionIdentifiers); - - /* - * An action is required for all APPC requests, this will be the recipe specified in the - * policy. - */ - appcRequest.setAction(lcmRecipeFormatter.getBodyRecipe()); - - /* - * 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 (recipeSupportsPayload(policy.getRecipe()) && payloadSupplied(policy.getPayload())) { - appcRequest.setPayload(parsePayload(policy.getPayload())); - } else { - appcRequest.setPayload(null); - } - - /* - * The APPC request must be wrapped in an input object. - */ - AppcLcmBody body = new AppcLcmBody(); - body.setInput(appcRequest); - - /* - * Once the LCM request is constructed, add it into the body of the dmaap wrapper. - */ - dmaapRequest.setBody(body); - - /* Return the request to be sent through dmaap. */ - return dmaapRequest; - } - - private static boolean payloadSupplied(Map payload) { - return payload != null && !payload.isEmpty(); - } - - private static boolean recipeSupportsPayload(String recipe) { - return !RECIPE_RESTART.equalsIgnoreCase(recipe) && !RECIPE_REBUILD.equalsIgnoreCase(recipe) - && !RECIPE_MIGRATE.equalsIgnoreCase(recipe); - } - - private static String parsePayload(Map payload) { - StringBuilder payloadString = new StringBuilder("{"); - payload.forEach( - (key, value) -> payloadString.append("\"").append(key).append("\": ").append(value).append(",")); - return payloadString.substring(0, payloadString.length() - 1) + "}"; - } - - /** - * 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 processResponse(AppcLcmDmaapWrapper dmaapResponse) { - AppcLcmBody appcBody = dmaapResponse.getBody(); - if (appcBody == null) { - throw new NullPointerException("APPC Body is null"); - } - - /* The actual APPC response is inside the dmaap wrapper's body.input field. */ - AppcLcmOutput appcResponse = appcBody.getOutput(); - if (appcResponse == null) { - throw new NullPointerException("APPC Response is null"); - } - - /* 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 = AppcLcmResponseCode.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 notification message. */ - message = appcResponse.getStatus().getMessage(); - - /* Maps the APPC response result to a Policy result. */ - switch (responseValue) { - case AppcLcmResponseCode.ACCEPTED: - /* Nothing to do if code is accept, continue processing */ - result = null; - break; - case AppcLcmResponseCode.SUCCESS: - result = PolicyResult.SUCCESS; - break; - case AppcLcmResponseCode.FAILURE: - result = PolicyResult.FAILURE; - break; - case AppcLcmResponseCode.REJECT: - case AppcLcmResponseCode.ERROR: - default: - result = PolicyResult.FAILURE_EXCEPTION; - } - return new AbstractMap.SimpleEntry<>(result, message); - } -} diff --git a/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index 403ad9859..53d2c2a7c 100644 --- a/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider \ No newline at end of file +org.onap.policy.controlloop.actor.appclcm.AppcLcmActor diff --git a/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java b/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java deleted file mode 100644 index 56ce047dd..000000000 --- a/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java +++ /dev/null @@ -1,457 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.time.Instant; -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.policy.appclcm.AppcLcmBody; -import org.onap.policy.appclcm.AppcLcmCommonHeader; -import org.onap.policy.appclcm.AppcLcmDmaapWrapper; -import org.onap.policy.appclcm.AppcLcmInput; -import org.onap.policy.appclcm.AppcLcmOutput; -import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; -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.onap.policy.simulators.Util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AppcLcmActorServiceProviderTest { - - private static final String VNF01 = "vnf01"; - - private static final String VNF_ID_KEY = "vnf-id"; - - private static final String REJECT = "REJECT"; - - private static final String PARTIAL_FAILURE = "PARTIAL FAILURE"; - - private static final String FAILURE = "FAILURE"; - - private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorServiceProviderTest.class); - - private static final VirtualControlLoopEvent onsetEvent; - private static final ControlLoopOperation operation; - private static final Policy policy; - private static final AppcLcmDmaapWrapper dmaapResponse; - - private static final String RECIPE_RESTART = "Restart"; - private static final String RECIPE_REBUILD = "Rebuild"; - private static final String RECIPE_MIGRATE = "Migrate"; - - static { - /* - * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a - * target type of VM. - */ - onsetEvent = new VirtualControlLoopEvent(); - onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); - onsetEvent.setRequestId(UUID.randomUUID()); - onsetEvent.setClosedLoopEventClient("tca.instance00001"); - onsetEvent.setTargetType(ControlLoopTargetType.VM); - onsetEvent.setTarget("generic-vnf.vnf-name"); - onsetEvent.setFrom("DCAE"); - onsetEvent.setClosedLoopAlarmStart(Instant.now()); - onsetEvent.setAai(new HashMap<>()); - onsetEvent.getAai().put("generic-vnf.vnf-name", "fw0001vm001fw001"); - onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); - - /* Construct an operation with an APPC actor and restart operation. */ - operation = new ControlLoopOperation(); - operation.setActor("APPC"); - operation.setOperation(RECIPE_RESTART); - operation.setTarget("VM"); - operation.setEnd(Instant.now()); - operation.setSubRequestId("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.VNF)); - policy.setRecipe(RECIPE_RESTART); - policy.setPayload(null); - policy.setRetry(2); - policy.setTimeout(300); - - /* A sample DMAAP request wrapper. */ - AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); - dmaapRequest.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); - dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); - dmaapRequest.setType("request"); - - /* A sample DMAAP response wrapper */ - dmaapResponse = new AppcLcmDmaapWrapper(); - dmaapResponse.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); - dmaapResponse.setRpcName(policy.getRecipe().toLowerCase()); - dmaapResponse.setType("response"); - - /* A sample APPC LCM request. */ - AppcLcmInput appcRequest = new AppcLcmInput(); - - /* The following code constructs a sample APPC LCM Request */ - appcRequest.setAction("restart"); - - HashMap actionIdentifiers = new HashMap<>(); - actionIdentifiers.put(VNF_ID_KEY, "trial-vnf-003"); - - appcRequest.setActionIdentifiers(actionIdentifiers); - - AppcLcmCommonHeader commonHeader = new AppcLcmCommonHeader(); - commonHeader.setRequestId(onsetEvent.getRequestId()); - commonHeader.setSubRequestId("1"); - commonHeader.setOriginatorId(onsetEvent.getRequestId().toString()); - - appcRequest.setCommonHeader(commonHeader); - - appcRequest.setPayload(null); - - AppcLcmBody appcBody = new AppcLcmBody(); - appcBody.setInput(appcRequest); - - dmaapRequest.setBody(appcBody); - - /* The following code constructs a sample APPC LCM Response */ - AppcLcmOutput appcResponse = new AppcLcmOutput(appcRequest); - appcResponse.getStatus().setCode(400); - appcResponse.getStatus().setMessage("Restart Successful"); - - appcBody.setOutput(appcResponse); - - dmaapResponse.setBody(appcBody); - } - - /** - * Set up before test class. - * - * @throws Exception if an error occurs - */ - @BeforeClass - public static void setUpSimulator() throws Exception { - Util.buildAaiSim(); - } - - /** - * Tear down after test class. - */ - @AfterClass - public static void tearDownSimulator() { - HttpServletServerFactoryInstance.getServerFactory().destroy(); - } - - @Test - public void testConstructor() { - AppcLcmActorServiceProvider prov = new AppcLcmActorServiceProvider(); - assertEquals(-1, prov.getSequenceNumber()); - - // verify that it has the operators we expect - var expected = AppcLcmConstants.COMBINED_OPERATION_NAMES.stream().sorted().collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - } - - /** - * A test to construct an APPC LCM restart request. - */ - @Test - public void constructRestartRequestTest() { - - AppcLcmDmaapWrapper dmaapRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, policy, VNF01); - - /* The service provider must return a non null DMAAP request wrapper */ - assertNotNull(dmaapRequest); - - /* The DMAAP wrapper's type field must be request */ - assertEquals("request", dmaapRequest.getType()); - - /* The DMAAP wrapper's body field cannot be null */ - assertNotNull(dmaapRequest.getBody()); - - AppcLcmInput appcRequest = dmaapRequest.getBody().getInput(); - - /* A common header is required and cannot be null */ - assertNotNull(appcRequest.getCommonHeader()); - assertEquals(appcRequest.getCommonHeader().getRequestId(), onsetEvent.getRequestId()); - - /* An action is required and cannot be null */ - assertNotNull(appcRequest.getAction()); - assertEquals(RECIPE_RESTART, appcRequest.getAction()); - - /* Action Identifiers are required and cannot be null */ - assertNotNull(appcRequest.getActionIdentifiers()); - assertNotNull(appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); - assertEquals(VNF01, appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); - - logger.debug("APPC Request: \n" + appcRequest.toString()); - } - - /** - * A test to process a successful APPC restart response. - */ - @Test - public void processRestartResponseSuccessTest() { - AbstractMap.SimpleEntry result = - AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.SUCCESS, result.getKey()); - assertEquals("Restart Successful", result.getValue()); - } - - /** - * A test to assert that a null pointer exception is thrown if the APPC response body - * is null. - */ - @Test(expected = NullPointerException.class) - public void processNullBodyResponseTest() { - AppcLcmActorServiceProvider.processResponse(new AppcLcmDmaapWrapper()); - } - - /** - * A test to assert that a null pointer exception is thrown if the APPC response - * output is null. - */ - @Test(expected = NullPointerException.class) - public void processNullOutputResponseTest() { - AppcLcmDmaapWrapper dmaapWrapper = new AppcLcmDmaapWrapper(); - dmaapWrapper.setBody(new AppcLcmBody()); - AppcLcmActorServiceProvider.processResponse(dmaapWrapper); - } - - /** - * A test to map APPC response results to corresponding Policy results. - */ - @Test - public void appcToPolicyResultTest() { - - AbstractMap.SimpleEntry result; - - /* If APPC accepts, PolicyResult is null */ - dmaapResponse.getBody().getOutput().getStatus().setCode(100); - dmaapResponse.getBody().getOutput().getStatus().setMessage("ACCEPTED"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertNull(result.getKey()); - - /* If APPC is successful, PolicyResult is success */ - dmaapResponse.getBody().getOutput().getStatus().setCode(400); - dmaapResponse.getBody().getOutput().getStatus().setMessage("SUCCESS"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.SUCCESS, result.getKey()); - - /* If APPC returns an error, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(200); - dmaapResponse.getBody().getOutput().getStatus().setMessage("ERROR"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC rejects, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(300); - dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* Test multiple reject codes */ - dmaapResponse.getBody().getOutput().getStatus().setCode(306); - dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - dmaapResponse.getBody().getOutput().getStatus().setCode(313); - dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC returns failure, PolicyResult is failure */ - dmaapResponse.getBody().getOutput().getStatus().setCode(401); - dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE, result.getKey()); - - /* Test multiple failure codes */ - dmaapResponse.getBody().getOutput().getStatus().setCode(406); - dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE, result.getKey()); - - dmaapResponse.getBody().getOutput().getStatus().setCode(450); - dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE, result.getKey()); - - /* If APPC returns partial success, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(500); - dmaapResponse.getBody().getOutput().getStatus().setMessage("PARTIAL SUCCESS"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC returns partial failure, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(501); - dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* Test multiple partial failure codes */ - dmaapResponse.getBody().getOutput().getStatus().setCode(599); - dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - dmaapResponse.getBody().getOutput().getStatus().setCode(550); - dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC code is unknown to Policy, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(700); - dmaapResponse.getBody().getOutput().getStatus().setMessage("UNKNOWN"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - } - - /* - * This test exercises getters not exercised in other tests. - */ - @Test - public void testMethods() { - AppcLcmActorServiceProvider sp = new AppcLcmActorServiceProvider(); - - assertEquals("APPC", sp.actor()); - assertEquals(4, sp.recipes().size()); - assertEquals("VM", sp.recipeTargets(RECIPE_RESTART).get(0)); - assertEquals("vm-id", sp.recipePayloads(RECIPE_RESTART).get(0)); - } - - @Test - public void testPayloadNotPassedWhenNotSupportedByRecipe() { - // given - Policy migratePolicy = constructPolicyWithRecipe(RECIPE_MIGRATE); - Policy rebuildPolicy = constructPolicyWithRecipe(RECIPE_REBUILD); - Policy restartPolicy = constructPolicyWithRecipe(RECIPE_RESTART); - - // when - AppcLcmDmaapWrapper migrateRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, migratePolicy, VNF01); - AppcLcmDmaapWrapper rebuildRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, rebuildPolicy, VNF01); - AppcLcmDmaapWrapper restartRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, restartPolicy, VNF01); - - // then - assertNull(migrateRequest.getBody().getInput().getPayload()); - assertNull(rebuildRequest.getBody().getInput().getPayload()); - assertNull(restartRequest.getBody().getInput().getPayload()); - } - - @Test - public void testPayloadNotPassedWhenNotSuppliedOrEmpty() { - // given - Policy noPayloadPolicy = constructHealthCheckPolicyWithPayload(null); - Policy emptyPayloadPolicy = constructHealthCheckPolicyWithPayload(new HashMap<>()); - - // when - AppcLcmDmaapWrapper noPayloadRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, noPayloadPolicy, VNF01); - AppcLcmDmaapWrapper emptyPayloadRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, emptyPayloadPolicy, VNF01); - - // then - assertNull(noPayloadRequest.getBody().getInput().getPayload()); - assertNull(emptyPayloadRequest.getBody().getInput().getPayload()); - } - - @Test - public void testPayloadParsedProperlyForSinglePayloadParameter() { - // given - HashMap payload = new HashMap<>(); - payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); - Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); - - // when - AppcLcmDmaapWrapper dmaapRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, otherPolicy, VNF01); - - // then - assertEquals("{\"requestParameters\": {\"host-ip-address\":\"10.183.37.25\"}}", - dmaapRequest.getBody().getInput().getPayload()); - } - - @Test - public void testPayloadParsedProperlyForMultiplePayloadParameters() { - // given - HashMap payload = new HashMap<>(); - payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); - payload.put("configurationParameters", - "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," - + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," - + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]"); - Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); - - // when - AppcLcmDmaapWrapper dmaapRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, otherPolicy, VNF01); - - // then - assertEquals(dmaapRequest.getBody().getInput().getPayload(), "{\"requestParameters\": " - + "{\"host-ip-address\":\"10.183.37.25\"}," + "\"configurationParameters\": " - + "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," - + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," - + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]" + "}"); - } - - private Policy constructHealthCheckPolicyWithPayload(HashMap payload) { - return constructHealthCheckPolicyWithPayloadAndRecipe(payload, "Health-Check"); - } - - private Policy constructPolicyWithRecipe(String recipe) { - return constructHealthCheckPolicyWithPayloadAndRecipe(null, recipe); - } - - private Policy constructHealthCheckPolicyWithPayloadAndRecipe(HashMap payload, String recipe) { - Policy otherPolicy = new Policy(); - otherPolicy.setName("Perform health check"); - otherPolicy.setDescription("Upon getting the trigger event, perform health check"); - otherPolicy.setActor("APPC"); - otherPolicy.setTarget(new Target(TargetType.VNF)); - otherPolicy.setRecipe(recipe); - otherPolicy.setPayload(payload); - otherPolicy.setRetry(2); - otherPolicy.setTimeout(300); - return otherPolicy; - } -} diff --git a/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java b/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java new file mode 100644 index 000000000..e2bbb10db --- /dev/null +++ b/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java @@ -0,0 +1,457 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.time.Instant; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.UUID; +import java.util.stream.Collectors; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.appclcm.AppcLcmBody; +import org.onap.policy.appclcm.AppcLcmCommonHeader; +import org.onap.policy.appclcm.AppcLcmDmaapWrapper; +import org.onap.policy.appclcm.AppcLcmInput; +import org.onap.policy.appclcm.AppcLcmOutput; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +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.onap.policy.simulators.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmActorTest { + + private static final String VNF01 = "vnf01"; + + private static final String VNF_ID_KEY = "vnf-id"; + + private static final String REJECT = "REJECT"; + + private static final String PARTIAL_FAILURE = "PARTIAL FAILURE"; + + private static final String FAILURE = "FAILURE"; + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorTest.class); + + private static final VirtualControlLoopEvent onsetEvent; + private static final ControlLoopOperation operation; + private static final Policy policy; + private static final AppcLcmDmaapWrapper dmaapResponse; + + private static final String RECIPE_RESTART = "Restart"; + private static final String RECIPE_REBUILD = "Rebuild"; + private static final String RECIPE_MIGRATE = "Migrate"; + + static { + /* + * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a + * target type of VM. + */ + onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); + onsetEvent.setRequestId(UUID.randomUUID()); + onsetEvent.setClosedLoopEventClient("tca.instance00001"); + onsetEvent.setTargetType(ControlLoopTargetType.VM); + onsetEvent.setTarget("generic-vnf.vnf-name"); + onsetEvent.setFrom("DCAE"); + onsetEvent.setClosedLoopAlarmStart(Instant.now()); + onsetEvent.setAai(new HashMap<>()); + onsetEvent.getAai().put("generic-vnf.vnf-name", "fw0001vm001fw001"); + onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); + + /* Construct an operation with an APPC actor and restart operation. */ + operation = new ControlLoopOperation(); + operation.setActor("APPC"); + operation.setOperation(RECIPE_RESTART); + operation.setTarget("VM"); + operation.setEnd(Instant.now()); + operation.setSubRequestId("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.VNF)); + policy.setRecipe(RECIPE_RESTART); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + + /* A sample DMAAP request wrapper. */ + AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); + dmaapRequest.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); + dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); + dmaapRequest.setType("request"); + + /* A sample DMAAP response wrapper */ + dmaapResponse = new AppcLcmDmaapWrapper(); + dmaapResponse.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); + dmaapResponse.setRpcName(policy.getRecipe().toLowerCase()); + dmaapResponse.setType("response"); + + /* A sample APPC LCM request. */ + AppcLcmInput appcRequest = new AppcLcmInput(); + + /* The following code constructs a sample APPC LCM Request */ + appcRequest.setAction("restart"); + + HashMap actionIdentifiers = new HashMap<>(); + actionIdentifiers.put(VNF_ID_KEY, "trial-vnf-003"); + + appcRequest.setActionIdentifiers(actionIdentifiers); + + AppcLcmCommonHeader commonHeader = new AppcLcmCommonHeader(); + commonHeader.setRequestId(onsetEvent.getRequestId()); + commonHeader.setSubRequestId("1"); + commonHeader.setOriginatorId(onsetEvent.getRequestId().toString()); + + appcRequest.setCommonHeader(commonHeader); + + appcRequest.setPayload(null); + + AppcLcmBody appcBody = new AppcLcmBody(); + appcBody.setInput(appcRequest); + + dmaapRequest.setBody(appcBody); + + /* The following code constructs a sample APPC LCM Response */ + AppcLcmOutput appcResponse = new AppcLcmOutput(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("Restart Successful"); + + appcBody.setOutput(appcResponse); + + dmaapResponse.setBody(appcBody); + } + + /** + * Set up before test class. + * + * @throws Exception if an error occurs + */ + @BeforeClass + public static void setUpSimulator() throws Exception { + Util.buildAaiSim(); + } + + /** + * Tear down after test class. + */ + @AfterClass + public static void tearDownSimulator() { + HttpServletServerFactoryInstance.getServerFactory().destroy(); + } + + @Test + public void testConstructor() { + AppcLcmActor prov = new AppcLcmActor(); + assertEquals(-1, prov.getSequenceNumber()); + + // verify that it has the operators we expect + var expected = AppcLcmConstants.COMBINED_OPERATION_NAMES.stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + /** + * A test to construct an APPC LCM restart request. + */ + @Test + public void constructRestartRequestTest() { + + AppcLcmDmaapWrapper dmaapRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, policy, VNF01); + + /* The service provider must return a non null DMAAP request wrapper */ + assertNotNull(dmaapRequest); + + /* The DMAAP wrapper's type field must be request */ + assertEquals("request", dmaapRequest.getType()); + + /* The DMAAP wrapper's body field cannot be null */ + assertNotNull(dmaapRequest.getBody()); + + AppcLcmInput appcRequest = dmaapRequest.getBody().getInput(); + + /* A common header is required and cannot be null */ + assertNotNull(appcRequest.getCommonHeader()); + assertEquals(appcRequest.getCommonHeader().getRequestId(), onsetEvent.getRequestId()); + + /* An action is required and cannot be null */ + assertNotNull(appcRequest.getAction()); + assertEquals(RECIPE_RESTART, appcRequest.getAction()); + + /* Action Identifiers are required and cannot be null */ + assertNotNull(appcRequest.getActionIdentifiers()); + assertNotNull(appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); + assertEquals(VNF01, appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); + + logger.debug("APPC Request: \n" + appcRequest.toString()); + } + + /** + * A test to process a successful APPC restart response. + */ + @Test + public void processRestartResponseSuccessTest() { + AbstractMap.SimpleEntry result = + AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.SUCCESS, result.getKey()); + assertEquals("Restart Successful", result.getValue()); + } + + /** + * A test to assert that a null pointer exception is thrown if the APPC response body + * is null. + */ + @Test(expected = NullPointerException.class) + public void processNullBodyResponseTest() { + AppcLcmActor.processResponse(new AppcLcmDmaapWrapper()); + } + + /** + * A test to assert that a null pointer exception is thrown if the APPC response + * output is null. + */ + @Test(expected = NullPointerException.class) + public void processNullOutputResponseTest() { + AppcLcmDmaapWrapper dmaapWrapper = new AppcLcmDmaapWrapper(); + dmaapWrapper.setBody(new AppcLcmBody()); + AppcLcmActor.processResponse(dmaapWrapper); + } + + /** + * A test to map APPC response results to corresponding Policy results. + */ + @Test + public void appcToPolicyResultTest() { + + AbstractMap.SimpleEntry result; + + /* If APPC accepts, PolicyResult is null */ + dmaapResponse.getBody().getOutput().getStatus().setCode(100); + dmaapResponse.getBody().getOutput().getStatus().setMessage("ACCEPTED"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertNull(result.getKey()); + + /* If APPC is successful, PolicyResult is success */ + dmaapResponse.getBody().getOutput().getStatus().setCode(400); + dmaapResponse.getBody().getOutput().getStatus().setMessage("SUCCESS"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.SUCCESS, result.getKey()); + + /* If APPC returns an error, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(200); + dmaapResponse.getBody().getOutput().getStatus().setMessage("ERROR"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC rejects, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(300); + dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* Test multiple reject codes */ + dmaapResponse.getBody().getOutput().getStatus().setCode(306); + dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + dmaapResponse.getBody().getOutput().getStatus().setCode(313); + dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC returns failure, PolicyResult is failure */ + dmaapResponse.getBody().getOutput().getStatus().setCode(401); + dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE, result.getKey()); + + /* Test multiple failure codes */ + dmaapResponse.getBody().getOutput().getStatus().setCode(406); + dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE, result.getKey()); + + dmaapResponse.getBody().getOutput().getStatus().setCode(450); + dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE, result.getKey()); + + /* If APPC returns partial success, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(500); + dmaapResponse.getBody().getOutput().getStatus().setMessage("PARTIAL SUCCESS"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC returns partial failure, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(501); + dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* Test multiple partial failure codes */ + dmaapResponse.getBody().getOutput().getStatus().setCode(599); + dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + dmaapResponse.getBody().getOutput().getStatus().setCode(550); + dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC code is unknown to Policy, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(700); + dmaapResponse.getBody().getOutput().getStatus().setMessage("UNKNOWN"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + } + + /* + * This test exercises getters not exercised in other tests. + */ + @Test + public void testMethods() { + AppcLcmActor sp = new AppcLcmActor(); + + assertEquals("APPC", sp.actor()); + assertEquals(4, sp.recipes().size()); + assertEquals("VM", sp.recipeTargets(RECIPE_RESTART).get(0)); + assertEquals("vm-id", sp.recipePayloads(RECIPE_RESTART).get(0)); + } + + @Test + public void testPayloadNotPassedWhenNotSupportedByRecipe() { + // given + Policy migratePolicy = constructPolicyWithRecipe(RECIPE_MIGRATE); + Policy rebuildPolicy = constructPolicyWithRecipe(RECIPE_REBUILD); + Policy restartPolicy = constructPolicyWithRecipe(RECIPE_RESTART); + + // when + AppcLcmDmaapWrapper migrateRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, migratePolicy, VNF01); + AppcLcmDmaapWrapper rebuildRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, rebuildPolicy, VNF01); + AppcLcmDmaapWrapper restartRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, restartPolicy, VNF01); + + // then + assertNull(migrateRequest.getBody().getInput().getPayload()); + assertNull(rebuildRequest.getBody().getInput().getPayload()); + assertNull(restartRequest.getBody().getInput().getPayload()); + } + + @Test + public void testPayloadNotPassedWhenNotSuppliedOrEmpty() { + // given + Policy noPayloadPolicy = constructHealthCheckPolicyWithPayload(null); + Policy emptyPayloadPolicy = constructHealthCheckPolicyWithPayload(new HashMap<>()); + + // when + AppcLcmDmaapWrapper noPayloadRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, noPayloadPolicy, VNF01); + AppcLcmDmaapWrapper emptyPayloadRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, emptyPayloadPolicy, VNF01); + + // then + assertNull(noPayloadRequest.getBody().getInput().getPayload()); + assertNull(emptyPayloadRequest.getBody().getInput().getPayload()); + } + + @Test + public void testPayloadParsedProperlyForSinglePayloadParameter() { + // given + HashMap payload = new HashMap<>(); + payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); + Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); + + // when + AppcLcmDmaapWrapper dmaapRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, otherPolicy, VNF01); + + // then + assertEquals("{\"requestParameters\": {\"host-ip-address\":\"10.183.37.25\"}}", + dmaapRequest.getBody().getInput().getPayload()); + } + + @Test + public void testPayloadParsedProperlyForMultiplePayloadParameters() { + // given + HashMap payload = new HashMap<>(); + payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); + payload.put("configurationParameters", + "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," + + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," + + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]"); + Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); + + // when + AppcLcmDmaapWrapper dmaapRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, otherPolicy, VNF01); + + // then + assertEquals(dmaapRequest.getBody().getInput().getPayload(), "{\"requestParameters\": " + + "{\"host-ip-address\":\"10.183.37.25\"}," + "\"configurationParameters\": " + + "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," + + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," + + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]" + "}"); + } + + private Policy constructHealthCheckPolicyWithPayload(HashMap payload) { + return constructHealthCheckPolicyWithPayloadAndRecipe(payload, "Health-Check"); + } + + private Policy constructPolicyWithRecipe(String recipe) { + return constructHealthCheckPolicyWithPayloadAndRecipe(null, recipe); + } + + private Policy constructHealthCheckPolicyWithPayloadAndRecipe(HashMap payload, String recipe) { + Policy otherPolicy = new Policy(); + otherPolicy.setName("Perform health check"); + otherPolicy.setDescription("Upon getting the trigger event, perform health check"); + otherPolicy.setActor("APPC"); + otherPolicy.setTarget(new Target(TargetType.VNF)); + otherPolicy.setRecipe(recipe); + otherPolicy.setPayload(payload); + otherPolicy.setRetry(2); + otherPolicy.setTimeout(300); + return otherPolicy; + } +} diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActor.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActor.java new file mode 100644 index 000000000..d630d18ae --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActor.java @@ -0,0 +1,288 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019-2020 Bell Canada. All rights reserved. + * Modifications Copyright (C) 2020 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.cds; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Struct; +import com.google.protobuf.Struct.Builder; +import com.google.protobuf.util.JsonFormat; +import io.grpc.Status; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers; +import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader; +import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; +import org.onap.policy.cds.CdsResponse; +import org.onap.policy.cds.api.CdsProcessorListener; +import org.onap.policy.cds.client.CdsProcessorGrpcClient; +import org.onap.policy.cds.properties.CdsServerProperties; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; +import org.onap.policy.controlloop.actor.cds.request.CdsActionRequest; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.actorserviceprovider.impl.ActorImpl; +import org.onap.policy.controlloop.policy.Policy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * CDS is an unusual actor in that it uses a single, generic operator to initiate all + * operation types. The action taken is always the same, only the operation name changes. + */ +public class CdsActor extends ActorImpl { + public static final String NAME = CdsActorConstants.CDS_ACTOR; + + private static final Logger LOGGER = LoggerFactory.getLogger(CdsActor.class); + + /** + * Constructs the object. + */ + public CdsActor() { + super(CdsActorConstants.CDS_ACTOR); + + addOperator(new GrpcOperator(CdsActorConstants.CDS_ACTOR, GrpcOperation.NAME, GrpcOperation::new)); + } + + @Override + public Operator getOperator(String name) { + /* + * All operations are managed by the same operator, regardless of the name. + */ + return super.getOperator(GrpcOperation.NAME); + } + + // TODO old code: remove lines down to **HERE** + + /** + * {@inheritDoc}. + */ + @Override + public String actor() { + return CdsActorConstants.CDS_ACTOR; + } + + /** + * {@inheritDoc}. Note: This is a placeholder for now. + */ + @Override + public List recipes() { + return new ArrayList<>(); + } + + /** + * {@inheritDoc}. Note: This is a placeholder for now. + */ + @Override + public List recipeTargets(final String recipe) { + return new ArrayList<>(); + } + + /** + * {@inheritDoc}. Note: This is a placeholder for now. + */ + @Override + public List recipePayloads(final String recipe) { + return new ArrayList<>(); + } + + /** + * Build the CDS ExecutionServiceInput request from the policy object and the AAI + * enriched parameters. TO-DO: Avoid leaking Exceptions to the Kie Session thread. TBD + * item for Frankfurt release. + * + * @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 specified from the yaml generated by CLAMP or through + * Policy API. + * @param aaiParams Map of enriched AAI attributes in node.attribute notation. + * @return an Optional ExecutionServiceInput instance if valid else an Optional empty + * object is returned. + */ + public Optional constructRequest(VirtualControlLoopEvent onset, + ControlLoopOperation operation, Policy policy, Map aaiParams) { + + // For the current operational TOSCA policy model (yaml) CBA name and version are + // embedded in the payload + // section, with the new policy type model being proposed in Frankfurt we will be + // able to move it out. + Map payload = policy.getPayload(); + if (!validateCdsMandatoryParams(policy)) { + return Optional.empty(); + } + String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME); + String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION); + + // Retain only the payload by removing CBA name and version once they are + // extracted + // to be put in CDS request header. + payload.remove(CdsActorConstants.KEY_CBA_NAME); + payload.remove(CdsActorConstants.KEY_CBA_VERSION); + + // Embed payload from policy to ConfigDeployRequest object, serialize and inject + // into grpc request. + String cbaActionName = policy.getRecipe(); + CdsActionRequest request = new CdsActionRequest(); + request.setPolicyPayload(payload); + request.setActionName(cbaActionName); + request.setResolutionKey(UUID.randomUUID().toString()); + + // Inject AAI properties into payload map. Offer flexibility to the usecase + // implementation to inject whatever AAI parameters are of interest to them. + // E.g. For vFW usecase El-Alto inject service-instance-id, generic-vnf-id as + // needed by CDS. + request.setAaiProperties(aaiParams); + + // Inject any additional event parameters that may be present in the onset event + if (onset.getAdditionalEventParams() != null) { + request.setAdditionalEventParams(onset.getAdditionalEventParams()); + } + + Builder struct = Struct.newBuilder(); + try { + String requestStr = request.generateCdsPayload(); + Preconditions.checkState(!Strings.isNullOrEmpty(requestStr), + "Unable to build " + "config-deploy-request from payload parameters: {}", payload); + JsonFormat.parser().merge(requestStr, struct); + } catch (InvalidProtocolBufferException | CoderException e) { + LOGGER.error("Failed to embed CDS payload string into the input request. blueprint({}:{}) for action({})", + cbaName, cbaVersion, cbaActionName, e); + return Optional.empty(); + } + + // Build CDS gRPC request common-header + CommonHeader commonHeader = CommonHeader.newBuilder().setOriginatorId(CdsActorConstants.ORIGINATOR_ID) + .setRequestId(onset.getRequestId().toString()).setSubRequestId(operation.getSubRequestId()) + .build(); + + // Build CDS gRPC request action-identifier + ActionIdentifiers actionIdentifiers = + ActionIdentifiers.newBuilder().setBlueprintName(cbaName).setBlueprintVersion(cbaVersion) + .setActionName(cbaActionName).setMode(CdsActorConstants.CDS_MODE).build(); + + // Finally build the ExecutionServiceInput gRPC request object. + ExecutionServiceInput executionServiceInput = ExecutionServiceInput.newBuilder().setCommonHeader(commonHeader) + .setActionIdentifiers(actionIdentifiers).setPayload(struct.build()).build(); + return Optional.of(executionServiceInput); + } + + private boolean validateCdsMandatoryParams(Policy policy) { + if (policy == null || policy.getPayload() == null) { + return false; + } + Map payload = policy.getPayload(); + String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME); + String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION); + String cbaActionName = policy.getRecipe(); + return !Strings.isNullOrEmpty(cbaName) && !Strings.isNullOrEmpty(cbaVersion) + && !Strings.isNullOrEmpty(cbaActionName); + } + + public class CdsActorServiceManager implements CdsProcessorListener { + + private final AtomicReference cdsStatus = new AtomicReference<>(); + + /** + * {@inheritDoc}. + */ + @Override + public void onMessage(final ExecutionServiceOutput message) { + LOGGER.info("Received notification from CDS: {}", message); + EventType eventType = message.getStatus().getEventType(); + switch (eventType) { + case EVENT_COMPONENT_FAILURE: + cdsStatus.compareAndSet(null, CdsActorConstants.FAILED); + break; + case EVENT_COMPONENT_PROCESSING: + cdsStatus.compareAndSet(null, CdsActorConstants.PROCESSING); + break; + case EVENT_COMPONENT_EXECUTED: + cdsStatus.compareAndSet(null, CdsActorConstants.SUCCESS); + break; + default: + cdsStatus.compareAndSet(null, CdsActorConstants.FAILED); + break; + } + } + + /** + * {@inheritDoc}. + */ + @Override + public void onError(final Throwable throwable) { + Status status = Status.fromThrowable(throwable); + cdsStatus.compareAndSet(null, CdsActorConstants.ERROR); + LOGGER.error("Failed processing blueprint {}", status, throwable); + } + + /** + * Send gRPC request to CDS to execute the blueprint. + * + * @param cdsClient CDS grpc client object. + * @param cdsProps CDS properties. + * @param executionServiceInput a valid CDS grpc request object. + * @return the cds response. + */ + public CdsResponse sendRequestToCds(CdsProcessorGrpcClient cdsClient, CdsServerProperties cdsProps, + ExecutionServiceInput executionServiceInput) { + try { + LOGGER.trace("Start CdsActorServiceProvider.executeCdsBlueprintProcessor {}.", executionServiceInput); + // TO-DO: Handle requests asynchronously once the callback support is + // added to actors. + CountDownLatch countDownLatch = cdsClient.sendRequest(executionServiceInput); + boolean status = countDownLatch.await(cdsProps.getTimeout(), TimeUnit.SECONDS); + if (!status) { + cdsStatus.compareAndSet(null, CdsActorConstants.TIMED_OUT); + } + LOGGER.info("CDS status response {}", getCdsStatus()); + } catch (InterruptedException ex) { + LOGGER.error("Caught exception in executeCdsBlueprintProcessor in CdsActorServiceProvider: ", ex); + cdsStatus.compareAndSet(null, CdsActorConstants.INTERRUPTED); + Thread.currentThread().interrupt(); + } + LOGGER.info("Status of the CDS gRPC request is: {}", getCdsStatus()); + + CdsResponse response = new CdsResponse(); + response.setRequestId(executionServiceInput != null && executionServiceInput.getCommonHeader() != null + ? executionServiceInput.getCommonHeader().getRequestId() + : null); + response.setStatus(this.getCdsStatus()); + return response; + } + + String getCdsStatus() { + return cdsStatus.get(); + } + } + + // **HERE** +} diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java deleted file mode 100644 index 45ef34495..000000000 --- a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java +++ /dev/null @@ -1,288 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2019-2020 Bell Canada. All rights reserved. - * Modifications Copyright (C) 2020 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.cds; - -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Struct; -import com.google.protobuf.Struct.Builder; -import com.google.protobuf.util.JsonFormat; -import io.grpc.Status; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers; -import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader; -import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType; -import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; -import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; -import org.onap.policy.cds.CdsResponse; -import org.onap.policy.cds.api.CdsProcessorListener; -import org.onap.policy.cds.client.CdsProcessorGrpcClient; -import org.onap.policy.cds.properties.CdsServerProperties; -import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; -import org.onap.policy.controlloop.actor.cds.request.CdsActionRequest; -import org.onap.policy.controlloop.actorserviceprovider.Operator; -import org.onap.policy.controlloop.actorserviceprovider.impl.ActorImpl; -import org.onap.policy.controlloop.policy.Policy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * CDS is an unusual actor in that it uses a single, generic operator to initiate all - * operation types. The action taken is always the same, only the operation name changes. - */ -public class CdsActorServiceProvider extends ActorImpl { - public static final String NAME = CdsActorConstants.CDS_ACTOR; - - private static final Logger LOGGER = LoggerFactory.getLogger(CdsActorServiceProvider.class); - - /** - * Constructs the object. - */ - public CdsActorServiceProvider() { - super(CdsActorConstants.CDS_ACTOR); - - addOperator(new GrpcOperator(CdsActorConstants.CDS_ACTOR, GrpcOperation.NAME, GrpcOperation::new)); - } - - @Override - public Operator getOperator(String name) { - /* - * All operations are managed by the same operator, regardless of the name. - */ - return super.getOperator(GrpcOperation.NAME); - } - - // TODO old code: remove lines down to **HERE** - - /** - * {@inheritDoc}. - */ - @Override - public String actor() { - return CdsActorConstants.CDS_ACTOR; - } - - /** - * {@inheritDoc}. Note: This is a placeholder for now. - */ - @Override - public List recipes() { - return new ArrayList<>(); - } - - /** - * {@inheritDoc}. Note: This is a placeholder for now. - */ - @Override - public List recipeTargets(final String recipe) { - return new ArrayList<>(); - } - - /** - * {@inheritDoc}. Note: This is a placeholder for now. - */ - @Override - public List recipePayloads(final String recipe) { - return new ArrayList<>(); - } - - /** - * Build the CDS ExecutionServiceInput request from the policy object and the AAI - * enriched parameters. TO-DO: Avoid leaking Exceptions to the Kie Session thread. TBD - * item for Frankfurt release. - * - * @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 specified from the yaml generated by CLAMP or through - * Policy API. - * @param aaiParams Map of enriched AAI attributes in node.attribute notation. - * @return an Optional ExecutionServiceInput instance if valid else an Optional empty - * object is returned. - */ - public Optional constructRequest(VirtualControlLoopEvent onset, - ControlLoopOperation operation, Policy policy, Map aaiParams) { - - // For the current operational TOSCA policy model (yaml) CBA name and version are - // embedded in the payload - // section, with the new policy type model being proposed in Frankfurt we will be - // able to move it out. - Map payload = policy.getPayload(); - if (!validateCdsMandatoryParams(policy)) { - return Optional.empty(); - } - String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME); - String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION); - - // Retain only the payload by removing CBA name and version once they are - // extracted - // to be put in CDS request header. - payload.remove(CdsActorConstants.KEY_CBA_NAME); - payload.remove(CdsActorConstants.KEY_CBA_VERSION); - - // Embed payload from policy to ConfigDeployRequest object, serialize and inject - // into grpc request. - String cbaActionName = policy.getRecipe(); - CdsActionRequest request = new CdsActionRequest(); - request.setPolicyPayload(payload); - request.setActionName(cbaActionName); - request.setResolutionKey(UUID.randomUUID().toString()); - - // Inject AAI properties into payload map. Offer flexibility to the usecase - // implementation to inject whatever AAI parameters are of interest to them. - // E.g. For vFW usecase El-Alto inject service-instance-id, generic-vnf-id as - // needed by CDS. - request.setAaiProperties(aaiParams); - - // Inject any additional event parameters that may be present in the onset event - if (onset.getAdditionalEventParams() != null) { - request.setAdditionalEventParams(onset.getAdditionalEventParams()); - } - - Builder struct = Struct.newBuilder(); - try { - String requestStr = request.generateCdsPayload(); - Preconditions.checkState(!Strings.isNullOrEmpty(requestStr), - "Unable to build " + "config-deploy-request from payload parameters: {}", payload); - JsonFormat.parser().merge(requestStr, struct); - } catch (InvalidProtocolBufferException | CoderException e) { - LOGGER.error("Failed to embed CDS payload string into the input request. blueprint({}:{}) for action({})", - cbaName, cbaVersion, cbaActionName, e); - return Optional.empty(); - } - - // Build CDS gRPC request common-header - CommonHeader commonHeader = CommonHeader.newBuilder().setOriginatorId(CdsActorConstants.ORIGINATOR_ID) - .setRequestId(onset.getRequestId().toString()).setSubRequestId(operation.getSubRequestId()) - .build(); - - // Build CDS gRPC request action-identifier - ActionIdentifiers actionIdentifiers = - ActionIdentifiers.newBuilder().setBlueprintName(cbaName).setBlueprintVersion(cbaVersion) - .setActionName(cbaActionName).setMode(CdsActorConstants.CDS_MODE).build(); - - // Finally build the ExecutionServiceInput gRPC request object. - ExecutionServiceInput executionServiceInput = ExecutionServiceInput.newBuilder().setCommonHeader(commonHeader) - .setActionIdentifiers(actionIdentifiers).setPayload(struct.build()).build(); - return Optional.of(executionServiceInput); - } - - private boolean validateCdsMandatoryParams(Policy policy) { - if (policy == null || policy.getPayload() == null) { - return false; - } - Map payload = policy.getPayload(); - String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME); - String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION); - String cbaActionName = policy.getRecipe(); - return !Strings.isNullOrEmpty(cbaName) && !Strings.isNullOrEmpty(cbaVersion) - && !Strings.isNullOrEmpty(cbaActionName); - } - - public class CdsActorServiceManager implements CdsProcessorListener { - - private final AtomicReference cdsStatus = new AtomicReference<>(); - - /** - * {@inheritDoc}. - */ - @Override - public void onMessage(final ExecutionServiceOutput message) { - LOGGER.info("Received notification from CDS: {}", message); - EventType eventType = message.getStatus().getEventType(); - switch (eventType) { - case EVENT_COMPONENT_FAILURE: - cdsStatus.compareAndSet(null, CdsActorConstants.FAILED); - break; - case EVENT_COMPONENT_PROCESSING: - cdsStatus.compareAndSet(null, CdsActorConstants.PROCESSING); - break; - case EVENT_COMPONENT_EXECUTED: - cdsStatus.compareAndSet(null, CdsActorConstants.SUCCESS); - break; - default: - cdsStatus.compareAndSet(null, CdsActorConstants.FAILED); - break; - } - } - - /** - * {@inheritDoc}. - */ - @Override - public void onError(final Throwable throwable) { - Status status = Status.fromThrowable(throwable); - cdsStatus.compareAndSet(null, CdsActorConstants.ERROR); - LOGGER.error("Failed processing blueprint {}", status, throwable); - } - - /** - * Send gRPC request to CDS to execute the blueprint. - * - * @param cdsClient CDS grpc client object. - * @param cdsProps CDS properties. - * @param executionServiceInput a valid CDS grpc request object. - * @return the cds response. - */ - public CdsResponse sendRequestToCds(CdsProcessorGrpcClient cdsClient, CdsServerProperties cdsProps, - ExecutionServiceInput executionServiceInput) { - try { - LOGGER.trace("Start CdsActorServiceProvider.executeCdsBlueprintProcessor {}.", executionServiceInput); - // TO-DO: Handle requests asynchronously once the callback support is - // added to actors. - CountDownLatch countDownLatch = cdsClient.sendRequest(executionServiceInput); - boolean status = countDownLatch.await(cdsProps.getTimeout(), TimeUnit.SECONDS); - if (!status) { - cdsStatus.compareAndSet(null, CdsActorConstants.TIMED_OUT); - } - LOGGER.info("CDS status response {}", getCdsStatus()); - } catch (InterruptedException ex) { - LOGGER.error("Caught exception in executeCdsBlueprintProcessor in CdsActorServiceProvider: ", ex); - cdsStatus.compareAndSet(null, CdsActorConstants.INTERRUPTED); - Thread.currentThread().interrupt(); - } - LOGGER.info("Status of the CDS gRPC request is: {}", getCdsStatus()); - - CdsResponse response = new CdsResponse(); - response.setRequestId(executionServiceInput != null && executionServiceInput.getCommonHeader() != null - ? executionServiceInput.getCommonHeader().getRequestId() - : null); - response.setStatus(this.getCdsStatus()); - return response; - } - - String getCdsStatus() { - return cdsStatus.get(); - } - } - - // **HERE** -} diff --git a/models-interactions/model-actors/actor.cds/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.cds/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index e91d41989..69d1780bc 100644 --- a/models-interactions/model-actors/actor.cds/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.cds/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider +org.onap.policy.controlloop.actor.cds.CdsActor diff --git a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java deleted file mode 100644 index 73787da3f..000000000 --- a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java +++ /dev/null @@ -1,262 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2019 Bell Canada. All rights reserved. - * Modifications Copyright (C) 2020 Nordix Foundation. - * Modifications Copyright (C) 2020 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.cds; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableMap; -import com.google.protobuf.Struct; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers; -import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader; -import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType; -import org.onap.ccsdk.cds.controllerblueprints.common.api.Status; -import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; -import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; -import org.onap.policy.cds.CdsResponse; -import org.onap.policy.cds.client.CdsProcessorGrpcClient; -import org.onap.policy.cds.properties.CdsServerProperties; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider.CdsActorServiceManager; -import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; -import org.onap.policy.controlloop.actor.test.BasicActor; -import org.onap.policy.controlloop.actorserviceprovider.Operator; -import org.onap.policy.controlloop.policy.Policy; - -public class CdsActorServiceProviderTest extends BasicActor { - - private static final String CDS_BLUEPRINT_NAME = "vfw-cds"; - private static final String CDS_BLUEPRINT_VERSION = "1.0.0"; - private static final UUID REQUEST_ID = UUID.randomUUID(); - private static final String SUBREQUEST_ID = "123456"; - private static final String CDS_RECIPE = "test-cds-recipe"; - - @Mock - private CdsProcessorGrpcClient cdsClient; - private CdsActorServiceProvider cdsActor; - private Policy policy; - private CdsServerProperties cdsProps; - private Map aaiParams; - private VirtualControlLoopEvent onset; - private ControlLoopOperation operation; - - /** - * Test setup. - */ - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - - // Setup policy - policy = new Policy(); - Map payloadMap = new HashMap() { - private static final long serialVersionUID = 1L; - - { - put(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME); - put(CdsActorConstants.KEY_CBA_VERSION, CDS_BLUEPRINT_VERSION); - put("data", "{\"mapInfo\":{\"key\":\"val\"},\"arrayInfo\":[\"one\",\"two\"],\"paramInfo\":\"val\"}"); - } - }; - policy.setPayload(payloadMap); - policy.setRecipe(CDS_RECIPE); - - // Setup the CDS properties - cdsProps = new CdsServerProperties(); - cdsProps.setHost("10.10.10.10"); - cdsProps.setPort(2000); - cdsProps.setUsername("testUser"); - cdsProps.setPassword("testPassword"); - cdsProps.setTimeout(1); - - // Setup aaiParams - aaiParams = ImmutableMap.of("service-instance-id", "1234", "generic-vnf-id", "5678"); - - // Setup cdsClient - when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(mock(CountDownLatch.class)); - - // Setup the cdsActor - cdsActor = new CdsActorServiceProvider(); - - // Setup onset event - onset = new VirtualControlLoopEvent(); - onset.setRequestId(REQUEST_ID); - - // Setup controlloop operation object - operation = new ControlLoopOperation(); - operation.setSubRequestId(SUBREQUEST_ID); - } - - @Test - public void testActor() { - assertEquals(CdsActorConstants.CDS_ACTOR, cdsActor.actor()); - } - - @Test - public void testActorService() { - // verify that it all plugs into the ActorService - verifyActorService(CdsActorConstants.CDS_ACTOR, "service.yaml"); - } - - @Test - public void testGetOperator() { - CdsActorServiceProvider sp = new CdsActorServiceProvider(); - - // should always return the same operator regardless of the name - Operator oper = sp.getOperator("unknown"); - assertNotNull(oper); - assertSame(oper, sp.getOperator("another")); - } - - @Test - public void testConstructRequestWhenMissingCdsParamsInPolicyPayload() { - policy.setPayload(new HashMap<>()); - Optional cdsRequestOpt = cdsActor.constructRequest(onset, operation, policy, aaiParams); - - assertFalse(cdsRequestOpt.isPresent()); - } - - @Test - public void testConstructRequest() { - Optional cdsRequestOpt = cdsActor.constructRequest(onset, operation, policy, aaiParams); - - assertTrue(cdsRequestOpt.isPresent()); - final ExecutionServiceInput cdsRequest = cdsRequestOpt.get(); - - assertTrue(cdsRequest.hasCommonHeader()); - CommonHeader commonHeader = cdsRequest.getCommonHeader(); - assertEquals(commonHeader.getRequestId(), REQUEST_ID.toString()); - assertEquals(SUBREQUEST_ID, commonHeader.getSubRequestId()); - - assertTrue(cdsRequest.hasPayload()); - Struct cdsPayload = cdsRequest.getPayload(); - assertTrue(cdsPayload.containsFields(CDS_RECIPE + "-request")); - - assertTrue(cdsRequest.hasActionIdentifiers()); - ActionIdentifiers actionIdentifiers = cdsRequest.getActionIdentifiers(); - assertEquals(CDS_RECIPE, actionIdentifiers.getActionName()); - assertEquals(CDS_BLUEPRINT_NAME, actionIdentifiers.getBlueprintName()); - assertEquals(CDS_BLUEPRINT_VERSION, actionIdentifiers.getBlueprintVersion()); - } - - @Test - public void testRecipePayloads() { - assertEquals(0, cdsActor.recipePayloads("").size()); - } - - @Test - public void testRecipes() { - assertEquals(0, cdsActor.recipes().size()); - } - - @Test - public void testRecipeTargets() { - assertEquals(0, cdsActor.recipeTargets("").size()); - } - - @Test - public void testSendRequestToCdsSuccess() { - sendRequestToCds(); - verify(cdsClient).sendRequest(any(ExecutionServiceInput.class)); - } - - @Test - public void testSendRequestToCdsLatchInterrupted() throws InterruptedException { - // Reset cdsClient - CountDownLatch countDownLatch = mock(CountDownLatch.class); - doThrow(new InterruptedException("Test latch interrupted failure")).when(countDownLatch).await(anyLong(), - any(TimeUnit.class)); - when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(countDownLatch); - - CdsActorServiceProvider.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); - CdsResponse response = - cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); - assertTrue(Thread.interrupted()); - assertNotNull(response); - assertEquals(CdsActorConstants.INTERRUPTED, response.getStatus()); - } - - @Test - public void testSendRequestToCdsLatchTimedOut() { - CdsActorServiceProvider.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); - CdsResponse response = - cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); - assertNotNull(response); - assertEquals(CdsActorConstants.TIMED_OUT, response.getStatus()); - } - - @Test - public void testOnMessage() throws InterruptedException { - ExecutionServiceOutput message = ExecutionServiceOutput.newBuilder() - .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_FAILURE).build()).build(); - - // Test "no timeout" scenarios - CountDownLatch latch = mock(CountDownLatch.class); - when(latch.await(anyLong(), any(TimeUnit.class))).thenReturn(true); - when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(latch); - - CdsActorServiceManager cdsActorSvcMgr = sendRequestToCds(); - - // #1: Failure test - cdsActorSvcMgr.onMessage(message); - assertEquals(CdsActorConstants.FAILED, cdsActorSvcMgr.getCdsStatus()); - - // #2: Success test - cdsActorSvcMgr = sendRequestToCds(); - message = ExecutionServiceOutput.newBuilder() - .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_EXECUTED).build()).build(); - cdsActorSvcMgr.onMessage(message); - assertEquals(CdsActorConstants.SUCCESS, cdsActorSvcMgr.getCdsStatus()); - - // #3: Processing test - cdsActorSvcMgr = sendRequestToCds(); - message = ExecutionServiceOutput.newBuilder() - .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_PROCESSING).build()).build(); - cdsActorSvcMgr.onMessage(message); - assertEquals(CdsActorConstants.PROCESSING, cdsActorSvcMgr.getCdsStatus()); - } - - private CdsActorServiceManager sendRequestToCds() { - CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); - cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); - return cdsActorSvcMgr; - } -} diff --git a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorTest.java b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorTest.java new file mode 100644 index 000000000..706f170fb --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorTest.java @@ -0,0 +1,262 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Bell Canada. All rights reserved. + * Modifications Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2020 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.cds; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.Struct; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers; +import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader; +import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType; +import org.onap.ccsdk.cds.controllerblueprints.common.api.Status; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; +import org.onap.policy.cds.CdsResponse; +import org.onap.policy.cds.client.CdsProcessorGrpcClient; +import org.onap.policy.cds.properties.CdsServerProperties; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.cds.CdsActor.CdsActorServiceManager; +import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; +import org.onap.policy.controlloop.actor.test.BasicActor; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.policy.Policy; + +public class CdsActorTest extends BasicActor { + + private static final String CDS_BLUEPRINT_NAME = "vfw-cds"; + private static final String CDS_BLUEPRINT_VERSION = "1.0.0"; + private static final UUID REQUEST_ID = UUID.randomUUID(); + private static final String SUBREQUEST_ID = "123456"; + private static final String CDS_RECIPE = "test-cds-recipe"; + + @Mock + private CdsProcessorGrpcClient cdsClient; + private CdsActor cdsActor; + private Policy policy; + private CdsServerProperties cdsProps; + private Map aaiParams; + private VirtualControlLoopEvent onset; + private ControlLoopOperation operation; + + /** + * Test setup. + */ + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + // Setup policy + policy = new Policy(); + Map payloadMap = new HashMap() { + private static final long serialVersionUID = 1L; + + { + put(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME); + put(CdsActorConstants.KEY_CBA_VERSION, CDS_BLUEPRINT_VERSION); + put("data", "{\"mapInfo\":{\"key\":\"val\"},\"arrayInfo\":[\"one\",\"two\"],\"paramInfo\":\"val\"}"); + } + }; + policy.setPayload(payloadMap); + policy.setRecipe(CDS_RECIPE); + + // Setup the CDS properties + cdsProps = new CdsServerProperties(); + cdsProps.setHost("10.10.10.10"); + cdsProps.setPort(2000); + cdsProps.setUsername("testUser"); + cdsProps.setPassword("testPassword"); + cdsProps.setTimeout(1); + + // Setup aaiParams + aaiParams = ImmutableMap.of("service-instance-id", "1234", "generic-vnf-id", "5678"); + + // Setup cdsClient + when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(mock(CountDownLatch.class)); + + // Setup the cdsActor + cdsActor = new CdsActor(); + + // Setup onset event + onset = new VirtualControlLoopEvent(); + onset.setRequestId(REQUEST_ID); + + // Setup controlloop operation object + operation = new ControlLoopOperation(); + operation.setSubRequestId(SUBREQUEST_ID); + } + + @Test + public void testActor() { + assertEquals(CdsActorConstants.CDS_ACTOR, cdsActor.actor()); + } + + @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(CdsActorConstants.CDS_ACTOR, "service.yaml"); + } + + @Test + public void testGetOperator() { + CdsActor sp = new CdsActor(); + + // should always return the same operator regardless of the name + Operator oper = sp.getOperator("unknown"); + assertNotNull(oper); + assertSame(oper, sp.getOperator("another")); + } + + @Test + public void testConstructRequestWhenMissingCdsParamsInPolicyPayload() { + policy.setPayload(new HashMap<>()); + Optional cdsRequestOpt = cdsActor.constructRequest(onset, operation, policy, aaiParams); + + assertFalse(cdsRequestOpt.isPresent()); + } + + @Test + public void testConstructRequest() { + Optional cdsRequestOpt = cdsActor.constructRequest(onset, operation, policy, aaiParams); + + assertTrue(cdsRequestOpt.isPresent()); + final ExecutionServiceInput cdsRequest = cdsRequestOpt.get(); + + assertTrue(cdsRequest.hasCommonHeader()); + CommonHeader commonHeader = cdsRequest.getCommonHeader(); + assertEquals(commonHeader.getRequestId(), REQUEST_ID.toString()); + assertEquals(SUBREQUEST_ID, commonHeader.getSubRequestId()); + + assertTrue(cdsRequest.hasPayload()); + Struct cdsPayload = cdsRequest.getPayload(); + assertTrue(cdsPayload.containsFields(CDS_RECIPE + "-request")); + + assertTrue(cdsRequest.hasActionIdentifiers()); + ActionIdentifiers actionIdentifiers = cdsRequest.getActionIdentifiers(); + assertEquals(CDS_RECIPE, actionIdentifiers.getActionName()); + assertEquals(CDS_BLUEPRINT_NAME, actionIdentifiers.getBlueprintName()); + assertEquals(CDS_BLUEPRINT_VERSION, actionIdentifiers.getBlueprintVersion()); + } + + @Test + public void testRecipePayloads() { + assertEquals(0, cdsActor.recipePayloads("").size()); + } + + @Test + public void testRecipes() { + assertEquals(0, cdsActor.recipes().size()); + } + + @Test + public void testRecipeTargets() { + assertEquals(0, cdsActor.recipeTargets("").size()); + } + + @Test + public void testSendRequestToCdsSuccess() { + sendRequestToCds(); + verify(cdsClient).sendRequest(any(ExecutionServiceInput.class)); + } + + @Test + public void testSendRequestToCdsLatchInterrupted() throws InterruptedException { + // Reset cdsClient + CountDownLatch countDownLatch = mock(CountDownLatch.class); + doThrow(new InterruptedException("Test latch interrupted failure")).when(countDownLatch).await(anyLong(), + any(TimeUnit.class)); + when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(countDownLatch); + + CdsActor.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); + CdsResponse response = + cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); + assertTrue(Thread.interrupted()); + assertNotNull(response); + assertEquals(CdsActorConstants.INTERRUPTED, response.getStatus()); + } + + @Test + public void testSendRequestToCdsLatchTimedOut() { + CdsActor.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); + CdsResponse response = + cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); + assertNotNull(response); + assertEquals(CdsActorConstants.TIMED_OUT, response.getStatus()); + } + + @Test + public void testOnMessage() throws InterruptedException { + ExecutionServiceOutput message = ExecutionServiceOutput.newBuilder() + .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_FAILURE).build()).build(); + + // Test "no timeout" scenarios + CountDownLatch latch = mock(CountDownLatch.class); + when(latch.await(anyLong(), any(TimeUnit.class))).thenReturn(true); + when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(latch); + + CdsActorServiceManager cdsActorSvcMgr = sendRequestToCds(); + + // #1: Failure test + cdsActorSvcMgr.onMessage(message); + assertEquals(CdsActorConstants.FAILED, cdsActorSvcMgr.getCdsStatus()); + + // #2: Success test + cdsActorSvcMgr = sendRequestToCds(); + message = ExecutionServiceOutput.newBuilder() + .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_EXECUTED).build()).build(); + cdsActorSvcMgr.onMessage(message); + assertEquals(CdsActorConstants.SUCCESS, cdsActorSvcMgr.getCdsStatus()); + + // #3: Processing test + cdsActorSvcMgr = sendRequestToCds(); + message = ExecutionServiceOutput.newBuilder() + .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_PROCESSING).build()).build(); + cdsActorSvcMgr.onMessage(message); + assertEquals(CdsActorConstants.PROCESSING, cdsActorSvcMgr.getCdsStatus()); + } + + private CdsActorServiceManager sendRequestToCds() { + CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); + cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); + return cdsActorSvcMgr; + } +} diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActor.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActor.java new file mode 100644 index 000000000..59b509291 --- /dev/null +++ b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActor.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019 Huawei Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. + * ================================================================================ + * 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.guard; + +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.OperationPartial; + +public class GuardActor extends HttpActor { + // actor name + public static final String NAME = OperationPartial.GUARD_ACTOR_NAME; + + /** + * Constructs the object. + */ + public GuardActor() { + super(NAME, GuardActorParams.class); + + addOperator(new DecisionOperator(NAME, DecisionOperation.NAME, DecisionOperation::new)); + } +} diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java deleted file mode 100644 index 1cf09d399..000000000 --- a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SdncActorServiceProvider - * ================================================================================ - * Copyright (C) 2018-2019 Huawei Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. - * ================================================================================ - * 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.guard; - -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.OperationPartial; - -public class GuardActorServiceProvider extends HttpActor { - // actor name - public static final String NAME = OperationPartial.GUARD_ACTOR_NAME; - - /** - * Constructs the object. - */ - public GuardActorServiceProvider() { - super(NAME, GuardActorParams.class); - - addOperator(new DecisionOperator(NAME, DecisionOperation.NAME, DecisionOperation::new)); - } -} diff --git a/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index dd4368504..16d7591fa 100644 --- a/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.guard.GuardActorServiceProvider +org.onap.policy.controlloop.actor.guard.GuardActor diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java deleted file mode 100644 index 0ad8161c6..000000000 --- a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2020 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.guard; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.stream.Collectors; -import org.junit.Test; -import org.onap.policy.controlloop.actor.test.BasicActor; - -public class GuardActorServiceProviderTest extends BasicActor { - - @Test - public void test() { - final GuardActorServiceProvider prov = new GuardActorServiceProvider(); - - // verify that it has the operators we expect - var expected = Arrays.asList(DecisionOperation.NAME).stream().sorted().collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - - // verify that it all plugs into the ActorService - verifyActorService(GuardActorServiceProvider.NAME, "service.yaml"); - - assertTrue(prov.getOperator(DecisionOperation.NAME) instanceof DecisionOperator); - } -} diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorTest.java new file mode 100644 index 000000000..e5c3f139d --- /dev/null +++ b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorTest.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.stream.Collectors; +import org.junit.Test; +import org.onap.policy.controlloop.actor.test.BasicActor; + +public class GuardActorTest extends BasicActor { + + @Test + public void test() { + final GuardActor prov = new GuardActor(); + + // verify that it has the operators we expect + var expected = Arrays.asList(DecisionOperation.NAME).stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + + // verify that it all plugs into the ActorService + verifyActorService(GuardActor.NAME, "service.yaml"); + + assertTrue(prov.getOperator(DecisionOperation.NAME) instanceof DecisionOperator); + } +} diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActor.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActor.java new file mode 100644 index 000000000..a5cf65f34 --- /dev/null +++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActor.java @@ -0,0 +1,223 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019 Huawei Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. + * ================================================================================ + * 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.sdnc; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.sdnc.SdncHealNetworkInfo; +import org.onap.policy.sdnc.SdncHealRequest; +import org.onap.policy.sdnc.SdncHealRequestHeaderInfo; +import org.onap.policy.sdnc.SdncHealRequestInfo; +import org.onap.policy.sdnc.SdncHealServiceInfo; +import org.onap.policy.sdnc.SdncHealVfModuleInfo; +import org.onap.policy.sdnc.SdncHealVfModuleParameter; +import org.onap.policy.sdnc.SdncHealVfModuleParametersInfo; +import org.onap.policy.sdnc.SdncHealVfModuleRequestInput; +import org.onap.policy.sdnc.SdncHealVnfInfo; +import org.onap.policy.sdnc.SdncRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SdncActor extends HttpActor { + private static final Logger logger = LoggerFactory.getLogger(SdncActor.class); + + public static final String NAME = "SDNC"; + + // TODO old code: remove lines down to **HERE** + + // Strings for Sdnc Actor + private static final String SDNC_ACTOR = "SDNC"; + + // Strings for targets + private static final String TARGET_VM = "VM"; + + // Strings for recipes + private static final String RECIPE_REROUTE = "Reroute"; + + // Strings for recipes + private static final String RECIPE_BW_ON_DEMAND = "BandwidthOnDemand"; + + private static final ImmutableList recipes = ImmutableList.of(RECIPE_REROUTE); + private static final ImmutableMap> targets = new ImmutableMap.Builder>() + .put(RECIPE_REROUTE, ImmutableList.of(TARGET_VM)).build(); + + // **HERE** + + /** + * Constructs the object. + */ + public SdncActor() { + super(NAME, HttpActorParams.class); + + addOperator(new HttpOperator(NAME, RerouteOperation.NAME, RerouteOperation::new)); + addOperator(new HttpOperator(NAME, BandwidthOnDemandOperation.NAME, BandwidthOnDemandOperation::new)); + } + + + // TODO old code: remove lines down to **HERE** + + @Override + public String actor() { + return SDNC_ACTOR; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + return Collections.emptyList(); + } + + /** + * Construct a request. + * + * @param onset the onset event + * @param operation the control loop operation + * @param policy the policy + * @return the constructed request + */ + public SdncRequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy) { + switch (policy.getRecipe()) { + case RECIPE_REROUTE: + return constructReOptimizeRequest(onset); + case RECIPE_BW_ON_DEMAND: + logger.info("Construct request for receipe {}", RECIPE_BW_ON_DEMAND); + return constructBwOnDemandRequest(onset); + default: + logger.info("Unsupported recipe {}", policy.getRecipe()); + return null; + } + } + + private SdncRequest constructBwOnDemandRequest(VirtualControlLoopEvent onset) { + // Construct an Sdnc request + String serviceInstance = onset.getAai().get("service-instance.service-instance-id"); + if (serviceInstance == null || serviceInstance.isEmpty()) { + // This indicates that AAI Enrichment needs to be done by event producer. + return null; + } + SdncHealVfModuleParameter bandwidth = new SdncHealVfModuleParameter(); + bandwidth.setName("bandwidth"); + bandwidth.setValue(onset.getAai().get("bandwidth")); + + SdncHealVfModuleParameter timeStamp = new SdncHealVfModuleParameter(); + timeStamp.setName("bandwidth-change-time"); + timeStamp.setValue(onset.getAai().get("bandwidth-change-time")); + + SdncHealVfModuleParametersInfo vfParametersInfo = new SdncHealVfModuleParametersInfo(); + vfParametersInfo.addParameters(bandwidth); + vfParametersInfo.addParameters(timeStamp); + + SdncHealVfModuleRequestInput vfRequestInfo = new SdncHealVfModuleRequestInput(); + vfRequestInfo.setVfModuleParametersInfo(vfParametersInfo); + + SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo(); + serviceInfo.setServiceInstanceId(serviceInstance); + + SdncHealRequestInfo requestInfo = new SdncHealRequestInfo(); + requestInfo.setRequestAction("SdwanBandwidthChange"); + + SdncHealRequestHeaderInfo headerInfo = new SdncHealRequestHeaderInfo(); + headerInfo.setSvcAction("update"); + headerInfo.setSvcRequestId(UUID.randomUUID().toString()); + + SdncRequest request = new SdncRequest(); + request.setNsInstanceId(serviceInstance); + request.setRequestId(onset.getRequestId()); + request.setUrl("/GENERIC-RESOURCE-API:vf-module-topology-operation"); + + SdncHealVnfInfo vnfInfo = new SdncHealVnfInfo(); + vnfInfo.setVnfId(onset.getAai().get("vnfId")); + + SdncHealVfModuleInfo vfModuleInfo = new SdncHealVfModuleInfo(); + vfModuleInfo.setVfModuleId(""); + + SdncHealRequest healRequest = new SdncHealRequest(); + healRequest.setVnfInfo(vnfInfo); + healRequest.setVfModuleInfo(vfModuleInfo); + healRequest.setRequestHeaderInfo(headerInfo); + healRequest.setVfModuleRequestInput(vfRequestInfo); + healRequest.setRequestInfo(requestInfo); + healRequest.setServiceInfo(serviceInfo); + request.setHealRequest(healRequest); + return request; + } + + private SdncRequest constructReOptimizeRequest(VirtualControlLoopEvent onset) { + // Construct an Sdnc request + String serviceInstance = onset.getAai().get("service-instance.service-instance-id"); + if (serviceInstance == null || serviceInstance.isEmpty()) { + // This indicates that AAI Enrichment needs to be done by event producer. + return null; + } + SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo(); + serviceInfo.setServiceInstanceId(serviceInstance); + + String networkId = onset.getAai().get("network-information.network-id"); + if (networkId == null || networkId.isEmpty()) { + // This indicates that AAI Enrichment needs to be done by event producer. + return null; + } + SdncHealNetworkInfo networkInfo = new SdncHealNetworkInfo(); + networkInfo.setNetworkId(networkId); + + SdncHealRequestInfo requestInfo = new SdncHealRequestInfo(); + requestInfo.setRequestAction("ReoptimizeSOTNInstance"); + + SdncHealRequestHeaderInfo headerInfo = new SdncHealRequestHeaderInfo(); + headerInfo.setSvcAction("reoptimize"); + headerInfo.setSvcRequestId(UUID.randomUUID().toString()); + + SdncRequest request = new SdncRequest(); + request.setNsInstanceId(serviceInstance); + request.setRequestId(onset.getRequestId()); + request.setUrl("/GENERIC-RESOURCE-API:network-topology-operation"); + + SdncHealRequest healRequest = new SdncHealRequest(); + healRequest.setRequestHeaderInfo(headerInfo); + healRequest.setNetworkInfo(networkInfo); + healRequest.setRequestInfo(requestInfo); + healRequest.setServiceInfo(serviceInfo); + request.setHealRequest(healRequest); + return request; + } + + // **HERE** +} diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java deleted file mode 100644 index cd9ad1ac2..000000000 --- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java +++ /dev/null @@ -1,223 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SdncActorServiceProvider - * ================================================================================ - * Copyright (C) 2018-2019 Huawei Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. - * ================================================================================ - * 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.sdnc; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.sdnc.SdncHealNetworkInfo; -import org.onap.policy.sdnc.SdncHealRequest; -import org.onap.policy.sdnc.SdncHealRequestHeaderInfo; -import org.onap.policy.sdnc.SdncHealRequestInfo; -import org.onap.policy.sdnc.SdncHealServiceInfo; -import org.onap.policy.sdnc.SdncHealVfModuleInfo; -import org.onap.policy.sdnc.SdncHealVfModuleParameter; -import org.onap.policy.sdnc.SdncHealVfModuleParametersInfo; -import org.onap.policy.sdnc.SdncHealVfModuleRequestInput; -import org.onap.policy.sdnc.SdncHealVnfInfo; -import org.onap.policy.sdnc.SdncRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SdncActorServiceProvider extends HttpActor { - private static final Logger logger = LoggerFactory.getLogger(SdncActorServiceProvider.class); - - public static final String NAME = "SDNC"; - - // TODO old code: remove lines down to **HERE** - - // Strings for Sdnc Actor - private static final String SDNC_ACTOR = "SDNC"; - - // Strings for targets - private static final String TARGET_VM = "VM"; - - // Strings for recipes - private static final String RECIPE_REROUTE = "Reroute"; - - // Strings for recipes - private static final String RECIPE_BW_ON_DEMAND = "BandwidthOnDemand"; - - private static final ImmutableList recipes = ImmutableList.of(RECIPE_REROUTE); - private static final ImmutableMap> targets = new ImmutableMap.Builder>() - .put(RECIPE_REROUTE, ImmutableList.of(TARGET_VM)).build(); - - // **HERE** - - /** - * Constructs the object. - */ - public SdncActorServiceProvider() { - super(NAME, HttpActorParams.class); - - addOperator(new HttpOperator(NAME, RerouteOperation.NAME, RerouteOperation::new)); - addOperator(new HttpOperator(NAME, BandwidthOnDemandOperation.NAME, BandwidthOnDemandOperation::new)); - } - - - // TODO old code: remove lines down to **HERE** - - @Override - public String actor() { - return SDNC_ACTOR; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - return Collections.emptyList(); - } - - /** - * Construct a request. - * - * @param onset the onset event - * @param operation the control loop operation - * @param policy the policy - * @return the constructed request - */ - public SdncRequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy) { - switch (policy.getRecipe()) { - case RECIPE_REROUTE: - return constructReOptimizeRequest(onset); - case RECIPE_BW_ON_DEMAND: - logger.info("Construct request for receipe {}", RECIPE_BW_ON_DEMAND); - return constructBwOnDemandRequest(onset); - default: - logger.info("Unsupported recipe {}", policy.getRecipe()); - return null; - } - } - - private SdncRequest constructBwOnDemandRequest(VirtualControlLoopEvent onset) { - // Construct an Sdnc request - String serviceInstance = onset.getAai().get("service-instance.service-instance-id"); - if (serviceInstance == null || serviceInstance.isEmpty()) { - // This indicates that AAI Enrichment needs to be done by event producer. - return null; - } - SdncHealVfModuleParameter bandwidth = new SdncHealVfModuleParameter(); - bandwidth.setName("bandwidth"); - bandwidth.setValue(onset.getAai().get("bandwidth")); - - SdncHealVfModuleParameter timeStamp = new SdncHealVfModuleParameter(); - timeStamp.setName("bandwidth-change-time"); - timeStamp.setValue(onset.getAai().get("bandwidth-change-time")); - - SdncHealVfModuleParametersInfo vfParametersInfo = new SdncHealVfModuleParametersInfo(); - vfParametersInfo.addParameters(bandwidth); - vfParametersInfo.addParameters(timeStamp); - - SdncHealVfModuleRequestInput vfRequestInfo = new SdncHealVfModuleRequestInput(); - vfRequestInfo.setVfModuleParametersInfo(vfParametersInfo); - - SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo(); - serviceInfo.setServiceInstanceId(serviceInstance); - - SdncHealRequestInfo requestInfo = new SdncHealRequestInfo(); - requestInfo.setRequestAction("SdwanBandwidthChange"); - - SdncHealRequestHeaderInfo headerInfo = new SdncHealRequestHeaderInfo(); - headerInfo.setSvcAction("update"); - headerInfo.setSvcRequestId(UUID.randomUUID().toString()); - - SdncRequest request = new SdncRequest(); - request.setNsInstanceId(serviceInstance); - request.setRequestId(onset.getRequestId()); - request.setUrl("/GENERIC-RESOURCE-API:vf-module-topology-operation"); - - SdncHealVnfInfo vnfInfo = new SdncHealVnfInfo(); - vnfInfo.setVnfId(onset.getAai().get("vnfId")); - - SdncHealVfModuleInfo vfModuleInfo = new SdncHealVfModuleInfo(); - vfModuleInfo.setVfModuleId(""); - - SdncHealRequest healRequest = new SdncHealRequest(); - healRequest.setVnfInfo(vnfInfo); - healRequest.setVfModuleInfo(vfModuleInfo); - healRequest.setRequestHeaderInfo(headerInfo); - healRequest.setVfModuleRequestInput(vfRequestInfo); - healRequest.setRequestInfo(requestInfo); - healRequest.setServiceInfo(serviceInfo); - request.setHealRequest(healRequest); - return request; - } - - private SdncRequest constructReOptimizeRequest(VirtualControlLoopEvent onset) { - // Construct an Sdnc request - String serviceInstance = onset.getAai().get("service-instance.service-instance-id"); - if (serviceInstance == null || serviceInstance.isEmpty()) { - // This indicates that AAI Enrichment needs to be done by event producer. - return null; - } - SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo(); - serviceInfo.setServiceInstanceId(serviceInstance); - - String networkId = onset.getAai().get("network-information.network-id"); - if (networkId == null || networkId.isEmpty()) { - // This indicates that AAI Enrichment needs to be done by event producer. - return null; - } - SdncHealNetworkInfo networkInfo = new SdncHealNetworkInfo(); - networkInfo.setNetworkId(networkId); - - SdncHealRequestInfo requestInfo = new SdncHealRequestInfo(); - requestInfo.setRequestAction("ReoptimizeSOTNInstance"); - - SdncHealRequestHeaderInfo headerInfo = new SdncHealRequestHeaderInfo(); - headerInfo.setSvcAction("reoptimize"); - headerInfo.setSvcRequestId(UUID.randomUUID().toString()); - - SdncRequest request = new SdncRequest(); - request.setNsInstanceId(serviceInstance); - request.setRequestId(onset.getRequestId()); - request.setUrl("/GENERIC-RESOURCE-API:network-topology-operation"); - - SdncHealRequest healRequest = new SdncHealRequest(); - healRequest.setRequestHeaderInfo(headerInfo); - healRequest.setNetworkInfo(networkInfo); - healRequest.setRequestInfo(requestInfo); - healRequest.setServiceInfo(serviceInfo); - request.setHealRequest(healRequest); - return request; - } - - // **HERE** -} diff --git a/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index f4d1e975e..0c66fdf75 100644 --- a/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.sdnc.SdncActorServiceProvider \ No newline at end of file +org.onap.policy.controlloop.actor.sdnc.SdncActor diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java deleted file mode 100644 index 752cb9125..000000000 --- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * TestSdncActorServiceProvider - * ================================================================================ - * Copyright (C) 2018-2019 Huawei. All rights reserved. - * Modifications Copyright (C) 2018-2020 AT&T Corp. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.sdnc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.util.Arrays; -import java.util.Objects; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.test.BasicActor; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.sdnc.SdncRequest; - -public class SdncActorServiceProviderTest extends BasicActor { - - private static final String REROUTE = RerouteOperation.NAME; - - /** - * Set up before test class. - * - * @throws Exception if the A&AI simulator cannot be started - */ - @BeforeClass - public static void setUpSimulator() throws Exception { - org.onap.policy.simulators.Util.buildAaiSim(); - } - - @AfterClass - public static void tearDownSimulator() { - HttpServletServerFactoryInstance.getServerFactory().destroy(); - } - - @Test - public void testSdncActorServiceProvider() { - final SdncActorServiceProvider prov = new SdncActorServiceProvider(); - - // verify that it has the operators we expect - var expected = Arrays.asList(BandwidthOnDemandOperation.NAME, RerouteOperation.NAME).stream().sorted() - .collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - - // verify that it all plugs into the ActorService - verifyActorService(SdncActorServiceProvider.NAME, "service.yaml"); - } - - @Test - public void testConstructRequest() { - VirtualControlLoopEvent onset = new VirtualControlLoopEvent(); - ControlLoopOperation operation = new ControlLoopOperation(); - - Policy policy = new Policy(); - policy.setRecipe(REROUTE); - - SdncActorServiceProvider provider = new SdncActorServiceProvider(); - assertNull(provider.constructRequest(onset, operation, policy)); - - onset.getAai().put("network-information.network-id", "network-5555"); - assertNull(provider.constructRequest(onset, operation, policy)); - - assertNull(provider.constructRequest(onset, operation, policy)); - - UUID requestId = UUID.randomUUID(); - onset.setRequestId(requestId); - assertNull(provider.constructRequest(onset, operation, policy)); - - assertNull(provider.constructRequest(onset, operation, policy)); - - onset.getAai().put("service-instance.service-instance-id", "service-instance-01"); - assertNotNull(provider.constructRequest(onset, operation, policy)); - - policy.setRecipe(REROUTE); - assertNotNull(provider.constructRequest(onset, operation, policy)); - - SdncRequest request = provider.constructRequest(onset, operation, policy); - - assertEquals(requestId, Objects.requireNonNull(request).getRequestId()); - assertEquals("reoptimize", request.getHealRequest().getRequestHeaderInfo().getSvcAction()); - assertEquals("ReoptimizeSOTNInstance", request.getHealRequest().getRequestInfo().getRequestAction()); - assertEquals("network-5555", request.getHealRequest().getNetworkInfo().getNetworkId()); - assertEquals("service-instance-01", request.getHealRequest().getServiceInfo().getServiceInstanceId()); - } - - @Test - public void testMethods() { - SdncActorServiceProvider sp = new SdncActorServiceProvider(); - - assertEquals("SDNC", sp.actor()); - assertEquals(1, sp.recipes().size()); - assertEquals(REROUTE, sp.recipes().get(0)); - assertEquals("VM", sp.recipeTargets(REROUTE).get(0)); - assertEquals(0, sp.recipePayloads(REROUTE).size()); - } -} diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorTest.java new file mode 100644 index 000000000..020b09e8c --- /dev/null +++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorTest.java @@ -0,0 +1,124 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * Modifications Copyright (C) 2018-2020 AT&T Corp. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.sdnc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.test.BasicActor; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.sdnc.SdncRequest; + +public class SdncActorTest extends BasicActor { + + private static final String REROUTE = RerouteOperation.NAME; + + /** + * Set up before test class. + * + * @throws Exception if the A&AI simulator cannot be started + */ + @BeforeClass + public static void setUpSimulator() throws Exception { + org.onap.policy.simulators.Util.buildAaiSim(); + } + + @AfterClass + public static void tearDownSimulator() { + HttpServletServerFactoryInstance.getServerFactory().destroy(); + } + + @Test + public void testSdncActorServiceProvider() { + final SdncActor prov = new SdncActor(); + + // verify that it has the operators we expect + var expected = Arrays.asList(BandwidthOnDemandOperation.NAME, RerouteOperation.NAME).stream().sorted() + .collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + + // verify that it all plugs into the ActorService + verifyActorService(SdncActor.NAME, "service.yaml"); + } + + @Test + public void testConstructRequest() { + VirtualControlLoopEvent onset = new VirtualControlLoopEvent(); + ControlLoopOperation operation = new ControlLoopOperation(); + + Policy policy = new Policy(); + policy.setRecipe(REROUTE); + + SdncActor provider = new SdncActor(); + assertNull(provider.constructRequest(onset, operation, policy)); + + onset.getAai().put("network-information.network-id", "network-5555"); + assertNull(provider.constructRequest(onset, operation, policy)); + + assertNull(provider.constructRequest(onset, operation, policy)); + + UUID requestId = UUID.randomUUID(); + onset.setRequestId(requestId); + assertNull(provider.constructRequest(onset, operation, policy)); + + assertNull(provider.constructRequest(onset, operation, policy)); + + onset.getAai().put("service-instance.service-instance-id", "service-instance-01"); + assertNotNull(provider.constructRequest(onset, operation, policy)); + + policy.setRecipe(REROUTE); + assertNotNull(provider.constructRequest(onset, operation, policy)); + + SdncRequest request = provider.constructRequest(onset, operation, policy); + + assertEquals(requestId, Objects.requireNonNull(request).getRequestId()); + assertEquals("reoptimize", request.getHealRequest().getRequestHeaderInfo().getSvcAction()); + assertEquals("ReoptimizeSOTNInstance", request.getHealRequest().getRequestInfo().getRequestAction()); + assertEquals("network-5555", request.getHealRequest().getNetworkInfo().getNetworkId()); + assertEquals("service-instance-01", request.getHealRequest().getServiceInfo().getServiceInstanceId()); + } + + @Test + public void testMethods() { + SdncActor sp = new SdncActor(); + + assertEquals("SDNC", sp.actor()); + assertEquals(1, sp.recipes().size()); + assertEquals(REROUTE, sp.recipes().get(0)); + assertEquals("VM", sp.recipeTargets(REROUTE).get(0)); + assertEquals(0, sp.recipePayloads(REROUTE).size()); + } +} diff --git a/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActor.java b/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActor.java new file mode 100644 index 000000000..b9f477d30 --- /dev/null +++ b/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActor.java @@ -0,0 +1,304 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 Wipro Limited Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019-2020 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.sdnr; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.ControlLoopResponse; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.sdnr.PciCommonHeader; +import org.onap.policy.sdnr.PciRequest; +import org.onap.policy.sdnr.PciRequestWrapper; +import org.onap.policy.sdnr.PciResponse; +import org.onap.policy.sdnr.PciResponseCode; +import org.onap.policy.sdnr.PciResponseWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SDNR is an unusual actor in that it uses a single, generic operator to initiate all + * operation types. The action taken is always the same, only the operation name changes. + */ +public class SdnrActor extends BidirectionalTopicActor { + + public static final String NAME = "SDNR"; + + // TODO old code: remove lines down to **HERE** + + private static final Logger logger = LoggerFactory.getLogger(SdnrActor.class); + + // Strings for targets + private static final String TARGET_VNF = "VNF"; + + // Strings for recipes + private static final String RECIPE_MODIFY = "ModifyConfig"; + + /* To be used in future releases when pci ModifyConfig is used */ + private static final String SDNR_REQUEST_PARAMS = "request-parameters"; + private static final String SDNR_CONFIG_PARAMS = "configuration-parameters"; + + private static final ImmutableList recipes = ImmutableList.of(RECIPE_MODIFY); + private static final ImmutableMap> targets = new ImmutableMap.Builder>() + .put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); + private static final ImmutableMap> payloads = new ImmutableMap.Builder>() + .put(RECIPE_MODIFY, ImmutableList.of(SDNR_REQUEST_PARAMS, SDNR_CONFIG_PARAMS)).build(); + + // **HERE** + + /** + * Constructor. + */ + public SdnrActor() { + super(NAME, BidirectionalTopicActorParams.class); + + addOperator(new BidirectionalTopicOperator(NAME, SdnrOperation.NAME, this, SdnrOperation.SELECTOR_KEYS, + SdnrOperation::new)); + } + + @Override + public Operator getOperator(String name) { + /* + * All operations are managed by the same operator, regardless of the name. + */ + return super.getOperator(SdnrOperation.NAME); + } + + // TODO old code: remove lines down to **HERE** + + @Override + public String actor() { + return NAME; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); + } + + /** + * Constructs an SDNR request conforming to the pci 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 SDNR request conforming to the pci API using the DMAAP wrapper + */ + + public static PciRequestWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, + Policy policy) { + + /* Construct an SDNR request using pci Model */ + + /* + * The actual pci request is placed in a wrapper used to send through dmaap. The + * current version is 2.0 as of R1. + */ + PciRequestWrapper dmaapRequest = new PciRequestWrapper(); + dmaapRequest.setVersion("1.0"); + dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); + dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); + dmaapRequest.setType("request"); + + /* This is the actual request that is placed in the dmaap wrapper. */ + final PciRequest sdnrRequest = new PciRequest(); + + /* The common header is a required field for all SDNR requests. */ + PciCommonHeader requestCommonHeader = new PciCommonHeader(); + requestCommonHeader.setRequestId(onset.getRequestId()); + requestCommonHeader.setSubRequestId(operation.getSubRequestId()); + + sdnrRequest.setCommonHeader(requestCommonHeader); + sdnrRequest.setPayload(onset.getPayload()); + + /* + * An action is required for all SDNR requests, this will be the recipe + * specified in the policy. + */ + sdnrRequest.setAction(policy.getRecipe()); + + /* + * Once the pci request is constructed, add it into the body of the dmaap + * wrapper. + */ + dmaapRequest.setBody(sdnrRequest); + logger.info("SDNR Request to be sent is {}", dmaapRequest); + + /* Return the request to be sent through dmaap. */ + return dmaapRequest; + } + + /** + * Parses the operation attempt using the subRequestId of SDNR response. + * + * @param subRequestId + * the sub id used to send to SDNR, 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 in parsing the operation attempt {}", subRequestId); + return null; + } + return operationAttempt; + } + + /** + * Processes the SDNR pci response sent from SDNR. Determines if the SDNR + * operation was successful/unsuccessful and maps this to the corresponding + * Policy result. + * + * @param dmaapResponse + * the dmaap wrapper message that contains the actual SDNR reponse + * inside the body field + * + * @return an key-value pair that contains the Policy result and SDNR response + * message + */ + public static Pair processResponse( + PciResponseWrapper dmaapResponse) { + + logger.info("SDNR processResponse called : {}", dmaapResponse); + + /* The actual SDNR response is inside the wrapper's body field. */ + PciResponse sdnrResponse = dmaapResponse.getBody(); + + /* The message returned in the SDNR response. */ + String message; + + /* The Policy result determined from the SDNR Response. */ + PolicyResult result; + + /* + * If there is no status, Policy cannot determine if the request was successful. + */ + if (sdnrResponse.getStatus() == null) { + message = "Policy was unable to parse SDN-R response status field (it was null)."; + return Pair.of(PolicyResult.FAILURE_EXCEPTION, message); + } + + /* + * If there is no code, Policy cannot determine if the request was successful. + */ + String responseValue = PciResponseCode.toResponseValue(sdnrResponse.getStatus().getCode()); + if (responseValue == null) { + message = "Policy was unable to parse SDN-R response status code field."; + return Pair.of(PolicyResult.FAILURE_EXCEPTION, message); + } + logger.info("SDNR Response Code is {}", responseValue); + + /* Save the SDNR response's message for Policy notification message. */ + message = sdnrResponse.getStatus().getValue(); + logger.info("SDNR Response Message is {}", message); + + /* + * Response and Payload are just printed and no further action needed in + * casablanca release + */ + String rspPayload = sdnrResponse.getPayload(); + logger.info("SDNR Response Payload is {}", rspPayload); + + /* Maps the SDNR response result to a Policy result. */ + switch (responseValue) { + case PciResponseCode.ACCEPTED: + /* Nothing to do if code is accept, continue processing */ + result = null; + break; + case PciResponseCode.SUCCESS: + result = PolicyResult.SUCCESS; + break; + case PciResponseCode.FAILURE: + result = PolicyResult.FAILURE; + break; + case PciResponseCode.REJECT: + case PciResponseCode.ERROR: + default: + result = PolicyResult.FAILURE_EXCEPTION; + } + return Pair.of(result, message); + } + + /** + * Converts the SDNR response to ControlLoopResponse object. + * + * @param dmaapResponse + * the dmaap wrapper message that contains the actual SDNR reponse + * inside the body field + * + * @return a ControlLoopResponse object to send to DCAE_CL_RSP topic + */ + public static ControlLoopResponse getControlLoopResponse(PciResponseWrapper dmaapResponse, + VirtualControlLoopEvent event) { + + logger.info("SDNR getClosedLoopResponse called : {} {}", dmaapResponse, event); + + /* The actual SDNR response is inside the wrapper's body field. */ + PciResponse sdnrResponse = dmaapResponse.getBody(); + + /* The ControlLoop response determined from the SDNR Response and input event. */ + ControlLoopResponse clRsp = new ControlLoopResponse(); + clRsp.setPayload(sdnrResponse.getPayload()); + clRsp.setFrom(NAME); + clRsp.setTarget("DCAE"); + clRsp.setClosedLoopControlName(event.getClosedLoopControlName()); + clRsp.setPolicyName(event.getPolicyName()); + clRsp.setPolicyVersion(event.getPolicyVersion()); + clRsp.setRequestId(event.getRequestId()); + clRsp.setVersion(event.getVersion()); + logger.info("SDNR getClosedLoopResponse clRsp : {}", clRsp); + + return clRsp; + } + + // **HERE** +} diff --git a/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java b/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java deleted file mode 100644 index a43dcf774..000000000 --- a/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java +++ /dev/null @@ -1,304 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SdnrActorServiceProvider - * ================================================================================ - * Copyright (C) 2018 Wipro Limited Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019-2020 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.sdnr; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.Collections; -import java.util.List; -import org.apache.commons.lang3.tuple.Pair; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.ControlLoopResponse; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actorserviceprovider.Operator; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.PolicyResult; -import org.onap.policy.sdnr.PciCommonHeader; -import org.onap.policy.sdnr.PciRequest; -import org.onap.policy.sdnr.PciRequestWrapper; -import org.onap.policy.sdnr.PciResponse; -import org.onap.policy.sdnr.PciResponseCode; -import org.onap.policy.sdnr.PciResponseWrapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * SDNR is an unusual actor in that it uses a single, generic operator to initiate all - * operation types. The action taken is always the same, only the operation name changes. - */ -public class SdnrActorServiceProvider extends BidirectionalTopicActor { - - public static final String NAME = "SDNR"; - - // TODO old code: remove lines down to **HERE** - - private static final Logger logger = LoggerFactory.getLogger(SdnrActorServiceProvider.class); - - // Strings for targets - private static final String TARGET_VNF = "VNF"; - - // Strings for recipes - private static final String RECIPE_MODIFY = "ModifyConfig"; - - /* To be used in future releases when pci ModifyConfig is used */ - private static final String SDNR_REQUEST_PARAMS = "request-parameters"; - private static final String SDNR_CONFIG_PARAMS = "configuration-parameters"; - - private static final ImmutableList recipes = ImmutableList.of(RECIPE_MODIFY); - private static final ImmutableMap> targets = new ImmutableMap.Builder>() - .put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); - private static final ImmutableMap> payloads = new ImmutableMap.Builder>() - .put(RECIPE_MODIFY, ImmutableList.of(SDNR_REQUEST_PARAMS, SDNR_CONFIG_PARAMS)).build(); - - // **HERE** - - /** - * Constructor. - */ - public SdnrActorServiceProvider() { - super(NAME, BidirectionalTopicActorParams.class); - - addOperator(new BidirectionalTopicOperator(NAME, SdnrOperation.NAME, this, SdnrOperation.SELECTOR_KEYS, - SdnrOperation::new)); - } - - @Override - public Operator getOperator(String name) { - /* - * All operations are managed by the same operator, regardless of the name. - */ - return super.getOperator(SdnrOperation.NAME); - } - - // TODO old code: remove lines down to **HERE** - - @Override - public String actor() { - return NAME; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); - } - - /** - * Constructs an SDNR request conforming to the pci 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 SDNR request conforming to the pci API using the DMAAP wrapper - */ - - public static PciRequestWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, - Policy policy) { - - /* Construct an SDNR request using pci Model */ - - /* - * The actual pci request is placed in a wrapper used to send through dmaap. The - * current version is 2.0 as of R1. - */ - PciRequestWrapper dmaapRequest = new PciRequestWrapper(); - dmaapRequest.setVersion("1.0"); - dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); - dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); - dmaapRequest.setType("request"); - - /* This is the actual request that is placed in the dmaap wrapper. */ - final PciRequest sdnrRequest = new PciRequest(); - - /* The common header is a required field for all SDNR requests. */ - PciCommonHeader requestCommonHeader = new PciCommonHeader(); - requestCommonHeader.setRequestId(onset.getRequestId()); - requestCommonHeader.setSubRequestId(operation.getSubRequestId()); - - sdnrRequest.setCommonHeader(requestCommonHeader); - sdnrRequest.setPayload(onset.getPayload()); - - /* - * An action is required for all SDNR requests, this will be the recipe - * specified in the policy. - */ - sdnrRequest.setAction(policy.getRecipe()); - - /* - * Once the pci request is constructed, add it into the body of the dmaap - * wrapper. - */ - dmaapRequest.setBody(sdnrRequest); - logger.info("SDNR Request to be sent is {}", dmaapRequest); - - /* Return the request to be sent through dmaap. */ - return dmaapRequest; - } - - /** - * Parses the operation attempt using the subRequestId of SDNR response. - * - * @param subRequestId - * the sub id used to send to SDNR, 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 in parsing the operation attempt {}", subRequestId); - return null; - } - return operationAttempt; - } - - /** - * Processes the SDNR pci response sent from SDNR. Determines if the SDNR - * operation was successful/unsuccessful and maps this to the corresponding - * Policy result. - * - * @param dmaapResponse - * the dmaap wrapper message that contains the actual SDNR reponse - * inside the body field - * - * @return an key-value pair that contains the Policy result and SDNR response - * message - */ - public static Pair processResponse( - PciResponseWrapper dmaapResponse) { - - logger.info("SDNR processResponse called : {}", dmaapResponse); - - /* The actual SDNR response is inside the wrapper's body field. */ - PciResponse sdnrResponse = dmaapResponse.getBody(); - - /* The message returned in the SDNR response. */ - String message; - - /* The Policy result determined from the SDNR Response. */ - PolicyResult result; - - /* - * If there is no status, Policy cannot determine if the request was successful. - */ - if (sdnrResponse.getStatus() == null) { - message = "Policy was unable to parse SDN-R response status field (it was null)."; - return Pair.of(PolicyResult.FAILURE_EXCEPTION, message); - } - - /* - * If there is no code, Policy cannot determine if the request was successful. - */ - String responseValue = PciResponseCode.toResponseValue(sdnrResponse.getStatus().getCode()); - if (responseValue == null) { - message = "Policy was unable to parse SDN-R response status code field."; - return Pair.of(PolicyResult.FAILURE_EXCEPTION, message); - } - logger.info("SDNR Response Code is {}", responseValue); - - /* Save the SDNR response's message for Policy notification message. */ - message = sdnrResponse.getStatus().getValue(); - logger.info("SDNR Response Message is {}", message); - - /* - * Response and Payload are just printed and no further action needed in - * casablanca release - */ - String rspPayload = sdnrResponse.getPayload(); - logger.info("SDNR Response Payload is {}", rspPayload); - - /* Maps the SDNR response result to a Policy result. */ - switch (responseValue) { - case PciResponseCode.ACCEPTED: - /* Nothing to do if code is accept, continue processing */ - result = null; - break; - case PciResponseCode.SUCCESS: - result = PolicyResult.SUCCESS; - break; - case PciResponseCode.FAILURE: - result = PolicyResult.FAILURE; - break; - case PciResponseCode.REJECT: - case PciResponseCode.ERROR: - default: - result = PolicyResult.FAILURE_EXCEPTION; - } - return Pair.of(result, message); - } - - /** - * Converts the SDNR response to ControlLoopResponse object. - * - * @param dmaapResponse - * the dmaap wrapper message that contains the actual SDNR reponse - * inside the body field - * - * @return a ControlLoopResponse object to send to DCAE_CL_RSP topic - */ - public static ControlLoopResponse getControlLoopResponse(PciResponseWrapper dmaapResponse, - VirtualControlLoopEvent event) { - - logger.info("SDNR getClosedLoopResponse called : {} {}", dmaapResponse, event); - - /* The actual SDNR response is inside the wrapper's body field. */ - PciResponse sdnrResponse = dmaapResponse.getBody(); - - /* The ControlLoop response determined from the SDNR Response and input event. */ - ControlLoopResponse clRsp = new ControlLoopResponse(); - clRsp.setPayload(sdnrResponse.getPayload()); - clRsp.setFrom(NAME); - clRsp.setTarget("DCAE"); - clRsp.setClosedLoopControlName(event.getClosedLoopControlName()); - clRsp.setPolicyName(event.getPolicyName()); - clRsp.setPolicyVersion(event.getPolicyVersion()); - clRsp.setRequestId(event.getRequestId()); - clRsp.setVersion(event.getVersion()); - logger.info("SDNR getClosedLoopResponse clRsp : {}", clRsp); - - return clRsp; - } - - // **HERE** -} diff --git a/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index c8d5e4c41..af71a9ff3 100644 --- a/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.sdnr.SdnrActorServiceProvider +org.onap.policy.controlloop.actor.sdnr.SdnrActor diff --git a/models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java b/models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java deleted file mode 100644 index 799872d08..000000000 --- a/models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java +++ /dev/null @@ -1,203 +0,0 @@ -/*- - * SdnrActorServiceProviderTest - * ================================================================================ - * Copyright (C) 2018 Wipro Limited Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 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.sdnr; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.time.Instant; -import java.util.Arrays; -import java.util.HashMap; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.Test; -import org.onap.policy.controlloop.ControlLoopEventStatus; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.ControlLoopResponse; -import org.onap.policy.controlloop.ControlLoopTargetType; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.test.BasicActor; -import org.onap.policy.controlloop.actorserviceprovider.Operator; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.Target; -import org.onap.policy.controlloop.policy.TargetType; -import org.onap.policy.sdnr.PciRequest; -import org.onap.policy.sdnr.PciResponse; -import org.onap.policy.sdnr.PciResponseWrapper; -import org.onap.policy.sdnr.util.Serialization; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SdnrActorServiceProviderTest extends BasicActor { - - private static final String MODIFY_CONFIG = "ModifyConfig"; - - private static final Logger logger = LoggerFactory.getLogger(SdnrActorServiceProviderTest.class); - - private static final VirtualControlLoopEvent onsetEvent; - private static final ControlLoopOperation operation; - private static final Policy policy; - - static { - /* - * Construct an onset. Using dummy AAI details since the code mandates AAI details. - */ - onsetEvent = new VirtualControlLoopEvent(); - onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); - onsetEvent.setRequestId(UUID.randomUUID()); - onsetEvent.setClosedLoopEventClient("tca.instance00001"); - onsetEvent.setTargetType(ControlLoopTargetType.VNF); - onsetEvent.setTarget("generic-vnf.vnf-name"); - onsetEvent.setFrom("DCAE"); - onsetEvent.setClosedLoopAlarmStart(Instant.now()); - onsetEvent.setAai(new HashMap<>()); - onsetEvent.getAai().put("generic-vnf.vnf-name", "notused"); - onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); - onsetEvent.setPayload("some payload"); - - /* Construct an operation with an SDNR actor and ModifyConfig operation. */ - operation = new ControlLoopOperation(); - operation.setActor("SDNR"); - operation.setOperation(MODIFY_CONFIG); - operation.setTarget("VNF"); - operation.setEnd(Instant.now()); - operation.setSubRequestId("1"); - - /* Construct a policy specifying to modify configuration. */ - policy = new Policy(); - policy.setName("Modify PCI Config"); - policy.setDescription("Upon getting the trigger event, modify pci config"); - policy.setActor("SDNR"); - policy.setTarget(new Target(TargetType.VNF)); - policy.getTarget().setResourceID("Eace933104d443b496b8.nodes.heat.vpg"); - policy.setRecipe(MODIFY_CONFIG); - policy.setPayload(null); - policy.setRetry(2); - policy.setTimeout(300); - - } - - @Test - public void testConstructor() { - SdnrActorServiceProvider prov = new SdnrActorServiceProvider(); - assertEquals(0, prov.getSequenceNumber()); - - // verify that it has the operators we expect - var expected = Arrays.asList(SdnrOperation.NAME).stream().sorted().collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - } - - @Test - public void testActorService() { - // verify that it all plugs into the ActorService - verifyActorService(SdnrActorServiceProvider.NAME, "service.yaml"); - } - - @Test - public void testGetOperator() { - SdnrActorServiceProvider sp = new SdnrActorServiceProvider(); - - // should always return the same operator regardless of the name - Operator oper = sp.getOperator("unknown"); - assertNotNull(oper); - assertSame(oper, sp.getOperator("another")); - } - - @Test - public void testGetControlLoopResponse() { - PciRequest sdnrRequest; - sdnrRequest = SdnrActorServiceProvider.constructRequest(onsetEvent, operation, policy).getBody(); - PciResponse sdnrResponse = new PciResponse(sdnrRequest); - sdnrResponse.getStatus().setCode(200); - sdnrResponse.getStatus().setValue("SDNR success"); - sdnrResponse.setPayload("sdnr payload "); - /* Print out request as json to make sure serialization works */ - String jsonResponse = Serialization.gsonPretty.toJson(sdnrResponse); - logger.info(jsonResponse); - PciResponseWrapper pciResponseWrapper = new PciResponseWrapper(); - pciResponseWrapper.setBody(sdnrResponse); - - ControlLoopResponse clRsp = SdnrActorServiceProvider.getControlLoopResponse(pciResponseWrapper, onsetEvent); - assertEquals(clRsp.getClosedLoopControlName(), onsetEvent.getClosedLoopControlName()); - assertEquals(clRsp.getRequestId(), onsetEvent.getRequestId()); - assertEquals(clRsp.getPolicyName(), onsetEvent.getPolicyName()); - assertEquals(clRsp.getPolicyVersion(), onsetEvent.getPolicyVersion()); - assertEquals(clRsp.getVersion(), onsetEvent.getVersion()); - assertEquals("SDNR", clRsp.getFrom()); - assertEquals("DCAE", clRsp.getTarget()); - assertEquals(clRsp.getPayload(), sdnrResponse.getPayload()); - } - - @Test - public void testConstructModifyConfigRequest() { - - PciRequest sdnrRequest; - sdnrRequest = SdnrActorServiceProvider.constructRequest(onsetEvent, operation, policy).getBody(); - - /* The service provider must return a non null SDNR request */ - assertNotNull(sdnrRequest); - - /* A common header is required and cannot be null */ - assertNotNull(sdnrRequest.getCommonHeader()); - assertEquals(sdnrRequest.getCommonHeader().getRequestId(), onsetEvent.getRequestId()); - - /* An action is required and cannot be null */ - assertNotNull(sdnrRequest.getAction()); - assertEquals(MODIFY_CONFIG, sdnrRequest.getAction()); - - /* A payload is required and cannot be null */ - assertNotNull(sdnrRequest.getPayload()); - assertEquals("some payload", sdnrRequest.getPayload()); - - logger.debug("SDNR Request: \n" + sdnrRequest.toString()); - - /* Print out request as json to make sure serialization works */ - String jsonRequest = Serialization.gsonPretty.toJson(sdnrRequest); - 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(MODIFY_CONFIG)); - assertTrue(jsonRequest.contains("payload")); - - PciResponse sdnrResponse = new PciResponse(sdnrRequest); - sdnrResponse.getStatus().setCode(200); - sdnrResponse.getStatus().setValue("SDNR success"); - /* Print out request as json to make sure serialization works */ - String jsonResponse = Serialization.gsonPretty.toJson(sdnrResponse); - logger.debug("JSON Output: \n" + jsonResponse); - } - - @Test - public void testMethods() { - SdnrActorServiceProvider sp = new SdnrActorServiceProvider(); - - assertEquals("SDNR", sp.actor()); - assertEquals(1, sp.recipes().size()); - assertEquals("VNF", sp.recipeTargets(MODIFY_CONFIG).get(0)); - assertEquals(2, sp.recipePayloads(MODIFY_CONFIG).size()); - } -} diff --git a/models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorTest.java b/models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorTest.java new file mode 100644 index 000000000..48c16d05a --- /dev/null +++ b/models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorTest.java @@ -0,0 +1,203 @@ +/*- + * ONAP + * ================================================================================ + * Copyright (C) 2018 Wipro Limited Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019-2020 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.sdnr; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.time.Instant; +import java.util.Arrays; +import java.util.HashMap; +import java.util.UUID; +import java.util.stream.Collectors; +import org.junit.Test; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.ControlLoopResponse; +import org.onap.policy.controlloop.ControlLoopTargetType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.test.BasicActor; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.sdnr.PciRequest; +import org.onap.policy.sdnr.PciResponse; +import org.onap.policy.sdnr.PciResponseWrapper; +import org.onap.policy.sdnr.util.Serialization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SdnrActorTest extends BasicActor { + + private static final String MODIFY_CONFIG = "ModifyConfig"; + + private static final Logger logger = LoggerFactory.getLogger(SdnrActorTest.class); + + private static final VirtualControlLoopEvent onsetEvent; + private static final ControlLoopOperation operation; + private static final Policy policy; + + static { + /* + * Construct an onset. Using dummy AAI details since the code mandates AAI details. + */ + onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); + onsetEvent.setRequestId(UUID.randomUUID()); + onsetEvent.setClosedLoopEventClient("tca.instance00001"); + onsetEvent.setTargetType(ControlLoopTargetType.VNF); + onsetEvent.setTarget("generic-vnf.vnf-name"); + onsetEvent.setFrom("DCAE"); + onsetEvent.setClosedLoopAlarmStart(Instant.now()); + onsetEvent.setAai(new HashMap<>()); + onsetEvent.getAai().put("generic-vnf.vnf-name", "notused"); + onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); + onsetEvent.setPayload("some payload"); + + /* Construct an operation with an SDNR actor and ModifyConfig operation. */ + operation = new ControlLoopOperation(); + operation.setActor("SDNR"); + operation.setOperation(MODIFY_CONFIG); + operation.setTarget("VNF"); + operation.setEnd(Instant.now()); + operation.setSubRequestId("1"); + + /* Construct a policy specifying to modify configuration. */ + policy = new Policy(); + policy.setName("Modify PCI Config"); + policy.setDescription("Upon getting the trigger event, modify pci config"); + policy.setActor("SDNR"); + policy.setTarget(new Target(TargetType.VNF)); + policy.getTarget().setResourceID("Eace933104d443b496b8.nodes.heat.vpg"); + policy.setRecipe(MODIFY_CONFIG); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + + } + + @Test + public void testConstructor() { + SdnrActor prov = new SdnrActor(); + assertEquals(0, prov.getSequenceNumber()); + + // verify that it has the operators we expect + var expected = Arrays.asList(SdnrOperation.NAME).stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(SdnrActor.NAME, "service.yaml"); + } + + @Test + public void testGetOperator() { + SdnrActor sp = new SdnrActor(); + + // should always return the same operator regardless of the name + Operator oper = sp.getOperator("unknown"); + assertNotNull(oper); + assertSame(oper, sp.getOperator("another")); + } + + @Test + public void testGetControlLoopResponse() { + PciRequest sdnrRequest; + sdnrRequest = SdnrActor.constructRequest(onsetEvent, operation, policy).getBody(); + PciResponse sdnrResponse = new PciResponse(sdnrRequest); + sdnrResponse.getStatus().setCode(200); + sdnrResponse.getStatus().setValue("SDNR success"); + sdnrResponse.setPayload("sdnr payload "); + /* Print out request as json to make sure serialization works */ + String jsonResponse = Serialization.gsonPretty.toJson(sdnrResponse); + logger.info(jsonResponse); + PciResponseWrapper pciResponseWrapper = new PciResponseWrapper(); + pciResponseWrapper.setBody(sdnrResponse); + + ControlLoopResponse clRsp = SdnrActor.getControlLoopResponse(pciResponseWrapper, onsetEvent); + assertEquals(clRsp.getClosedLoopControlName(), onsetEvent.getClosedLoopControlName()); + assertEquals(clRsp.getRequestId(), onsetEvent.getRequestId()); + assertEquals(clRsp.getPolicyName(), onsetEvent.getPolicyName()); + assertEquals(clRsp.getPolicyVersion(), onsetEvent.getPolicyVersion()); + assertEquals(clRsp.getVersion(), onsetEvent.getVersion()); + assertEquals("SDNR", clRsp.getFrom()); + assertEquals("DCAE", clRsp.getTarget()); + assertEquals(clRsp.getPayload(), sdnrResponse.getPayload()); + } + + @Test + public void testConstructModifyConfigRequest() { + + PciRequest sdnrRequest; + sdnrRequest = SdnrActor.constructRequest(onsetEvent, operation, policy).getBody(); + + /* The service provider must return a non null SDNR request */ + assertNotNull(sdnrRequest); + + /* A common header is required and cannot be null */ + assertNotNull(sdnrRequest.getCommonHeader()); + assertEquals(sdnrRequest.getCommonHeader().getRequestId(), onsetEvent.getRequestId()); + + /* An action is required and cannot be null */ + assertNotNull(sdnrRequest.getAction()); + assertEquals(MODIFY_CONFIG, sdnrRequest.getAction()); + + /* A payload is required and cannot be null */ + assertNotNull(sdnrRequest.getPayload()); + assertEquals("some payload", sdnrRequest.getPayload()); + + logger.debug("SDNR Request: \n" + sdnrRequest.toString()); + + /* Print out request as json to make sure serialization works */ + String jsonRequest = Serialization.gsonPretty.toJson(sdnrRequest); + 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(MODIFY_CONFIG)); + assertTrue(jsonRequest.contains("payload")); + + PciResponse sdnrResponse = new PciResponse(sdnrRequest); + sdnrResponse.getStatus().setCode(200); + sdnrResponse.getStatus().setValue("SDNR success"); + /* Print out request as json to make sure serialization works */ + String jsonResponse = Serialization.gsonPretty.toJson(sdnrResponse); + logger.debug("JSON Output: \n" + jsonResponse); + } + + @Test + public void testMethods() { + SdnrActor sp = new SdnrActor(); + + assertEquals("SDNR", sp.actor()); + assertEquals(1, sp.recipes().size()); + assertEquals("VNF", sp.recipeTargets(MODIFY_CONFIG).get(0)); + assertEquals(2, sp.recipePayloads(MODIFY_CONFIG).size()); + } +} diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActor.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActor.java new file mode 100644 index 000000000..2b2fddec5 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActor.java @@ -0,0 +1,462 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.so; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.Tenant; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpPollingOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.so.SoCloudConfiguration; +import org.onap.policy.so.SoManager; +import org.onap.policy.so.SoModelInfo; +import org.onap.policy.so.SoOperationType; +import org.onap.policy.so.SoRelatedInstance; +import org.onap.policy.so.SoRelatedInstanceListElement; +import org.onap.policy.so.SoRequest; +import org.onap.policy.so.SoRequestDetails; +import org.onap.policy.so.SoRequestInfo; +import org.onap.policy.so.SoRequestParameters; +import org.onap.policy.so.util.Serialization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SoActor extends HttpActor { + private static final Logger logger = LoggerFactory.getLogger(SoActor.class); + + public static final String NAME = "SO"; + + // TODO old code: remove lines down to **HERE** + + private static final String TENANT_NOT_FOUND = "Tenant Item not found in AAI response {}"; + private static final String CONSTRUCTED_SO_MSG = "Constructed SO request: {}"; + + // Strings for targets + private static final String TARGET_VFC = "VFC"; + + // Strings for recipes + private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create"; + private static final String RECIPE_VF_MODULE_DELETE = "VF Module Delete"; + + private static final ImmutableList recipes = + ImmutableList.of(RECIPE_VF_MODULE_CREATE, RECIPE_VF_MODULE_DELETE); + private static final ImmutableMap> targets = + new ImmutableMap.Builder>().put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC)) + .put(RECIPE_VF_MODULE_DELETE, ImmutableList.of(TARGET_VFC)).build(); + + // name of request parameters within policy payload + public static final String REQ_PARAM_NM = "requestParameters"; + + // name of configuration parameters within policy payload + public static final String CONFIG_PARAM_NM = "configurationParameters"; + + // used to decode configuration parameters via gson + private static final Type CONFIG_TYPE = new TypeToken>>() {}.getType(); + + // Static variables required to hold the IDs of the last service item, VNF item and VF Module. + // Note that in + // a multithreaded deployment this WILL break + private static String lastVNFItemVnfId; + private static String lastServiceItemServiceInstanceId; + private static String lastVfModuleItemVfModuleInstanceId; + + // **HERE** + + /** + * Constructs the object. + */ + public SoActor() { + super(NAME, HttpPollingActorParams.class); + + addOperator(new HttpPollingOperator(NAME, VfModuleCreate.NAME, VfModuleCreate::new)); + addOperator(new HttpPollingOperator(NAME, VfModuleDelete.NAME, VfModuleDelete::new)); + } + + // TODO old code: remove lines down to **HERE** + + @Override + public String actor() { + return NAME; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + return Collections.emptyList(); + } + + private SoModelInfo prepareSoModelInfo(Policy policy) { + + if (policy.getTarget() == null || policy.getTarget().getModelCustomizationId() == null + || policy.getTarget().getModelInvariantId() == null) { + return null; + } + + if (policy.getTarget().getModelName() == null || policy.getTarget().getModelVersion() == null + || policy.getTarget().getModelVersionId() == null) { + return null; + } + + SoModelInfo soModelInfo = new SoModelInfo(); + soModelInfo.setModelCustomizationId(policy.getTarget().getModelCustomizationId()); + soModelInfo.setModelInvariantId(policy.getTarget().getModelInvariantId()); + soModelInfo.setModelName(policy.getTarget().getModelName()); + soModelInfo.setModelVersion(policy.getTarget().getModelVersion()); + soModelInfo.setModelVersionId(policy.getTarget().getModelVersionId()); + soModelInfo.setModelType("vfModule"); + return soModelInfo; + } + + /** + * Construct requestInfo for the SO requestDetails. + * + * @return SO request information + */ + private SoRequestInfo constructRequestInfo() { + SoRequestInfo soRequestInfo = new SoRequestInfo(); + soRequestInfo.setSource("POLICY"); + soRequestInfo.setSuppressRollback(false); + soRequestInfo.setRequestorId("policy"); + return soRequestInfo; + } + + /** + * This method is needed to get the serviceInstanceId and vnfInstanceId which is used in the asyncSORestCall. + * + * @param requestId the request Id + * @param callback callback method + * @param request the request + * @param url SO REST URL + * @param user username + * @param password password + */ + public static void sendRequest(String requestId, SoManager.SoCallback callback, Object request, String url, + String user, String password) { + SoManager soManager = new SoManager(url, user, password); + soManager.asyncSoRestCall(requestId, callback, lastServiceItemServiceInstanceId, lastVNFItemVnfId, + lastVfModuleItemVfModuleInstanceId, (SoRequest) request); + } + + + /** + * Builds the request parameters from the policy payload. + * + * @param policy the policy + * @param request request into which to stick the request parameters + */ + private void buildRequestParameters(Policy policy, SoRequestDetails request) { + // assume null until proven otherwise + request.setRequestParameters(null); + + if (policy.getPayload() == null) { + return; + } + + String json = policy.getPayload().get(REQ_PARAM_NM); + if (json == null) { + return; + } + + request.setRequestParameters(Serialization.gsonPretty.fromJson(json, SoRequestParameters.class)); + } + + /** + * Builds the configuration parameters from the policy payload. + * + * @param policy the policy + * @param request request into which to stick the configuration parameters + */ + private void buildConfigurationParameters(Policy policy, SoRequestDetails request) { + // assume null until proven otherwise + request.setConfigurationParameters(null); + + if (policy.getPayload() == null) { + return; + } + + String json = policy.getPayload().get(CONFIG_PARAM_NM); + if (json == null) { + return; + } + + request.setConfigurationParameters(Serialization.gsonPretty.fromJson(json, CONFIG_TYPE)); + } + + /** + * This method is called to remember the last service instance ID, VNF Item VNF ID and vf module ID. Note these + * fields are static, beware for multithreaded deployments + * + * @param vnfInstanceId update the last VNF instance ID to this value + * @param serviceInstanceId update the last service instance ID to this value + * @param vfModuleId update the vfModule instance ID to this value + */ + private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId, + final String vfModuleId) { + lastVNFItemVnfId = vnfInstanceId; + lastServiceItemServiceInstanceId = serviceInstanceId; + lastVfModuleItemVfModuleInstanceId = vfModuleId; + } + + /** + * Constructs a SO 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 + * @param aaiCqResponse response from A&AI custom query + * @return a SO request conforming to the lcm API using the DMAAP wrapper + */ + public SoRequest constructRequestCq(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy, + AaiCqResponse aaiCqResponse) { + if (!NAME.equals(policy.getActor()) || !recipes().contains(policy.getRecipe())) { + return null; + } + + // A&AI named query should have been performed by now. If not, return null + if (aaiCqResponse == null) { + return null; + } + + SoModelInfo soModelInfo = prepareSoModelInfo(policy); + + // Report the error vf module is not found + if (soModelInfo == null) { + logger.error("vf module is not found."); + return null; + } + + GenericVnf vnfItem; + ServiceInstance vnfServiceItem; + Tenant tenantItem; + CloudRegion cloudRegionItem; + + // Extract the items we're interested in from the response + try { + vnfItem = aaiCqResponse.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId()); + //Report VNF not found + if (vnfItem == null) { + logger.error("Generic Vnf is not found."); + return null; + } + } catch (Exception e) { + logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiCqResponse), e); + return null; + } + + try { + vnfServiceItem = aaiCqResponse.getServiceInstance(); + } catch (Exception e) { + logger.error("VNF Service Item not found in AAI response {}", + Serialization.gsonPretty.toJson(aaiCqResponse), e); + return null; + } + + try { + tenantItem = aaiCqResponse.getDefaultTenant(); + } catch (Exception e) { + logger.error(TENANT_NOT_FOUND, Serialization.gsonPretty.toJson(aaiCqResponse), e); + return null; + } + + try { + cloudRegionItem = aaiCqResponse.getDefaultCloudRegion(); + } catch (Exception e) { + logger.error(TENANT_NOT_FOUND, Serialization.gsonPretty.toJson(aaiCqResponse), e); + return null; + } + + + + // Construct SO Request for a policy's recipe + if (RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) { + return constructCreateRequestCq(aaiCqResponse, policy, tenantItem, vnfItem, vnfServiceItem, soModelInfo, + cloudRegionItem); + } else if (RECIPE_VF_MODULE_DELETE.equals(policy.getRecipe())) { + return constructDeleteRequestCq(tenantItem, vnfItem, vnfServiceItem, policy, cloudRegionItem); + } else { + return null; + } + } + + /** + * Construct the So request, based on Custom Query response from A&AI. + * + * @param aaiCqResponse Custom query response from A&AI + * @param policy policy information + * @param tenantItem Tenant from CQ response + * @param vnfItem Generic VNF from CQ response + * @param vnfServiceItem Service Instance from CQ response + * @param vfModuleItem VF Module from CustomQuery response + * @param cloudRegionItem Cloud Region from Custom query response + * @return SoRequest well formed So Request + */ + private SoRequest constructCreateRequestCq(AaiCqResponse aaiCqResponse, Policy policy, Tenant tenantItem, + GenericVnf vnfItem, ServiceInstance vnfServiceItem, SoModelInfo vfModuleItem, CloudRegion cloudRegionItem) { + SoRequest request = new SoRequest(); + request.setOperationType(SoOperationType.SCALE_OUT); + // + // + // Do NOT send So the requestId, they do not support this field + // + request.setRequestDetails(new SoRequestDetails()); + request.getRequestDetails().setRequestParameters(new SoRequestParameters()); + request.getRequestDetails().getRequestParameters().setUserParams(null); + + // cloudConfiguration + request.getRequestDetails().setCloudConfiguration(constructCloudConfigurationCq(tenantItem, cloudRegionItem)); + // modelInfo + request.getRequestDetails().setModelInfo(vfModuleItem); + + + // requestInfo + request.getRequestDetails().setRequestInfo(constructRequestInfo()); + request.getRequestDetails().getRequestInfo().setInstanceName("vfModuleName"); + + // relatedInstanceList + SoRelatedInstanceListElement relatedInstanceListElement1 = new SoRelatedInstanceListElement(); + SoRelatedInstanceListElement relatedInstanceListElement2 = new SoRelatedInstanceListElement(); + relatedInstanceListElement1.setRelatedInstance(new SoRelatedInstance()); + relatedInstanceListElement2.setRelatedInstance(new SoRelatedInstance()); + + // Service Item + relatedInstanceListElement1.getRelatedInstance().setInstanceId(vnfServiceItem.getServiceInstanceId()); + relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SoModelInfo()); + relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service"); + relatedInstanceListElement1.getRelatedInstance().getModelInfo() + .setModelInvariantId(vnfServiceItem.getModelInvariantId()); + relatedInstanceListElement1.getRelatedInstance().getModelInfo() + .setModelVersionId(vnfServiceItem.getModelVersionId()); + relatedInstanceListElement1.getRelatedInstance().getModelInfo() + .setModelName(aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelName()); + relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion( + aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelVersion()); + + + // VNF Item + relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getVnfId()); + relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SoModelInfo()); + relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf"); + relatedInstanceListElement2.getRelatedInstance().getModelInfo() + .setModelInvariantId(vnfItem.getModelInvariantId()); + relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getModelVersionId()); + + relatedInstanceListElement2.getRelatedInstance().getModelInfo() + .setModelName(aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelName()); + relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion( + aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelVersion()); + + + relatedInstanceListElement2.getRelatedInstance().getModelInfo() + .setModelCustomizationId(vnfItem.getModelCustomizationId()); + + + // Insert the Service Item and VNF Item + request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1); + request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2); + + // Request Parameters + buildRequestParameters(policy, request.getRequestDetails()); + + // Configuration Parameters + buildConfigurationParameters(policy, request.getRequestDetails()); + // Save the instance IDs for the VNF and service to static fields + // vfModuleId is not required for the create vf-module + preserveInstanceIds(vnfItem.getVnfId(), vnfServiceItem.getServiceInstanceId(), null); + if (logger.isDebugEnabled()) { + logger.debug(CONSTRUCTED_SO_MSG, Serialization.gsonPretty.toJson(request)); + } + return request; + } + + /** + * constructs delete request for So. + * + * @param tenantItem Tenant from A&AI CQ request + * @param vnfItem Generic VNF from A&AI CQ request + * @param vnfServiceItem ServiceInstance from A&AI CQ request + * @param policy policy information + * @param cloudRegionItem CloudRegion from A&AI CQ request + * @return SoRequest deleted + */ + private SoRequest constructDeleteRequestCq(Tenant tenantItem, GenericVnf vnfItem, ServiceInstance vnfServiceItem, + Policy policy, CloudRegion cloudRegionItem) { + SoRequest request = new SoRequest(); + request.setOperationType(SoOperationType.DELETE_VF_MODULE); + request.setRequestDetails(new SoRequestDetails()); + request.getRequestDetails().setRelatedInstanceList(null); + request.getRequestDetails().setConfigurationParameters(null); + + // cloudConfiguration + request.getRequestDetails().setCloudConfiguration(constructCloudConfigurationCq(tenantItem, cloudRegionItem)); + // modelInfo + request.getRequestDetails().setModelInfo(prepareSoModelInfo(policy)); + // requestInfo + request.getRequestDetails().setRequestInfo(constructRequestInfo()); + // Save the instance IDs for the VNF, service and vfModule to static fields + preserveInstanceIds(vnfItem.getVnfId(), vnfServiceItem.getServiceInstanceId(), null); + + if (logger.isDebugEnabled()) { + logger.debug(CONSTRUCTED_SO_MSG, Serialization.gsonPretty.toJson(request)); + } + return request; + } + + + /** + * Construct cloudConfiguration for the SO requestDetails. Overridden for custom query. + * + * @param tenantItem tenant item from A&AI named-query response + * @return SO cloud configuration + */ + private SoCloudConfiguration constructCloudConfigurationCq(Tenant tenantItem, CloudRegion cloudRegionItem) { + SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration(); + cloudConfiguration.setTenantId(tenantItem.getTenantId()); + cloudConfiguration.setLcpCloudRegionId(cloudRegionItem.getCloudRegionId()); + return cloudConfiguration; + } + + // **HERE** + +} diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java deleted file mode 100644 index 642e2b455..000000000 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java +++ /dev/null @@ -1,462 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * SOActorServiceProvider - * ================================================================================ - * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.so; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.gson.reflect.TypeToken; -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.onap.aai.domain.yang.CloudRegion; -import org.onap.aai.domain.yang.GenericVnf; -import org.onap.aai.domain.yang.ServiceInstance; -import org.onap.aai.domain.yang.Tenant; -import org.onap.policy.aai.AaiCqResponse; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpPollingOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingActorParams; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.so.SoCloudConfiguration; -import org.onap.policy.so.SoManager; -import org.onap.policy.so.SoModelInfo; -import org.onap.policy.so.SoOperationType; -import org.onap.policy.so.SoRelatedInstance; -import org.onap.policy.so.SoRelatedInstanceListElement; -import org.onap.policy.so.SoRequest; -import org.onap.policy.so.SoRequestDetails; -import org.onap.policy.so.SoRequestInfo; -import org.onap.policy.so.SoRequestParameters; -import org.onap.policy.so.util.Serialization; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SoActorServiceProvider extends HttpActor { - private static final Logger logger = LoggerFactory.getLogger(SoActorServiceProvider.class); - - public static final String NAME = "SO"; - - // TODO old code: remove lines down to **HERE** - - private static final String TENANT_NOT_FOUND = "Tenant Item not found in AAI response {}"; - private static final String CONSTRUCTED_SO_MSG = "Constructed SO request: {}"; - - // Strings for targets - private static final String TARGET_VFC = "VFC"; - - // Strings for recipes - private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create"; - private static final String RECIPE_VF_MODULE_DELETE = "VF Module Delete"; - - private static final ImmutableList recipes = - ImmutableList.of(RECIPE_VF_MODULE_CREATE, RECIPE_VF_MODULE_DELETE); - private static final ImmutableMap> targets = - new ImmutableMap.Builder>().put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC)) - .put(RECIPE_VF_MODULE_DELETE, ImmutableList.of(TARGET_VFC)).build(); - - // name of request parameters within policy payload - public static final String REQ_PARAM_NM = "requestParameters"; - - // name of configuration parameters within policy payload - public static final String CONFIG_PARAM_NM = "configurationParameters"; - - // used to decode configuration parameters via gson - private static final Type CONFIG_TYPE = new TypeToken>>() {}.getType(); - - // Static variables required to hold the IDs of the last service item, VNF item and VF Module. - // Note that in - // a multithreaded deployment this WILL break - private static String lastVNFItemVnfId; - private static String lastServiceItemServiceInstanceId; - private static String lastVfModuleItemVfModuleInstanceId; - - // **HERE** - - /** - * Constructs the object. - */ - public SoActorServiceProvider() { - super(NAME, HttpPollingActorParams.class); - - addOperator(new HttpPollingOperator(NAME, VfModuleCreate.NAME, VfModuleCreate::new)); - addOperator(new HttpPollingOperator(NAME, VfModuleDelete.NAME, VfModuleDelete::new)); - } - - // TODO old code: remove lines down to **HERE** - - @Override - public String actor() { - return NAME; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - return Collections.emptyList(); - } - - private SoModelInfo prepareSoModelInfo(Policy policy) { - - if (policy.getTarget() == null || policy.getTarget().getModelCustomizationId() == null - || policy.getTarget().getModelInvariantId() == null) { - return null; - } - - if (policy.getTarget().getModelName() == null || policy.getTarget().getModelVersion() == null - || policy.getTarget().getModelVersionId() == null) { - return null; - } - - SoModelInfo soModelInfo = new SoModelInfo(); - soModelInfo.setModelCustomizationId(policy.getTarget().getModelCustomizationId()); - soModelInfo.setModelInvariantId(policy.getTarget().getModelInvariantId()); - soModelInfo.setModelName(policy.getTarget().getModelName()); - soModelInfo.setModelVersion(policy.getTarget().getModelVersion()); - soModelInfo.setModelVersionId(policy.getTarget().getModelVersionId()); - soModelInfo.setModelType("vfModule"); - return soModelInfo; - } - - /** - * Construct requestInfo for the SO requestDetails. - * - * @return SO request information - */ - private SoRequestInfo constructRequestInfo() { - SoRequestInfo soRequestInfo = new SoRequestInfo(); - soRequestInfo.setSource("POLICY"); - soRequestInfo.setSuppressRollback(false); - soRequestInfo.setRequestorId("policy"); - return soRequestInfo; - } - - /** - * This method is needed to get the serviceInstanceId and vnfInstanceId which is used in the asyncSORestCall. - * - * @param requestId the request Id - * @param callback callback method - * @param request the request - * @param url SO REST URL - * @param user username - * @param password password - */ - public static void sendRequest(String requestId, SoManager.SoCallback callback, Object request, String url, - String user, String password) { - SoManager soManager = new SoManager(url, user, password); - soManager.asyncSoRestCall(requestId, callback, lastServiceItemServiceInstanceId, lastVNFItemVnfId, - lastVfModuleItemVfModuleInstanceId, (SoRequest) request); - } - - - /** - * Builds the request parameters from the policy payload. - * - * @param policy the policy - * @param request request into which to stick the request parameters - */ - private void buildRequestParameters(Policy policy, SoRequestDetails request) { - // assume null until proven otherwise - request.setRequestParameters(null); - - if (policy.getPayload() == null) { - return; - } - - String json = policy.getPayload().get(REQ_PARAM_NM); - if (json == null) { - return; - } - - request.setRequestParameters(Serialization.gsonPretty.fromJson(json, SoRequestParameters.class)); - } - - /** - * Builds the configuration parameters from the policy payload. - * - * @param policy the policy - * @param request request into which to stick the configuration parameters - */ - private void buildConfigurationParameters(Policy policy, SoRequestDetails request) { - // assume null until proven otherwise - request.setConfigurationParameters(null); - - if (policy.getPayload() == null) { - return; - } - - String json = policy.getPayload().get(CONFIG_PARAM_NM); - if (json == null) { - return; - } - - request.setConfigurationParameters(Serialization.gsonPretty.fromJson(json, CONFIG_TYPE)); - } - - /** - * This method is called to remember the last service instance ID, VNF Item VNF ID and vf module ID. Note these - * fields are static, beware for multithreaded deployments - * - * @param vnfInstanceId update the last VNF instance ID to this value - * @param serviceInstanceId update the last service instance ID to this value - * @param vfModuleId update the vfModule instance ID to this value - */ - private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId, - final String vfModuleId) { - lastVNFItemVnfId = vnfInstanceId; - lastServiceItemServiceInstanceId = serviceInstanceId; - lastVfModuleItemVfModuleInstanceId = vfModuleId; - } - - /** - * Constructs a SO 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 - * @param aaiCqResponse response from A&AI custom query - * @return a SO request conforming to the lcm API using the DMAAP wrapper - */ - public SoRequest constructRequestCq(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy, - AaiCqResponse aaiCqResponse) { - if (!NAME.equals(policy.getActor()) || !recipes().contains(policy.getRecipe())) { - return null; - } - - // A&AI named query should have been performed by now. If not, return null - if (aaiCqResponse == null) { - return null; - } - - SoModelInfo soModelInfo = prepareSoModelInfo(policy); - - // Report the error vf module is not found - if (soModelInfo == null) { - logger.error("vf module is not found."); - return null; - } - - GenericVnf vnfItem; - ServiceInstance vnfServiceItem; - Tenant tenantItem; - CloudRegion cloudRegionItem; - - // Extract the items we're interested in from the response - try { - vnfItem = aaiCqResponse.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId()); - //Report VNF not found - if (vnfItem == null) { - logger.error("Generic Vnf is not found."); - return null; - } - } catch (Exception e) { - logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiCqResponse), e); - return null; - } - - try { - vnfServiceItem = aaiCqResponse.getServiceInstance(); - } catch (Exception e) { - logger.error("VNF Service Item not found in AAI response {}", - Serialization.gsonPretty.toJson(aaiCqResponse), e); - return null; - } - - try { - tenantItem = aaiCqResponse.getDefaultTenant(); - } catch (Exception e) { - logger.error(TENANT_NOT_FOUND, Serialization.gsonPretty.toJson(aaiCqResponse), e); - return null; - } - - try { - cloudRegionItem = aaiCqResponse.getDefaultCloudRegion(); - } catch (Exception e) { - logger.error(TENANT_NOT_FOUND, Serialization.gsonPretty.toJson(aaiCqResponse), e); - return null; - } - - - - // Construct SO Request for a policy's recipe - if (RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) { - return constructCreateRequestCq(aaiCqResponse, policy, tenantItem, vnfItem, vnfServiceItem, soModelInfo, - cloudRegionItem); - } else if (RECIPE_VF_MODULE_DELETE.equals(policy.getRecipe())) { - return constructDeleteRequestCq(tenantItem, vnfItem, vnfServiceItem, policy, cloudRegionItem); - } else { - return null; - } - } - - /** - * Construct the So request, based on Custom Query response from A&AI. - * - * @param aaiCqResponse Custom query response from A&AI - * @param policy policy information - * @param tenantItem Tenant from CQ response - * @param vnfItem Generic VNF from CQ response - * @param vnfServiceItem Service Instance from CQ response - * @param vfModuleItem VF Module from CustomQuery response - * @param cloudRegionItem Cloud Region from Custom query response - * @return SoRequest well formed So Request - */ - private SoRequest constructCreateRequestCq(AaiCqResponse aaiCqResponse, Policy policy, Tenant tenantItem, - GenericVnf vnfItem, ServiceInstance vnfServiceItem, SoModelInfo vfModuleItem, CloudRegion cloudRegionItem) { - SoRequest request = new SoRequest(); - request.setOperationType(SoOperationType.SCALE_OUT); - // - // - // Do NOT send So the requestId, they do not support this field - // - request.setRequestDetails(new SoRequestDetails()); - request.getRequestDetails().setRequestParameters(new SoRequestParameters()); - request.getRequestDetails().getRequestParameters().setUserParams(null); - - // cloudConfiguration - request.getRequestDetails().setCloudConfiguration(constructCloudConfigurationCq(tenantItem, cloudRegionItem)); - // modelInfo - request.getRequestDetails().setModelInfo(vfModuleItem); - - - // requestInfo - request.getRequestDetails().setRequestInfo(constructRequestInfo()); - request.getRequestDetails().getRequestInfo().setInstanceName("vfModuleName"); - - // relatedInstanceList - SoRelatedInstanceListElement relatedInstanceListElement1 = new SoRelatedInstanceListElement(); - SoRelatedInstanceListElement relatedInstanceListElement2 = new SoRelatedInstanceListElement(); - relatedInstanceListElement1.setRelatedInstance(new SoRelatedInstance()); - relatedInstanceListElement2.setRelatedInstance(new SoRelatedInstance()); - - // Service Item - relatedInstanceListElement1.getRelatedInstance().setInstanceId(vnfServiceItem.getServiceInstanceId()); - relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SoModelInfo()); - relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service"); - relatedInstanceListElement1.getRelatedInstance().getModelInfo() - .setModelInvariantId(vnfServiceItem.getModelInvariantId()); - relatedInstanceListElement1.getRelatedInstance().getModelInfo() - .setModelVersionId(vnfServiceItem.getModelVersionId()); - relatedInstanceListElement1.getRelatedInstance().getModelInfo() - .setModelName(aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelName()); - relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion( - aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelVersion()); - - - // VNF Item - relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getVnfId()); - relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SoModelInfo()); - relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf"); - relatedInstanceListElement2.getRelatedInstance().getModelInfo() - .setModelInvariantId(vnfItem.getModelInvariantId()); - relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getModelVersionId()); - - relatedInstanceListElement2.getRelatedInstance().getModelInfo() - .setModelName(aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelName()); - relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion( - aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelVersion()); - - - relatedInstanceListElement2.getRelatedInstance().getModelInfo() - .setModelCustomizationId(vnfItem.getModelCustomizationId()); - - - // Insert the Service Item and VNF Item - request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1); - request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2); - - // Request Parameters - buildRequestParameters(policy, request.getRequestDetails()); - - // Configuration Parameters - buildConfigurationParameters(policy, request.getRequestDetails()); - // Save the instance IDs for the VNF and service to static fields - // vfModuleId is not required for the create vf-module - preserveInstanceIds(vnfItem.getVnfId(), vnfServiceItem.getServiceInstanceId(), null); - if (logger.isDebugEnabled()) { - logger.debug(CONSTRUCTED_SO_MSG, Serialization.gsonPretty.toJson(request)); - } - return request; - } - - /** - * constructs delete request for So. - * - * @param tenantItem Tenant from A&AI CQ request - * @param vnfItem Generic VNF from A&AI CQ request - * @param vnfServiceItem ServiceInstance from A&AI CQ request - * @param policy policy information - * @param cloudRegionItem CloudRegion from A&AI CQ request - * @return SoRequest deleted - */ - private SoRequest constructDeleteRequestCq(Tenant tenantItem, GenericVnf vnfItem, ServiceInstance vnfServiceItem, - Policy policy, CloudRegion cloudRegionItem) { - SoRequest request = new SoRequest(); - request.setOperationType(SoOperationType.DELETE_VF_MODULE); - request.setRequestDetails(new SoRequestDetails()); - request.getRequestDetails().setRelatedInstanceList(null); - request.getRequestDetails().setConfigurationParameters(null); - - // cloudConfiguration - request.getRequestDetails().setCloudConfiguration(constructCloudConfigurationCq(tenantItem, cloudRegionItem)); - // modelInfo - request.getRequestDetails().setModelInfo(prepareSoModelInfo(policy)); - // requestInfo - request.getRequestDetails().setRequestInfo(constructRequestInfo()); - // Save the instance IDs for the VNF, service and vfModule to static fields - preserveInstanceIds(vnfItem.getVnfId(), vnfServiceItem.getServiceInstanceId(), null); - - if (logger.isDebugEnabled()) { - logger.debug(CONSTRUCTED_SO_MSG, Serialization.gsonPretty.toJson(request)); - } - return request; - } - - - /** - * Construct cloudConfiguration for the SO requestDetails. Overridden for custom query. - * - * @param tenantItem tenant item from A&AI named-query response - * @return SO cloud configuration - */ - private SoCloudConfiguration constructCloudConfigurationCq(Tenant tenantItem, CloudRegion cloudRegionItem) { - SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration(); - cloudConfiguration.setTenantId(tenantItem.getTenantId()); - cloudConfiguration.setLcpCloudRegionId(cloudRegionItem.getCloudRegionId()); - return cloudConfiguration; - } - - // **HERE** - -} diff --git a/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index a955eb71c..365c8f980 100644 --- a/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.so.SoActorServiceProvider \ No newline at end of file +org.onap.policy.controlloop.actor.so.SoActor diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java deleted file mode 100644 index cdd8a334c..000000000 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * TestSOActorServiceProvider - * ================================================================================ - * Copyright (C) 2018 Ericsson. All rights reserved. - * ================================================================================ - * Modifications Copyright (C) 2018-2019 AT&T. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.so; - -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.UUID; -import java.util.stream.Collectors; -import org.apache.commons.io.IOUtils; -import org.junit.Test; -import org.onap.policy.aai.AaiCqResponse; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.test.BasicActor; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.Target; -import org.onap.policy.so.SoOperationType; -import org.onap.policy.so.SoRequest; -import org.onap.policy.so.SoRequestParameters; -import org.onap.policy.so.util.Serialization; - -public class SoActorServiceProviderTest extends BasicActor { - - private static final String C_VALUE = "cvalue"; - private static final String A_VALUE = "avalue"; - private static final String VF_MODULE_CREATE = "VF Module Create"; - private static final String VF_MODULE_DELETE = "VF Module Delete"; - - private void instantiateTargetCq(Policy policy) { - - Target target = new Target(); - target.setModelCustomizationId("47958575-138f-452a-8c8d-d89b595f8164"); - target.setModelInvariantId("e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e"); - target.setModelName("VfwclVfwsnkBbefb8ce2bde..base_vfw..module-0"); - target.setModelVersion("1"); - target.setModelVersionId("94b18b1d-cc91-4f43-911a-e6348665f292"); - - policy.setTarget(target); - } - - @Test - public void testConstructor() { - SoActorServiceProvider prov = new SoActorServiceProvider(); - - // verify that it has the operators we expect - var expected = Arrays.asList(VfModuleCreate.NAME, VfModuleDelete.NAME).stream().sorted() - .collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - } - - @Test - public void testActorService() { - // verify that it all plugs into the ActorService - verifyActorService(SoActorServiceProvider.NAME, "service.yaml"); - } - - @Test - public void testSendRequest() { - assertThatCode(() -> SoActorServiceProvider.sendRequest(UUID.randomUUID().toString(), null, null, null, null, - null)).doesNotThrowAnyException(); - } - - @Test - public void testMethods() { - SoActorServiceProvider sp = new SoActorServiceProvider(); - - assertEquals("SO", sp.actor()); - assertEquals(2, sp.recipes().size()); - assertEquals(VF_MODULE_CREATE, sp.recipes().get(0)); - assertEquals(VF_MODULE_DELETE, sp.recipes().get(1)); - assertEquals(0, sp.recipePayloads(VF_MODULE_CREATE).size()); - assertEquals(0, sp.recipeTargets("unknown recipe").size()); - assertEquals(1, sp.recipeTargets(VF_MODULE_CREATE).size()); - } - - @Test - public void testConstructRequestCq() throws Exception { - VirtualControlLoopEvent onset = new VirtualControlLoopEvent(); - final ControlLoopOperation operation = new ControlLoopOperation(); - final AaiCqResponse aaiCqResp = loadAaiResponseCq("aai/AaiCqResponseFull.json"); - final AaiCqResponse aaiCqRespMissing = loadAaiResponseCq("aai/AaiCqResponseMissing.json"); - final UUID requestId = UUID.randomUUID(); - onset.setRequestId(requestId); - - Policy policy = new Policy(); - policy.setActor("Dorothy"); - policy.setRecipe("GoToOz"); - - instantiateTargetCq(policy); - - assertNull(new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqResp)); - - policy.setActor("SO"); - - assertNull(new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqRespMissing)); - - policy.setRecipe(VF_MODULE_CREATE); - - // empty policy payload - SoRequest request = new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqResp); - assertNotNull(request); - - assertEquals("vfModuleName", request.getRequestDetails().getRequestInfo().getInstanceName()); - assertEquals("policy", request.getRequestDetails().getRequestInfo().getRequestorId()); - assertEquals("RegionOne", request.getRequestDetails().getCloudConfiguration().getLcpCloudRegionId()); - - // non-empty policy payload - policy.setPayload(makePayload()); - request = new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqResp); - assertNotNull(request); - assertEquals(true, request.getRequestDetails().getRequestParameters().isUsePreload()); - assertEquals(A_VALUE, request.getRequestDetails().getRequestParameters().getUserParams().get(0).get("akey")); - assertEquals(1, request.getRequestDetails().getConfigurationParameters().size()); - assertEquals(C_VALUE, request.getRequestDetails().getConfigurationParameters().get(0).get("ckey")); - - // payload with config, but no request params - policy.setPayload(makePayload()); - policy.getPayload().remove(SoActorServiceProvider.REQ_PARAM_NM); - request = new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqResp); - assertNotNull(request); - assertNull(request.getRequestDetails().getRequestParameters()); - assertNotNull(request.getRequestDetails().getConfigurationParameters()); - - // payload with request, but no config params - policy.setPayload(makePayload()); - policy.getPayload().remove(SoActorServiceProvider.CONFIG_PARAM_NM); - request = new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqResp); - assertNotNull(request); - assertNotNull(request.getRequestDetails().getRequestParameters()); - assertNull(request.getRequestDetails().getConfigurationParameters()); - - // null response - assertNull(new SoActorServiceProvider().constructRequestCq(onset, operation, policy, null)); - - instantiateTargetCq(policy); - policy.setRecipe(VF_MODULE_DELETE); - SoRequest deleteRequest = new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqResp); - assertNotNull(deleteRequest); - assertEquals(SoOperationType.DELETE_VF_MODULE, deleteRequest.getOperationType()); - - /* - * NOTE: The remaining tests must be done in order - */ - - policy.setRecipe(VF_MODULE_CREATE); - - // null tenant - assertNull(new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqRespMissing)); - - // null service item - assertNull(new SoActorServiceProvider().constructRequestCq(onset, operation, policy, aaiCqRespMissing)); - - assertNull(new SoActorServiceProvider().constructRequestCq(onset, operation, policy, null)); - } - - /** - * Reads an AAI vserver named-query response from a file. - * - * @param fileName name of the file containing the JSON response - * @return output from the AAI vserver named-query - * @throws IOException if the file cannot be read - */ - private AaiCqResponse loadAaiResponseCq(String fileName) throws IOException { - String resp = IOUtils.toString(getClass().getResource(fileName), StandardCharsets.UTF_8); - return new AaiCqResponse(resp); - } - - - - /** - * Creates a policy payload containing request & configuration parameters. - * - * @return the payload - */ - private Map makePayload() { - Map payload = new TreeMap<>(); - - payload.put(SoActorServiceProvider.REQ_PARAM_NM, makeReqParams()); - payload.put(SoActorServiceProvider.CONFIG_PARAM_NM, makeConfigParams()); - - return payload; - } - - /** - * Creates request parameters. - * - * @return request parameters, encoded as JSON - */ - private String makeReqParams() { - SoRequestParameters params = new SoRequestParameters(); - - params.setUsePreload(true); - - Map map = new TreeMap<>(); - map.put("akey", A_VALUE); - - List> lst = new LinkedList<>(); - lst.add(map); - - params.setUserParams(lst); - - return Serialization.gsonPretty.toJson(params); - } - - /** - * Creates configuration parameters. - * - * @return configuration parameters, encoded as JSON - */ - private String makeConfigParams() { - Map map = new TreeMap<>(); - map.put("ckey", C_VALUE); - - List> lst = new LinkedList<>(); - lst.add(map); - - return Serialization.gsonPretty.toJson(lst); - } - -} diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorTest.java new file mode 100644 index 000000000..783380855 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorTest.java @@ -0,0 +1,252 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2018-2020 AT&T. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.so; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; +import java.util.stream.Collectors; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.test.BasicActor; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.so.SoOperationType; +import org.onap.policy.so.SoRequest; +import org.onap.policy.so.SoRequestParameters; +import org.onap.policy.so.util.Serialization; + +public class SoActorTest extends BasicActor { + + private static final String C_VALUE = "cvalue"; + private static final String A_VALUE = "avalue"; + private static final String VF_MODULE_CREATE = "VF Module Create"; + private static final String VF_MODULE_DELETE = "VF Module Delete"; + + private void instantiateTargetCq(Policy policy) { + + Target target = new Target(); + target.setModelCustomizationId("47958575-138f-452a-8c8d-d89b595f8164"); + target.setModelInvariantId("e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e"); + target.setModelName("VfwclVfwsnkBbefb8ce2bde..base_vfw..module-0"); + target.setModelVersion("1"); + target.setModelVersionId("94b18b1d-cc91-4f43-911a-e6348665f292"); + + policy.setTarget(target); + } + + @Test + public void testConstructor() { + SoActor prov = new SoActor(); + + // verify that it has the operators we expect + var expected = Arrays.asList(VfModuleCreate.NAME, VfModuleDelete.NAME).stream().sorted() + .collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(SoActor.NAME, "service.yaml"); + } + + @Test + public void testSendRequest() { + assertThatCode(() -> SoActor.sendRequest(UUID.randomUUID().toString(), null, null, null, null, + null)).doesNotThrowAnyException(); + } + + @Test + public void testMethods() { + SoActor sp = new SoActor(); + + assertEquals("SO", sp.actor()); + assertEquals(2, sp.recipes().size()); + assertEquals(VF_MODULE_CREATE, sp.recipes().get(0)); + assertEquals(VF_MODULE_DELETE, sp.recipes().get(1)); + assertEquals(0, sp.recipePayloads(VF_MODULE_CREATE).size()); + assertEquals(0, sp.recipeTargets("unknown recipe").size()); + assertEquals(1, sp.recipeTargets(VF_MODULE_CREATE).size()); + } + + @Test + public void testConstructRequestCq() throws Exception { + VirtualControlLoopEvent onset = new VirtualControlLoopEvent(); + final ControlLoopOperation operation = new ControlLoopOperation(); + final AaiCqResponse aaiCqResp = loadAaiResponseCq("aai/AaiCqResponseFull.json"); + final AaiCqResponse aaiCqRespMissing = loadAaiResponseCq("aai/AaiCqResponseMissing.json"); + final UUID requestId = UUID.randomUUID(); + onset.setRequestId(requestId); + + Policy policy = new Policy(); + policy.setActor("Dorothy"); + policy.setRecipe("GoToOz"); + + instantiateTargetCq(policy); + + assertNull(new SoActor().constructRequestCq(onset, operation, policy, aaiCqResp)); + + policy.setActor("SO"); + + assertNull(new SoActor().constructRequestCq(onset, operation, policy, aaiCqRespMissing)); + + policy.setRecipe(VF_MODULE_CREATE); + + // empty policy payload + SoRequest request = new SoActor().constructRequestCq(onset, operation, policy, aaiCqResp); + assertNotNull(request); + + assertEquals("vfModuleName", request.getRequestDetails().getRequestInfo().getInstanceName()); + assertEquals("policy", request.getRequestDetails().getRequestInfo().getRequestorId()); + assertEquals("RegionOne", request.getRequestDetails().getCloudConfiguration().getLcpCloudRegionId()); + + // non-empty policy payload + policy.setPayload(makePayload()); + request = new SoActor().constructRequestCq(onset, operation, policy, aaiCqResp); + assertNotNull(request); + assertEquals(true, request.getRequestDetails().getRequestParameters().isUsePreload()); + assertEquals(A_VALUE, request.getRequestDetails().getRequestParameters().getUserParams().get(0).get("akey")); + assertEquals(1, request.getRequestDetails().getConfigurationParameters().size()); + assertEquals(C_VALUE, request.getRequestDetails().getConfigurationParameters().get(0).get("ckey")); + + // payload with config, but no request params + policy.setPayload(makePayload()); + policy.getPayload().remove(SoActor.REQ_PARAM_NM); + request = new SoActor().constructRequestCq(onset, operation, policy, aaiCqResp); + assertNotNull(request); + assertNull(request.getRequestDetails().getRequestParameters()); + assertNotNull(request.getRequestDetails().getConfigurationParameters()); + + // payload with request, but no config params + policy.setPayload(makePayload()); + policy.getPayload().remove(SoActor.CONFIG_PARAM_NM); + request = new SoActor().constructRequestCq(onset, operation, policy, aaiCqResp); + assertNotNull(request); + assertNotNull(request.getRequestDetails().getRequestParameters()); + assertNull(request.getRequestDetails().getConfigurationParameters()); + + // null response + assertNull(new SoActor().constructRequestCq(onset, operation, policy, null)); + + instantiateTargetCq(policy); + policy.setRecipe(VF_MODULE_DELETE); + SoRequest deleteRequest = new SoActor().constructRequestCq(onset, operation, policy, aaiCqResp); + assertNotNull(deleteRequest); + assertEquals(SoOperationType.DELETE_VF_MODULE, deleteRequest.getOperationType()); + + /* + * NOTE: The remaining tests must be done in order + */ + + policy.setRecipe(VF_MODULE_CREATE); + + // null tenant + assertNull(new SoActor().constructRequestCq(onset, operation, policy, aaiCqRespMissing)); + + // null service item + assertNull(new SoActor().constructRequestCq(onset, operation, policy, aaiCqRespMissing)); + + assertNull(new SoActor().constructRequestCq(onset, operation, policy, null)); + } + + /** + * Reads an AAI vserver named-query response from a file. + * + * @param fileName name of the file containing the JSON response + * @return output from the AAI vserver named-query + * @throws IOException if the file cannot be read + */ + private AaiCqResponse loadAaiResponseCq(String fileName) throws IOException { + String resp = IOUtils.toString(getClass().getResource(fileName), StandardCharsets.UTF_8); + return new AaiCqResponse(resp); + } + + + + /** + * Creates a policy payload containing request & configuration parameters. + * + * @return the payload + */ + private Map makePayload() { + Map payload = new TreeMap<>(); + + payload.put(SoActor.REQ_PARAM_NM, makeReqParams()); + payload.put(SoActor.CONFIG_PARAM_NM, makeConfigParams()); + + return payload; + } + + /** + * Creates request parameters. + * + * @return request parameters, encoded as JSON + */ + private String makeReqParams() { + SoRequestParameters params = new SoRequestParameters(); + + params.setUsePreload(true); + + Map map = new TreeMap<>(); + map.put("akey", A_VALUE); + + List> lst = new LinkedList<>(); + lst.add(map); + + params.setUserParams(lst); + + return Serialization.gsonPretty.toJson(params); + } + + /** + * Creates configuration parameters. + * + * @return configuration parameters, encoded as JSON + */ + private String makeConfigParams() { + Map map = new TreeMap<>(); + map.put("ckey", C_VALUE); + + List> lst = new LinkedList<>(); + lst.add(map); + + return Serialization.gsonPretty.toJson(lst); + } + +} diff --git a/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActor.java b/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActor.java new file mode 100644 index 000000000..cf4173176 --- /dev/null +++ b/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActor.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2017-2018 Intel Corp. All rights reserved. + * Modifications Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.vfc; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.List; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpPollingOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.vfc.VfcHealActionVmInfo; +import org.onap.policy.vfc.VfcHealAdditionalParams; +import org.onap.policy.vfc.VfcHealRequest; +import org.onap.policy.vfc.VfcRequest; + +public class VfcActor extends HttpActor { + private static final String GENERIC_VNF_ID = "generic-vnf.vnf-id"; + + // TODO old code: remove lines down to **HERE** + + // Strings for VFC Actor + private static final String VFC_ACTOR = "VFC"; + + public static final String NAME = VFC_ACTOR; + + // Strings for targets + private static final String TARGET_VM = "VM"; + + // Strings for recipes + private static final String RECIPE_RESTART = "Restart"; + + private static final ImmutableList recipes = ImmutableList.of(RECIPE_RESTART); + private static final ImmutableMap> targets = + new ImmutableMap.Builder>().put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).build(); + + // **HERE** + + /** + * Constructor. + */ + public VfcActor() { + super(NAME, HttpPollingActorParams.class); + + addOperator(new HttpPollingOperator(NAME, Restart.NAME, Restart::new)); + } + + // TODO old code: remove lines down to **HERE** + + @Override + public String actor() { + return VFC_ACTOR; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + return Collections.emptyList(); + } + + /** + * This method constructs the VFC request. + * + * @param onset onset object + * @param operation operation object + * @param policy policy object + * @param aaiCqResponse response from aai custom query + * @return VfcRequest + */ + public static VfcRequest constructRequestCq(VirtualControlLoopEvent onset, ControlLoopOperation operation, + Policy policy, AaiCqResponse aaiCqResponse) { + + // Construct an VFC request + VfcRequest request = new VfcRequest(); + String serviceInstance = onset.getAai().get("service-instance.service-instance-id"); + if (serviceInstance == null || "".equals(serviceInstance)) { + // get service instance from AaiCqResponse + if (aaiCqResponse == null) { + return null; + } + serviceInstance = aaiCqResponse.getServiceInstance().getServiceInstanceId(); + // If the serviceInstanceId returned is null then return null + if (serviceInstance == null) { + return null; + } + + } + request.setNsInstanceId(serviceInstance); + request.setRequestId(onset.getRequestId()); + request.setHealRequest(new VfcHealRequest()); + request.getHealRequest().setVnfInstanceId(onset.getAai().get(GENERIC_VNF_ID)); + request.getHealRequest().setCause(operation.getMessage()); + request.getHealRequest().setAdditionalParams(new VfcHealAdditionalParams()); + + if (policy.getRecipe().toLowerCase().equalsIgnoreCase(RECIPE_RESTART)) { + request.getHealRequest().getAdditionalParams().setAction("restartvm"); + request.getHealRequest().getAdditionalParams().setActionInfo(new VfcHealActionVmInfo()); + request.getHealRequest().getAdditionalParams().getActionInfo() + .setVmid(onset.getAai().get("vserver.vserver-id")); + request.getHealRequest().getAdditionalParams().getActionInfo() + .setVmname(onset.getAai().get("vserver.vserver-name")); + } else { + return null; + } + return request; + } + + // **HERE** + +} diff --git a/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProvider.java b/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProvider.java deleted file mode 100644 index 768ad4c11..000000000 --- a/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProvider.java +++ /dev/null @@ -1,141 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2017-2018 Intel Corp. All rights reserved. - * Modifications Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.vfc; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.Collections; -import java.util.List; -import org.onap.policy.aai.AaiCqResponse; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpPollingOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingActorParams; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.vfc.VfcHealActionVmInfo; -import org.onap.policy.vfc.VfcHealAdditionalParams; -import org.onap.policy.vfc.VfcHealRequest; -import org.onap.policy.vfc.VfcRequest; - -public class VfcActorServiceProvider extends HttpActor { - private static final String GENERIC_VNF_ID = "generic-vnf.vnf-id"; - - // TODO old code: remove lines down to **HERE** - - // Strings for VFC Actor - private static final String VFC_ACTOR = "VFC"; - - public static final String NAME = VFC_ACTOR; - - // Strings for targets - private static final String TARGET_VM = "VM"; - - // Strings for recipes - private static final String RECIPE_RESTART = "Restart"; - - private static final ImmutableList recipes = ImmutableList.of(RECIPE_RESTART); - private static final ImmutableMap> targets = - new ImmutableMap.Builder>().put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).build(); - - // **HERE** - - /** - * Constructor. - */ - public VfcActorServiceProvider() { - super(NAME, HttpPollingActorParams.class); - - addOperator(new HttpPollingOperator(NAME, Restart.NAME, Restart::new)); - } - - // TODO old code: remove lines down to **HERE** - - @Override - public String actor() { - return VFC_ACTOR; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - return Collections.emptyList(); - } - - /** - * This method constructs the VFC request. - * - * @param onset onset object - * @param operation operation object - * @param policy policy object - * @param aaiCqResponse response from aai custom query - * @return VfcRequest - */ - public static VfcRequest constructRequestCq(VirtualControlLoopEvent onset, ControlLoopOperation operation, - Policy policy, AaiCqResponse aaiCqResponse) { - - // Construct an VFC request - VfcRequest request = new VfcRequest(); - String serviceInstance = onset.getAai().get("service-instance.service-instance-id"); - if (serviceInstance == null || "".equals(serviceInstance)) { - // get service instance from AaiCqResponse - if (aaiCqResponse == null) { - return null; - } - serviceInstance = aaiCqResponse.getServiceInstance().getServiceInstanceId(); - // If the serviceInstanceId returned is null then return null - if (serviceInstance == null) { - return null; - } - - } - request.setNsInstanceId(serviceInstance); - request.setRequestId(onset.getRequestId()); - request.setHealRequest(new VfcHealRequest()); - request.getHealRequest().setVnfInstanceId(onset.getAai().get(GENERIC_VNF_ID)); - request.getHealRequest().setCause(operation.getMessage()); - request.getHealRequest().setAdditionalParams(new VfcHealAdditionalParams()); - - if (policy.getRecipe().toLowerCase().equalsIgnoreCase(RECIPE_RESTART)) { - request.getHealRequest().getAdditionalParams().setAction("restartvm"); - request.getHealRequest().getAdditionalParams().setActionInfo(new VfcHealActionVmInfo()); - request.getHealRequest().getAdditionalParams().getActionInfo() - .setVmid(onset.getAai().get("vserver.vserver-id")); - request.getHealRequest().getAdditionalParams().getActionInfo() - .setVmname(onset.getAai().get("vserver.vserver-name")); - } else { - return null; - } - return request; - } - - // **HERE** - -} diff --git a/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index e43c726cf..a9e6a1d9b 100644 --- a/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.vfc.VfcActorServiceProvider +org.onap.policy.controlloop.actor.vfc.VfcActor diff --git a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProviderTest.java b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProviderTest.java deleted file mode 100644 index 9e05f22e1..000000000 --- a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorServiceProviderTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - Policy Drools Applications - * ================================================================================ - * Copyright (C) 2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2018-2019 AT&T Corp. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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.vfc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Objects; -import java.util.UUID; -import java.util.stream.Collectors; -import org.apache.commons.io.IOUtils; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.policy.aai.AaiCqResponse; -import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.test.BasicActor; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.simulators.Util; -import org.onap.policy.vfc.VfcRequest; - -public class VfcActorServiceProviderTest extends BasicActor { - - private static final String DOROTHY_GALE_1939 = "dorothy.gale.1939"; - private static final String CQ_RESPONSE_JSON = "aai/AaiCqResponse.json"; - private static final String RESTART = "Restart"; - - /** - * Set up before test class. - * @throws Exception if the A&AI simulator cannot be started - */ - @BeforeClass - public static void setUpSimulator() throws Exception { - Util.buildAaiSim(); - } - - @AfterClass - public static void tearDownSimulator() { - HttpServletServerFactoryInstance.getServerFactory().destroy(); - } - - @Test - public void testConstructor() { - VfcActorServiceProvider prov = new VfcActorServiceProvider(); - assertEquals(0, prov.getSequenceNumber()); - - // verify that it has the operators we expect - var expected = Arrays.asList(Restart.NAME).stream().sorted().collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - } - - @Test - public void testActorService() { - // verify that it all plugs into the ActorService - verifyActorService(VfcActorServiceProvider.NAME, "service.yaml"); - } - - @Test - public void testMethods() { - VfcActorServiceProvider sp = new VfcActorServiceProvider(); - - assertEquals("VFC", sp.actor()); - assertEquals(1, sp.recipes().size()); - assertEquals(RESTART, sp.recipes().get(0)); - assertEquals("VM", sp.recipeTargets(RESTART).get(0)); - assertEquals(0, sp.recipePayloads(RESTART).size()); - } - - @Test - public void testConstructRequestCq() throws IOException { - VirtualControlLoopEvent onset = new VirtualControlLoopEvent(); - ControlLoopOperation operation = new ControlLoopOperation(); - - Policy policy = new Policy(); - policy.setRecipe("GoToOz"); - - assertNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, null)); - - onset.getAai().put("generic-vnf.vnf-id", DOROTHY_GALE_1939); - assertNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, null)); - - - UUID requestId = UUID.randomUUID(); - onset.setRequestId(requestId); - assertNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, null)); - - onset.getAai().put("generic-vnf.vnf-name", "Dorothy"); - assertNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, null)); - - - onset.getAai().put("service-instance.service-instance-id", ""); - assertNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, null)); - - assertNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, - loadAaiResponse(CQ_RESPONSE_JSON))); - - policy.setRecipe(RESTART); - assertNotNull(VfcActorServiceProvider.constructRequestCq(onset, operation, policy, - loadAaiResponse(CQ_RESPONSE_JSON))); - - VfcRequest request = VfcActorServiceProvider.constructRequestCq(onset, operation, policy, - loadAaiResponse(CQ_RESPONSE_JSON)); - - assertEquals(requestId, Objects.requireNonNull(request).getRequestId()); - assertEquals(DOROTHY_GALE_1939, request.getHealRequest().getVnfInstanceId()); - assertEquals("restartvm", request.getHealRequest().getAdditionalParams().getAction()); - } - - /** - * Reads an AAI vserver named-query response from a file. - * - * @param fileName name of the file containing the JSON response - * @return output from the AAI vserver named-query - * @throws IOException if the file cannot be read - */ - private AaiCqResponse loadAaiResponse(String fileName) throws IOException { - String resp = IOUtils.toString(getClass().getResource(fileName), StandardCharsets.UTF_8); - return new AaiCqResponse(resp); - } - -} diff --git a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorTest.java b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorTest.java new file mode 100644 index 000000000..bd4bb0980 --- /dev/null +++ b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcActorTest.java @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2018-2019 AT&T Corp. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.vfc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; +import org.apache.commons.io.IOUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.test.BasicActor; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.simulators.Util; +import org.onap.policy.vfc.VfcRequest; + +public class VfcActorTest extends BasicActor { + + private static final String DOROTHY_GALE_1939 = "dorothy.gale.1939"; + private static final String CQ_RESPONSE_JSON = "aai/AaiCqResponse.json"; + private static final String RESTART = "Restart"; + + /** + * Set up before test class. + * @throws Exception if the A&AI simulator cannot be started + */ + @BeforeClass + public static void setUpSimulator() throws Exception { + Util.buildAaiSim(); + } + + @AfterClass + public static void tearDownSimulator() { + HttpServletServerFactoryInstance.getServerFactory().destroy(); + } + + @Test + public void testConstructor() { + VfcActor prov = new VfcActor(); + assertEquals(0, prov.getSequenceNumber()); + + // verify that it has the operators we expect + var expected = Arrays.asList(Restart.NAME).stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(VfcActor.NAME, "service.yaml"); + } + + @Test + public void testMethods() { + VfcActor sp = new VfcActor(); + + assertEquals("VFC", sp.actor()); + assertEquals(1, sp.recipes().size()); + assertEquals(RESTART, sp.recipes().get(0)); + assertEquals("VM", sp.recipeTargets(RESTART).get(0)); + assertEquals(0, sp.recipePayloads(RESTART).size()); + } + + @Test + public void testConstructRequestCq() throws IOException { + VirtualControlLoopEvent onset = new VirtualControlLoopEvent(); + ControlLoopOperation operation = new ControlLoopOperation(); + + Policy policy = new Policy(); + policy.setRecipe("GoToOz"); + + assertNull(VfcActor.constructRequestCq(onset, operation, policy, null)); + + onset.getAai().put("generic-vnf.vnf-id", DOROTHY_GALE_1939); + assertNull(VfcActor.constructRequestCq(onset, operation, policy, null)); + + + UUID requestId = UUID.randomUUID(); + onset.setRequestId(requestId); + assertNull(VfcActor.constructRequestCq(onset, operation, policy, null)); + + onset.getAai().put("generic-vnf.vnf-name", "Dorothy"); + assertNull(VfcActor.constructRequestCq(onset, operation, policy, null)); + + + onset.getAai().put("service-instance.service-instance-id", ""); + assertNull(VfcActor.constructRequestCq(onset, operation, policy, null)); + + assertNull(VfcActor.constructRequestCq(onset, operation, policy, + loadAaiResponse(CQ_RESPONSE_JSON))); + + policy.setRecipe(RESTART); + assertNotNull(VfcActor.constructRequestCq(onset, operation, policy, + loadAaiResponse(CQ_RESPONSE_JSON))); + + VfcRequest request = VfcActor.constructRequestCq(onset, operation, policy, + loadAaiResponse(CQ_RESPONSE_JSON)); + + assertEquals(requestId, Objects.requireNonNull(request).getRequestId()); + assertEquals(DOROTHY_GALE_1939, request.getHealRequest().getVnfInstanceId()); + assertEquals("restartvm", request.getHealRequest().getAdditionalParams().getAction()); + } + + /** + * Reads an AAI vserver named-query response from a file. + * + * @param fileName name of the file containing the JSON response + * @return output from the AAI vserver named-query + * @throws IOException if the file cannot be read + */ + private AaiCqResponse loadAaiResponse(String fileName) throws IOException { + String resp = IOUtils.toString(getClass().getResource(fileName), StandardCharsets.UTF_8); + return new AaiCqResponse(resp); + } + +} -- cgit 1.2.3-korg