diff options
author | Saravanan A <saravanan.a75@wipro.com> | 2018-09-10 17:31:33 +0530 |
---|---|---|
committer | Saravanan A <saravanan.a75@wipro.com> | 2018-09-12 21:51:11 +0530 |
commit | dbecba3a4baffacf9f2da82592b3e3a9e2929f21 (patch) | |
tree | 71b93f111551115b8d0f8d634a23b825a9cd4b0e /controlloop/common/actors/actor.sdnr | |
parent | 2e2f7f988509b273912664ac2ffc07f583988b59 (diff) |
Add implementation for OOF PCI use case
Receive DMaaP message from PCI-Handler MS with PCI Config
change recommendations through DCAE_CL_OUTPUT topic.
Trigger SDN-R (if allowed by policy) by sending
DMaaP request through SDNR-CL topic.
When the response is received from SDNR through
SDNR-CL-RSP topic, just parse and print.
Code review comments addressed
Change-Id: If340a23ae18367b7f98e31fe79c09a09e645b2ad
Issue-ID: POLICY-1089
Signed-off-by: Saravanan A<saravanan.a75@wipro.com>
Diffstat (limited to 'controlloop/common/actors/actor.sdnr')
4 files changed, 486 insertions, 0 deletions
diff --git a/controlloop/common/actors/actor.sdnr/pom.xml b/controlloop/common/actors/actor.sdnr/pom.xml new file mode 100644 index 000000000..50ed820c0 --- /dev/null +++ b/controlloop/common/actors/actor.sdnr/pom.xml @@ -0,0 +1,83 @@ +<?xml version="1.0"?> +<!-- + ============LICENSE_START======================================================= + drools-pdp-apps + ================================================================================ + Copyright (C) 2018 Wipro Limited Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actors</artifactId> + <version>1.3.0-SNAPSHOT</version> + </parent> + + <artifactId>actor.sdnr</artifactId> + + <dependencies> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actorServiceProvider</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>sdnr</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>events</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> + <artifactId>simulators</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>policy-endpoints</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-pdp</groupId> + <artifactId>policy-management</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/controlloop/common/actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java b/controlloop/common/actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java new file mode 100644 index 000000000..406870208 --- /dev/null +++ b/controlloop/common/actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProvider.java @@ -0,0 +1,255 @@ +/*- + * ============LICENSE_START======================================================= + * SdnrActorServiceProvider + * ================================================================================ + * Copyright (C) 2018 Wipro Limited 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.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.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; + +public class SdnrActorServiceProvider implements Actor { + + public static class Pair<A, B> { + public final A result; + public final B message; + + public Pair(A result, B message) { + this.result = result; + this.message = message; + } + + public A getResult() { + return this.result; + } + + public B getMessage() { + return this.message; + } + } + + 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<String> recipes = ImmutableList.of(RECIPE_MODIFY); + private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>() + .put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); + private static final ImmutableMap<String, List<String>> payloads = new ImmutableMap.Builder<String, List<String>>() + .put(RECIPE_MODIFY, ImmutableList.of(SDNR_REQUEST_PARAMS, SDNR_CONFIG_PARAMS)).build(); + + @Override + public String actor() { + return "SDNR"; + } + + @Override + public List<String> recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List<String> recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List<String> recipePayloads(String recipe) { + return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); + } + + /** + * Constructs an 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 SdnrActorServiceProvider.Pair<PolicyResult, String> 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 new SdnrActorServiceProvider.Pair<>(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 new SdnrActorServiceProvider.Pair<>(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 new SdnrActorServiceProvider.Pair<>(result, message); + } +} diff --git a/controlloop/common/actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/controlloop/common/actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor new file mode 100644 index 000000000..c8d5e4c41 --- /dev/null +++ b/controlloop/common/actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor @@ -0,0 +1 @@ +org.onap.policy.controlloop.actor.sdnr.SdnrActorServiceProvider diff --git a/controlloop/common/actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java b/controlloop/common/actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java new file mode 100644 index 000000000..030bb9ec4 --- /dev/null +++ b/controlloop/common/actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrActorServiceProviderTest.java @@ -0,0 +1,147 @@ +/*- + * SdnrActorServiceProviderTest + * ================================================================================ + * Copyright (C) 2018 Wipro Limited 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.assertTrue; +import static org.junit.Assert.fail; + +import java.time.Instant; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.ControlLoopTargetType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.system.PolicyEngine; +import org.onap.policy.sdnr.PciRequest; +import org.onap.policy.sdnr.PciResponse; +import org.onap.policy.sdnr.util.Serialization; +import org.onap.policy.simulators.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SdnrActorServiceProviderTest { + + 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("ModifyConfig"); + 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("ModifyConfig"); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + } + + @Test + public void constructModifyConfigRequestTest() { + + 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("ModifyConfig", 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("ModifyConfig")); + 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("ModifyConfig").get(0)); + assertEquals(2, sp.recipePayloads("ModifyConfig").size()); + } +} |