diff options
Diffstat (limited to 'controlloop')
16 files changed, 478 insertions, 69 deletions
diff --git a/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java b/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java index 1d4af389f..b4151a9f9 100644 --- a/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java +++ b/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java @@ -3,13 +3,14 @@ * AppcLcmActorServiceProvider * ================================================================================ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Modifications copyright (c) 2018 Nokia * ================================================================================ * 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. @@ -196,10 +197,12 @@ public class AppcLcmActorServiceProvider implements Actor { * 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()); + LcmRequestWrapper dmaapRequest = new LcmRequestWrapper(); dmaapRequest.setVersion("2.0"); dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); - dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); + dmaapRequest.setRpcName(lcmRecipeFormatter.getUrlRecipe()); dmaapRequest.setType("request"); /* This is the actual request that is placed in the dmaap wrapper. */ @@ -226,8 +229,7 @@ public class AppcLcmActorServiceProvider implements Actor { * An action is required for all APPC requests, this will be the recipe specified in the * policy. */ - appcRequest.setAction( - policy.getRecipe().substring(0, 1).toUpperCase() + policy.getRecipe().substring(1).toLowerCase()); + appcRequest.setAction(lcmRecipeFormatter.getBodyRecipe()); /* * For R1, the payloads will not be required for the Restart, Rebuild, or Migrate recipes. diff --git a/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmRecipeFormatter.java b/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmRecipeFormatter.java new file mode 100644 index 000000000..c9feb0d2a --- /dev/null +++ b/controlloop/common/actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmRecipeFormatter.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * + * ================================================================================ + * Copyright (C) 2018 Nokia Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appclcm; + +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; + +import java.util.stream.Collectors; + +class AppcLcmRecipeFormatter { + + private final String dashCasedRecipe; + + AppcLcmRecipeFormatter(String dashCasedRecipe) { + this.dashCasedRecipe = dashCasedRecipe; + } + + String getUrlRecipe() { + return dashCasedRecipe.toLowerCase(); + } + + String getBodyRecipe() { + return Lists.newArrayList(dashCasedRecipe.split("-")) + .stream() + .map(String::toLowerCase) + .map(StringUtils::capitalize) + .collect(Collectors.joining("")); + } +} diff --git a/controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmRecipeFormatterTest.java b/controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmRecipeFormatterTest.java new file mode 100644 index 000000000..e63b04acd --- /dev/null +++ b/controlloop/common/actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmRecipeFormatterTest.java @@ -0,0 +1,98 @@ +/* + * ============LICENSE_START======================================================= + * + * ================================================================================ + * Copyright (C) 2018 Nokia Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appclcm; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + + + +public class AppcLcmRecipeFormatterTest { + + @Test + public void shouldCorrectlyFormatRestartRequestWhenRestartGiven() { + //given + AppcLcmRecipeFormatter recipeFormatter = new AppcLcmRecipeFormatter("Restart"); + String expectedUrlRecipe = "restart"; + String expectedBodyRecipe = "Restart"; + + //when + String actualUrlRecipe = recipeFormatter.getUrlRecipe(); + String actualBodyRecipe = recipeFormatter.getBodyRecipe(); + + //then + assertEquals(expectedUrlRecipe, actualUrlRecipe); + assertEquals(expectedBodyRecipe, actualBodyRecipe); + } + + @Test + public void shouldReturnCapitalizedBodySingleWordRecipe() { + //given + AppcLcmRecipeFormatter recipeFormatter = new AppcLcmRecipeFormatter("moDify"); + String expectedRecipe = "Modify"; + + //when + String actualRecipe = recipeFormatter.getBodyRecipe(); + + //then + assertEquals(expectedRecipe, actualRecipe); + } + + @Test + public void shouldReturnCapitalizeAndJoinedBodyMultiWordRecipe() { + //given + AppcLcmRecipeFormatter recipeFormatter = new AppcLcmRecipeFormatter("coNfig-moDify"); + String expectedRecipe = "ConfigModify"; + + //when + String actualRecipe = recipeFormatter.getBodyRecipe(); + + //then + assertEquals(expectedRecipe, actualRecipe); + } + + @Test + public void shouldReturnLowercasedUrlSingleWordRecipe() { + //given + AppcLcmRecipeFormatter recipeFormatter = new AppcLcmRecipeFormatter("ModIfy"); + String expectedRecipe = "modify"; + + //when + String actualRecipe = recipeFormatter.getUrlRecipe(); + + //then + assertEquals(expectedRecipe, actualRecipe); + } + + @Test + public void shouldReturnLowercasedDashJoinedUrlMultiWordRecipe() { + //given + AppcLcmRecipeFormatter recipeFormatter = new AppcLcmRecipeFormatter("Config-MoDify"); + String expectedRecipe = "config-modify"; + + //when + String actualRecipe = recipeFormatter.getUrlRecipe(); + + //then + assertEquals(expectedRecipe, actualRecipe); + } +}
\ No newline at end of file diff --git a/controlloop/common/eventmanager/pom.xml b/controlloop/common/eventmanager/pom.xml index 518875b38..4e01c6699 100644 --- a/controlloop/common/eventmanager/pom.xml +++ b/controlloop/common/eventmanager/pom.xml @@ -19,7 +19,7 @@ --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -181,5 +181,10 @@ <version>${project.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java index 4b438a94d..930f9578f 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java @@ -30,6 +30,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.NoSuchElementException; import org.onap.policy.aai.AaiGetVnfResponse; import org.onap.policy.aai.AaiGetVserverResponse; @@ -99,6 +100,7 @@ public class ControlLoopEventManager implements LockCallback, Serializable { private boolean isActivated = false; private LinkedList<ControlLoopOperation> controlLoopHistory = new LinkedList<>(); private ControlLoopOperationManager currentOperation = null; + private ControlLoopOperationManager lastOperationManager = null; private transient TargetLock targetLock = null; private AaiGetVnfResponse vnfResponse = null; private AaiGetVserverResponse vserverResponse = null; @@ -414,6 +416,7 @@ public class ControlLoopEventManager implements LockCallback, Serializable { // // And setup an operation // + this.lastOperationManager = this.currentOperation; this.currentOperation = new ControlLoopOperationManager(this.onset, policy, this); // // Return it @@ -449,6 +452,7 @@ public class ControlLoopEventManager implements LockCallback, Serializable { // // Just null this out // + this.lastOperationManager = this.currentOperation; this.currentOperation = null; // // TODO: Release our lock @@ -594,6 +598,26 @@ public class ControlLoopEventManager implements LockCallback, Serializable { return NEW_EVENT_STATUS.SYNTAX_ERROR; } + + /** + * Commit the abatement to the history database. + * + * @param message the abatement message + * @param outcome the abatement outcome + */ + public void commitAbatement(String message, String outcome) { + if (this.lastOperationManager == null) { + logger.error("{}: commitAbatement: no operation manager", this); + return; + } + try{ + this.lastOperationManager.commitAbatement(message,outcome); + } catch (NoSuchElementException e) { + logger.error("{}: commitAbatement threw an exception ", this, e); + } + } + + /** * Set the control loop time out. * diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java index 0eb924dd2..f1d912ef5 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java @@ -27,6 +27,7 @@ import java.util.AbstractMap; import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.NoSuchElementException; import javax.persistence.EntityManager; import javax.persistence.Persistence; @@ -844,7 +845,36 @@ public class ControlLoopOperationManager implements Serializable { } } logger.debug("Could not find associated operation"); - } + + /** + * Commit the abatement to the history database. + * + * @param message the abatement message + * @param outcome the abatement outcome + */ + public void commitAbatement(String message, String outcome) { + logger.info("commitAbatement: " + message + ", " + outcome); + + if (this.currentOperation == null) { + try { + this.currentOperation = this.operationHistory.getLast(); + } catch (NoSuchElementException e) { + logger.error("{}: commitAbatement threw an exception ", this, e); + return; + } + } + this.currentOperation.clOperation.setEnd(Instant.now()); + this.currentOperation.clOperation.setMessage(message); + this.currentOperation.clOperation.setOutcome(outcome); + // + // Store commit in DB + // + this.storeOperationInDataBase(); + // + // Clear the current operation field + // + this.currentOperation = null; + } } diff --git a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java index 46452974e..d1763f52c 100644 --- a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java +++ b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManagerTest.java @@ -36,6 +36,14 @@ import java.time.Instant; import java.util.HashMap; import java.util.UUID; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.NoResultException; +import javax.persistence.NonUniqueResultException; +import javax.persistence.Persistence; +import javax.persistence.Query; + + import org.apache.commons.io.IOUtils; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -94,23 +102,62 @@ public class ControlLoopOperationManagerTest { PolicyEngine.manager.setEnvironmentProperty("aai.password", "AAI"); } + private static EntityManagerFactory emf; + private static EntityManager em; + + + private static int getCount() { + // Create a query for number of items in DB + String sql = "select count(*) as count from operationshistory10"; + Query nq = em.createNativeQuery(sql); + + int numEvents = -1; + try { + numEvents = ((Number) nq.getSingleResult()).intValue(); + } catch (NoResultException | NonUniqueResultException ex) { + logger.error("getCountFromDb threw: ", ex); + fail(ex.getMessage()); + } + return numEvents; + } + + /** * Set up test class. */ @BeforeClass - public static void setUpSimulator() { + public static void setUp() { + try { org.onap.policy.simulators.Util.buildAaiSim(); } catch (Exception e) { fail(e.getMessage()); } + + // Set PU + System.setProperty("OperationsHistoryPU", "TestOperationsHistoryPU"); + + // Enter dummy props to avoid nullPointerException + PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.ONAP_KEY_URL, "a"); + PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.ONAP_KEY_USER, "b"); + PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.ONAP_KEY_PASS, "c"); + + // Connect to in-mem db + emf = Persistence.createEntityManagerFactory("TestOperationsHistoryPU"); + em = emf.createEntityManager(); } + + /** + * Clean up test class. + */ @AfterClass - public static void tearDownSimulator() { + public static void tearDown() { + em.close(); + emf.close(); HttpServletServer.factory.destroy(); } - + @Test public void testRetriesFail() { // @@ -759,5 +806,48 @@ public class ControlLoopOperationManagerTest { System.setProperty("OperationsHistoryPU", "TestOperationsHistoryPU"); assertEquals(PolicyResult.FAILURE, clom.onResponse(soRw)); - } + } + + @Test + public void testCommitAbatement() throws ControlLoopException, AaiException, IOException { + + String yamlString = null; + try ( InputStream is = new FileInputStream(new File("src/test/resources/test.yaml")) ) { + yamlString = IOUtils.toString(is, StandardCharsets.UTF_8); + } catch (Exception e) { + fail(e.getMessage()); + } + + UUID requestId = UUID.randomUUID(); + VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.setClosedLoopControlName("TwoOnsetTest"); + onsetEvent.setRequestId(requestId); + onsetEvent.setTarget("generic-vnf.vnf-id"); + onsetEvent.setClosedLoopAlarmStart(Instant.now()); + onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); + onsetEvent.setAai(new HashMap<>()); + onsetEvent.getAai().put("generic-vnf.vnf-name", "onsetOne"); + + ControlLoopEventManager manager = + new ControlLoopEventManager(onsetEvent.getClosedLoopControlName(), onsetEvent.getRequestId()); + VirtualControlLoopNotification notification = manager.activate(yamlString, onsetEvent); + assertNotNull(notification); + assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification()); + + Policy policy = manager.getProcessor().getCurrentPolicy(); + ControlLoopOperationManager clom = new ControlLoopOperationManager(onsetEvent, policy, manager); + assertNotNull(clom); + + clom.startOperation(onsetEvent); + + int numEventsBefore = getCount(); + logger.info("numEventsBefore={}", numEventsBefore); + + clom.commitAbatement("Test message","TEST_RESULT"); + + int numEventsAfter = getCount(); + logger.info("numEventsAfter={}", numEventsAfter); + + assertEquals(1, numEventsAfter - numEventsBefore); + } } diff --git a/controlloop/common/eventmanager/src/test/resources/META-INF/persistence.xml b/controlloop/common/eventmanager/src/test/resources/META-INF/persistence.xml index 047d0ab6d..1c2eb12fd 100644 --- a/controlloop/common/eventmanager/src/test/resources/META-INF/persistence.xml +++ b/controlloop/common/eventmanager/src/test/resources/META-INF/persistence.xml @@ -22,16 +22,17 @@ <persistence-unit name="TestOperationsHistoryPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> - <class>org.onap.policy.whatever.WhatEver</class> - + <class>org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry</class> + <properties> - <property name="javax.persistence.jdbc.url" value="jdbc:derby:memory:apex_test" /> - <property name="javax.persistence.target-database" value="Derby" /> - <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" /> - - <property name="eclipselink.ddl-generation" value="drop-and-create-tables" /> - <property name="eclipselink.ddl-generation.output-mode" value="database"/> - <property name="eclipselink.logging.level" value="INFO" /> + <property name="eclipselink.ddl-generation" value="create-or-extend-tables" /> + <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /> + <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test" /> + <property name="javax.persistence.jdbc.user" value="sa" /> + <property name="javax.persistence.jdbc.password" value="" /> + <property name="eclipselink.ddl-generation" value="drop-and-create-tables" /> + <property name="eclipselink.ddl-generation.output-mode" value="database"/> + <property name="eclipselink.logging.level" value="INFO" /> </properties> </persistence-unit> </persistence> diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java index 4ac22600b..146f42170 100644 --- a/controlloop/common/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/CallGuardTask.java @@ -20,45 +20,99 @@ package org.onap.policy.guard; -import com.att.research.xacml.api.DataTypeException; -import com.att.research.xacml.std.annotations.RequestParser; - +import java.util.HashSet; +import java.util.Set; import java.util.UUID; - +import java.util.function.Supplier; import org.drools.core.WorkingMemory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.std.annotations.RequestParser; public class CallGuardTask implements Runnable { private static final Logger logger = LoggerFactory.getLogger(CallGuardTask.class); - WorkingMemory workingMemory; - String restfulPdpUrl; - String clname; - String actor; - String recipe; - String target; - String requestId; + + /** + * Actor/recipe pairs whose guard requests need a VF Module count. Each element is of + * the form "<actor>:<recipe>". + */ + private static final Set<String> NEEDS_VF_COUNT = new HashSet<>(); + + /** + * Actor/recipe pairs whose guard requests need the VF Module count to be incremented + * (i.e., because a module is being added). Each element is of the form + * "<actor>:<recipe>". + */ + private static final Set<String> INCR_VF_COUNT = new HashSet<>(); + + static { + INCR_VF_COUNT.add("SO:VF Module Create"); + NEEDS_VF_COUNT.addAll(INCR_VF_COUNT); + } + + private WorkingMemory workingMemory; + private String clname; + private String actor; + private String recipe; + private String target; + private String requestId; + private Integer vfCount; + + /** + * Populated once the response has been determined, which may happen during the + * constructor or later, during {@link #run()}. + */ + private PolicyGuardResponse guardResponse; /** * Guard url is grabbed from PolicyEngine.manager properties */ - public CallGuardTask(WorkingMemory wm, String cl, String act, String rec, String tar, String reqId) { + public CallGuardTask(WorkingMemory wm, String cl, String act, String rec, String tar, String reqId, Supplier<Integer> vfcnt) { workingMemory = wm; clname = cl; actor = act; recipe = rec; requestId = reqId; target = tar; + + vfCount = null; + + String key = act + ":" + rec; + + if (NEEDS_VF_COUNT.contains(key)) { + // this actor/recipe needs the count - get it + if ((vfCount = vfcnt.get()) == null) { + /* + * The count is missing - create an artificial Deny, which will be + * inserted into working memory when "run()" is called. + */ + guardResponse = new PolicyGuardResponse(Util.DENY, UUID.fromString(requestId), recipe); + logger.error("CallGuardTask.run missing VF Module count; requestId={}", requestId); + return; + } + + if (INCR_VF_COUNT.contains(key)) { + // this actor/recipe needs the count to be incremented + ++vfCount; + } + } } @Override public void run() { + if (guardResponse != null) { + // already have a response - just insert it + workingMemory.insert(guardResponse); + return; + } + final long startTime = System.nanoTime(); com.att.research.xacml.api.Request request = null; PolicyGuardXacmlRequestAttributes xacmlReq = - new PolicyGuardXacmlRequestAttributes(clname, actor, recipe, target, requestId); + new PolicyGuardXacmlRequestAttributes(clname, actor, recipe, target, requestId, vfCount); try { request = RequestParser.parseRequest(xacmlReq); @@ -90,8 +144,7 @@ public class CallGuardTask implements Runnable { guardDecision = Util.INDETERMINATE; } - PolicyGuardResponse guardResponse = - new PolicyGuardResponse(guardDecision, UUID.fromString(this.requestId), this.recipe); + guardResponse = new PolicyGuardResponse(guardDecision, UUID.fromString(this.requestId), this.recipe); // diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java index 321d80ce2..53ba6075e 100644 --- a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlHelper.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * guard * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 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. @@ -100,6 +100,9 @@ public class PolicyGuardXacmlHelper { if (xacmlReq.getClnameID() != null) { attributes.put("clname", xacmlReq.getClnameID()); } + if (xacmlReq.getVfCount() != null) { + attributes.put("vfCount", xacmlReq.getVfCount()); + } JSONObject jsonReq = new JSONObject(); jsonReq.put("decisionAttributes", attributes); jsonReq.put("onapName", "PDPD"); diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java index ab1d04efa..6b17af804 100644 --- a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributes.java @@ -36,15 +36,17 @@ public class PolicyGuardXacmlRequestAttributes { * @param operationId the operation Id * @param targetId the target Id * @param requestId the request Id + * @param vfCount the new number of VF Modules */ public PolicyGuardXacmlRequestAttributes(String clnameId, String actorId, String operationId, String targetId, - String requestId) { + String requestId, Integer vfCount) { super(); this.clnameID = clnameId; this.actorID = actorId; this.operationID = operationId; this.targetID = targetId; this.requestID = requestId; + this.vfCount = vfCount; } @Override @@ -68,6 +70,9 @@ public class PolicyGuardXacmlRequestAttributes { @XACMLResource(includeInResults = true, attributeId = "urn:oasis:names:tc:xacml:1.0:request:request-id") String requestID; + @XACMLResource(includeInResults = true, attributeId = "urn:oasis:names:tc:xacml:1.0:request:vf-count") + Integer vfCount; + public String getActorID() { return actorID; } @@ -107,4 +112,12 @@ public class PolicyGuardXacmlRequestAttributes { public void setClnameID(String clnameID) { this.clnameID = clnameID; } + + public Integer getVfCount() { + return vfCount; + } + + public void setVfCount(Integer vfCount) { + this.vfCount = vfCount; + } } diff --git a/controlloop/common/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java b/controlloop/common/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java index 3255aec77..b1b057542 100644 --- a/controlloop/common/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java +++ b/controlloop/common/guard/src/test/java/org/onap/policy/guard/CallGuardTaskTest.java @@ -26,37 +26,53 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.drools.core.impl.StatefulKnowledgeSessionImpl; +import java.util.function.Supplier; +import org.drools.core.WorkingMemory; import org.junit.Test; public class CallGuardTaskTest { - static final String REQ_ID = "1-2-3-4-5"; - static final String REQ_MATCHER = "0+1-0+2-0+3-0+4-0+5"; + private static final String REQ_ID = "1-2-3-4-5"; + private static final String REQ_MATCHER = "0+1-0+2-0+3-0+4-0+5"; + private static final String VF_COUNT_ACTOR = "SO"; + private static final String INCR_VF_COUNT_RECIPE = "VF Module Create"; - @Test /** - * Tests that the run method inserts guard response into working memory. + * Tests that "run" works, and inserts guard response into working memory. */ + @Test public void testRun() { - // Create mock working session - StatefulKnowledgeSessionImpl mockWorkingSession = mock(StatefulKnowledgeSessionImpl.class); + // plain - doesn't need VF module count + doTestRun(Util.INDETERMINATE, "act", "rec", () -> null); + + // SO actor, but plain recipe - doesn't need VF module count + doTestRun(Util.INDETERMINATE, VF_COUNT_ACTOR, "rec", () -> null); + + // plain actor, but scale-out recipe - doesn't need VF module count + doTestRun(Util.INDETERMINATE, "act", "VF Module Create", () -> null); + + // needs VF count + doTestRun(Util.INDETERMINATE, VF_COUNT_ACTOR, INCR_VF_COUNT_RECIPE, () -> 22); + + // needs VF count, but it's missing ==> DENY + doTestRun(Util.DENY, VF_COUNT_ACTOR, INCR_VF_COUNT_RECIPE, () -> null); + } + + private void doTestRun(String status, String actor, String recipe, Supplier<Integer> vfCount) { + WorkingMemory mockWorkingSession = mock(WorkingMemory.class); when(mockWorkingSession.insert(isNotNull())).thenReturn(null); // Create CallGuardTask and run - CallGuardTask cgt = new CallGuardTask(mockWorkingSession, "cl", "act", "rec", "tar", REQ_ID); + CallGuardTask cgt = new CallGuardTask(mockWorkingSession, "cl", actor, recipe, "tar", REQ_ID, vfCount); cgt.run(); verify(mockWorkingSession).insert(argThat((Object obj) -> { if (!(obj instanceof PolicyGuardResponse)) { return false; } - // Check if the inserted response is PolicyGuardResponse, is Indeterminate, and has same - // reqID + // Check if the inserted response is PolicyGuardResponse, is Indeterminate, + // and has same reqID PolicyGuardResponse response = (PolicyGuardResponse) obj; // req ID has form 00000001-0002-0003-0004-000000000005 - return Util.INDETERMINATE.equals(response.getResult()) - && response.getRequestID().toString().matches(REQ_MATCHER); + return status.equals(response.getResult()) && response.getRequestID().toString().matches(REQ_MATCHER); })); - } - } diff --git a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java index 867c05d2f..e69820a3d 100644 --- a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java +++ b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlHelperTest.java @@ -59,6 +59,8 @@ import org.onap.policy.drools.system.PolicyEngine; import org.onap.policy.drools.utils.logging.LoggerUtil; public class PolicyGuardXacmlHelperTest { + + private static final Integer VF_COUNT = 100; /** * Set up test class. @@ -88,7 +90,8 @@ public class PolicyGuardXacmlHelperTest { // Null/ Bad Connection Case PolicyGuardXacmlRequestAttributes xacmlReq = new PolicyGuardXacmlRequestAttributes( - org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, "actor", "recipe", "target", "requestId"); + org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, "actor", "recipe", "target", + "requestId", VF_COUNT); String rawDecision = new PolicyGuardXacmlHelper().callPDP(xacmlReq); assertNotNull(rawDecision); assertEquals(0, Util.INDETERMINATE.compareToIgnoreCase(rawDecision)); @@ -97,7 +100,7 @@ public class PolicyGuardXacmlHelperTest { @Test public void testSimulator() { PolicyGuardXacmlRequestAttributes request = new PolicyGuardXacmlRequestAttributes("clname_id", "actor_id", - "operation_id", "target_id", "request_id"); + "operation_id", "target_id", "request_id", VF_COUNT); String xacmlResponse = new PolicyGuardXacmlHelper().callPDP(request); assertNotNull(xacmlResponse); } @@ -110,13 +113,14 @@ public class PolicyGuardXacmlHelperTest { public void testCallPdp() { // Deny Case PolicyGuardXacmlRequestAttributes xacmlReq = new PolicyGuardXacmlRequestAttributes( - org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, "actor", "recipe", "target", "requestId"); + org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, "actor", "recipe", "target", + "requestId", VF_COUNT); String rawDecision = new PolicyGuardXacmlHelper().callPDP(xacmlReq); assertNotNull(rawDecision); assertTrue(0 == Util.DENY.compareToIgnoreCase(rawDecision)); // Permit Case - xacmlReq = new PolicyGuardXacmlRequestAttributes("clname", "actor", "recipe", "target", "requestId"); + xacmlReq = new PolicyGuardXacmlRequestAttributes("clname", "actor", "recipe", "target", "requestId", VF_COUNT); rawDecision = new PolicyGuardXacmlHelper().callPDP(xacmlReq); assertNotNull(rawDecision); assertEquals(0, Util.PERMIT.compareToIgnoreCase(rawDecision)); @@ -130,7 +134,8 @@ public class PolicyGuardXacmlHelperTest { */ public void testCallPdpExtra() { PolicyGuardXacmlRequestAttributes xacmlReq = new PolicyGuardXacmlRequestAttributes( - org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, "actor", "recipe", "target", "requestId"); + org.onap.policy.simulators.GuardSimulatorJaxRs.DENY_CLNAME, "actor", "recipe", "target", + "requestId", VF_COUNT); xacmlReq.setClnameID(null); String rawDecision = new PolicyGuardXacmlHelper().callPDP(xacmlReq); diff --git a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java index a61f5200b..7b5affd32 100644 --- a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java +++ b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardXacmlRequestAttributesTest.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright (C) 2018 Ericsson. All rights reserved. * ================================================================================ + * Modifications Copyright (C) 2018 AT&T. 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 @@ -31,35 +33,43 @@ public class PolicyGuardXacmlRequestAttributesTest { @Test public void policyGuardXacmlRequestAttributesTest() { - assertNotNull(new PolicyGuardXacmlRequestAttributes(null, null, null, null, null)); + PolicyGuardXacmlRequestAttributes attributes = + new PolicyGuardXacmlRequestAttributes(null, null, null, null, null, null); + assertNotNull(attributes); - UUID controlLoopId = UUID.randomUUID(); - UUID operationId = UUID.randomUUID(); UUID requestId = UUID.randomUUID(); - UUID actorId = UUID.randomUUID(); - UUID targetId = UUID.randomUUID(); - - PolicyGuardXacmlRequestAttributes attributes = new PolicyGuardXacmlRequestAttributes(controlLoopId.toString(), - actorId.toString(), operationId.toString(), targetId.toString(), requestId.toString()); - attributes.setRequestID(requestId.toString()); assertEquals(requestId.toString(), attributes.getRequestID()); + UUID operationId = UUID.randomUUID(); attributes.setOperationID(operationId.toString()); assertEquals(operationId.toString(), attributes.getOperationID()); + UUID actorId = UUID.randomUUID(); attributes.setActorID(actorId.toString()); assertEquals(actorId.toString(), attributes.getActorID()); + UUID targetId = UUID.randomUUID(); attributes.setTargetID(targetId.toString()); assertEquals(targetId.toString(), attributes.getTargetID()); attributes.setTargetID(targetId.toString()); assertEquals(targetId.toString(), attributes.getTargetID()); + UUID controlLoopId = UUID.randomUUID(); attributes.setClnameID(controlLoopId.toString()); assertEquals(controlLoopId.toString(), attributes.getClnameID()); + attributes.setClnameID(null); + assertEquals(null, attributes.getClnameID()); + + Integer vfCount = 20; + attributes.setVfCount(vfCount); + assertEquals(vfCount, attributes.getVfCount()); + + attributes.setVfCount(null); + assertEquals(null, attributes.getVfCount()); + assertEquals("PolicyGuardXacmlRequestAttributes [actorID=", attributes.toString().substring(0, 43)); } } diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl index 71715c075..248497292 100644 --- a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl @@ -32,6 +32,7 @@ import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager; import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS; import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager; import org.onap.policy.controlloop.actor.so.SOActorServiceProvider; +import org.onap.policy.aai.AaiNqResponseWrapper; import org.onap.policy.appc.Request; import org.onap.policy.appc.Response; import org.onap.policy.appc.CommonHeader; @@ -340,6 +341,10 @@ rule "${policyName}.EVENT.MANAGER" logger.info("{}: {}: abatement received for {}. Closing the control loop", $params.getClosedLoopControlName(), drools.getRule().getName(), $event.getRequestId()); + + /// DB Write---end event processing for this RequestId() + $manager.commitAbatement("Event Abated","Closed"); + notification.setFrom("policy"); notification.setPolicyName(drools.getRule().getName()); notification.setPolicyScope("${policyScope}"); @@ -678,8 +683,11 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED" $operation.policy.getActor().toString(), $operation.policy.getRecipe(), $operation.getTargetEntity(), - $event.getRequestId().toString() - )); + $event.getRequestId().toString(), + () -> { + AaiNqResponseWrapper resp = $manager.getNqVserverFromAai(); + return(resp == null ? null : resp.countVfModules()); + })); t.start(); } else{ diff --git a/controlloop/templates/archetype-cl-casablanca/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl b/controlloop/templates/archetype-cl-casablanca/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl index 24cb7f86a..0352dec10 100644 --- a/controlloop/templates/archetype-cl-casablanca/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl +++ b/controlloop/templates/archetype-cl-casablanca/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl @@ -33,6 +33,7 @@ import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager; import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS; import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager; import org.onap.policy.controlloop.actor.so.SOActorServiceProvider; +import org.onap.policy.aai.AaiNqResponseWrapper; import org.onap.policy.appc.Request; import org.onap.policy.appc.Response; import org.onap.policy.appc.CommonHeader; @@ -644,8 +645,11 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED" $operation.policy.getActor().toString(), $operation.policy.getRecipe(), $operation.getTargetEntity(), - $event.getRequestId().toString() - )); + $event.getRequestId().toString(), + () -> { + AaiNqResponseWrapper resp = $manager.getNqVserverFromAai(); + return(resp == null ? null : resp.countVfModules()); + })); t.start(); } else{ |