2  * Copyright 2016-2017, Nokia Corporation
 
   4  * Licensed under the Apache License, Version 2.0 (the "License");
 
   5  * you may not use this file except in compliance with the License.
 
   6  * You may obtain a copy of the License at
 
   8  *     http://www.apache.org/licenses/LICENSE-2.0
 
  10  * Unless required by applicable law or agreed to in writing, software
 
  11  * distributed under the License is distributed on an "AS IS" BASIS,
 
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  13  * See the License for the specific language governing permissions and
 
  14  * limitations under the License.
 
  16 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification;
 
  18 import com.google.gson.*;
 
  19 import com.nokia.cbam.lcm.v32.model.*;
 
  20 import java.util.ArrayList;
 
  21 import java.util.List;
 
  22 import java.util.NoSuchElementException;
 
  23 import java.util.Optional;
 
  24 import java.util.concurrent.*;
 
  25 import org.junit.Before;
 
  26 import org.junit.Test;
 
  27 import org.mockito.ArgumentCaptor;
 
  28 import org.mockito.InjectMocks;
 
  29 import org.mockito.Mockito;
 
  30 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager;
 
  31 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase;
 
  32 import org.threeten.bp.OffsetDateTime;
 
  34 import static java.util.Optional.empty;
 
  36 import static com.nokia.cbam.lcm.v32.model.OperationType.*;
 
  37 import static junit.framework.TestCase.*;
 
  38 import static org.mockito.Mockito.*;
 
  39 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
 
  40 import static org.springframework.test.util.ReflectionTestUtils.setField;
 
  42 public class TestLifecycleChangeNotificationManager extends TestBase {
 
  45     private LifecycleChangeNotificationManager lifecycleChangeNotificationManager;
 
  46     private VnfLifecycleChangeNotification recievedLcn = new VnfLifecycleChangeNotification();
 
  47     private List<OperationExecution> operationExecutions = new ArrayList<>();
 
  48     private OperationExecution instantiationOperation = new OperationExecution();
 
  49     private OperationExecution scaleOperation = new OperationExecution();
 
  50     private OperationExecution healOperation = new OperationExecution();
 
  51     private OperationExecution terminationOperation = new OperationExecution();
 
  53     private ArgumentCaptor<OperationExecution> currentOperationExecution = ArgumentCaptor.forClass(OperationExecution.class);
 
  54     private ArgumentCaptor<Optional> affectedConnectionPoints = ArgumentCaptor.forClass(Optional.class);
 
  56     private List<VnfInfo> vnfs = new ArrayList<>();
 
  57     private VnfInfo vnf = new VnfInfo();
 
  60     public void initMocks() throws Exception {
 
  61         setField(LifecycleChangeNotificationManager.class, "logger", logger);
 
  62         instantiationOperation.setId("instantiationOperationExecutionId");
 
  63         instantiationOperation.setStartTime(OffsetDateTime.now());
 
  64         instantiationOperation.setOperationType(OperationType.INSTANTIATE);
 
  65         scaleOperation.setId("scaleOperationExecutionId");
 
  66         scaleOperation.setStartTime(OffsetDateTime.now().plusDays(1));
 
  67         scaleOperation.setOperationType(OperationType.SCALE);
 
  68         terminationOperation.setId("terminationExecutionId");
 
  69         terminationOperation.setStartTime(OffsetDateTime.now().plusDays(1));
 
  70         terminationOperation.setOperationType(OperationType.TERMINATE);
 
  71         healOperation.setId("healOperaitonExecutionId");
 
  72         healOperation.setOperationType(OperationType.HEAL);
 
  73         recievedLcn.setLifecycleOperationOccurrenceId("instantiationOperationExecutionId");
 
  74         healOperation.setStartTime(OffsetDateTime.now().plusDays(1));
 
  75         recievedLcn.setVnfInstanceId(VNF_ID);
 
  76         when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(operationExecutions));
 
  77         prepOperation(instantiationOperation);
 
  78         prepOperation(scaleOperation);
 
  79         prepOperation(healOperation);
 
  80         prepOperation(terminationOperation);
 
  81         doNothing().when(notificationSender).processNotification(eq(recievedLcn), currentOperationExecution.capture(), affectedConnectionPoints.capture(), eq(VIM_ID));
 
  82         InstantiateVnfRequest instantiateVnfRequest = new InstantiateVnfRequest();
 
  83         VimInfo vimInfo = new VimInfo();
 
  84         vimInfo.setId(VIM_ID);
 
  85         instantiateVnfRequest.getVims().add(vimInfo);
 
  86         when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(new Gson().toJsonTree(instantiateVnfRequest)));
 
  87         when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnfs));
 
  90         VnfProperty prop = new VnfProperty();
 
  91         prop.setName(LifecycleManager.EXTERNAL_VNFM_ID);
 
  92         prop.setValue(VNFM_ID);
 
  93         vnf.setExtensions(new ArrayList<>());
 
  94         vnf.getExtensions().add(prop);
 
  95         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnf));
 
  98     private void prepOperation(OperationExecution operationExecution) {
 
  99         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
 
 100         operationExecution.setOperationParams(root);
 
 101         switch (operationExecution.getOperationType()) {
 
 103                 root.getAsJsonObject().addProperty("terminationType", "GRACEFULL");
 
 105         when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(operationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(operationExecution));
 
 106         operationExecutions.add(operationExecution);
 
 109     private void addEmptyModifiedConnectionPoints(OperationExecution operationExecution) {
 
 110         OperationResult operationResult = new OperationResult();
 
 111         operationResult.operationResult = new ReportedAffectedConnectionPoints();
 
 112         JsonElement additionalData = new Gson().toJsonTree(operationResult);
 
 113         operationExecution.setAdditionalData(additionalData);
 
 117      * The first instantiation before the current operation is selected
 
 120     public void testLastInstantiationSelection() {
 
 121         List<OperationExecution> operations = new ArrayList<>();
 
 123         OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE);
 
 124         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
 
 125         OperationExecution operationClosestInstantiate = buildOperation(OffsetDateTime.now().minusDays(2), INSTANTIATE);
 
 126         OperationExecution operationFurthers = buildOperation(OffsetDateTime.now().minusDays(3), INSTANTIATE);
 
 128         operations.add(operation);
 
 129         operations.add(operationScale);
 
 130         operations.add(operationClosestInstantiate);
 
 131         operations.add(operationFurthers);
 
 132         assertEquals(operationClosestInstantiate, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation));
 
 136      * The instantiation operation itself is valid as the last instantiation operation
 
 139     public void testInstantiationSufficesTheLastInstantiation() {
 
 140         OffsetDateTime baseTime = OffsetDateTime.now();
 
 141         List<OperationExecution> operations = new ArrayList<>();
 
 143         OperationExecution operation = buildOperation(OffsetDateTime.now(), INSTANTIATE);
 
 144         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
 
 145         OperationExecution operationFurthers = buildOperation(OffsetDateTime.now().minusDays(2), INSTANTIATE);
 
 147         operations.add(operation);
 
 148         operations.add(operationScale);
 
 149         operations.add(operationFurthers);
 
 150         assertEquals(operation, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation));
 
 154      * If no instantiation operation is found for before the selected operation
 
 157     public void testNoInstantiation() {
 
 158         OffsetDateTime baseTime = OffsetDateTime.now();
 
 159         List<OperationExecution> operations = new ArrayList<>();
 
 161         OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE);
 
 162         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
 
 164         operations.add(operation);
 
 165         operations.add(operationScale);
 
 167             LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation);
 
 169         } catch (NoSuchElementException e) {
 
 175      * the operations are ordered from newest (first) to oldest (last)
 
 178     public void testOperationOrdering() {
 
 179         List<OperationExecution> operationExecutions = new ArrayList<>();
 
 180         OperationExecution before = buildOperation(OffsetDateTime.now(), OperationType.INSTANTIATE);
 
 181         operationExecutions.add(before);
 
 182         OperationExecution after = buildOperation(OffsetDateTime.now().plusDays(1), OperationType.SCALE);
 
 183         operationExecutions.add(after);
 
 184         List<OperationExecution> sorted1 = LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions);
 
 185         assertEquals(after, sorted1.get(0));
 
 186         assertEquals(before, sorted1.get(1));
 
 190      * if VNF listing fails the processing of the notifications is aborted
 
 193     public void testUnableToListVnfs() throws Exception {
 
 194         RuntimeException expectedException = new RuntimeException();
 
 195         when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
 
 198             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 200         } catch (Exception e) {
 
 201             assertEquals(expectedException, e.getCause());
 
 202             verify(logger).error("Unable to list VNFs / query VNF", expectedException);
 
 207      * if VNF query fails the processing of the notifications is aborted
 
 210     public void testUnableToQueryVnf() throws Exception {
 
 211         RuntimeException expectedException = new RuntimeException();
 
 212         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
 
 215             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 217         } catch (Exception e) {
 
 218             assertEquals(expectedException, e.getCause());
 
 219             verify(logger).error("Unable to list VNFs / query VNF", expectedException);
 
 224      * if the VNF is not managed by this VNFM the LCN is dropped
 
 227     public void testNonManagedVnf() throws Exception {
 
 228         vnf.getExtensions().clear();
 
 230         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 232         Mockito.verifyZeroInteractions(operationExecutionApi);
 
 233         verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed VNF");
 
 237      * LCN is not logged in case of non info log level
 
 240     public void testNoLogging() throws Exception {
 
 241         vnf.getExtensions().clear();
 
 242         when(logger.isInfoEnabled()).thenReturn(false);
 
 244         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 246         verify(logger, never()).info(eq("Received LCN: {}"), anyString());
 
 250      * if the VNF is not managed by this VNFM the LCN is dropped
 
 253     public void testManagedByOtherVnf() throws Exception {
 
 254         vnf.getExtensions().get(0).setValue("unknownVnfmId");
 
 256         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 258         Mockito.verifyZeroInteractions(operationExecutionApi);
 
 259         verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed by the VNFM with id unknownVnfmId");
 
 263      * if the VNF disappeared before processing the LCN
 
 266     public void testDisappearedVnf() throws Exception {
 
 269         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 271         Mockito.verifyZeroInteractions(operationExecutionApi);
 
 272         verify(logger).warn("The VNF with " + VNF_ID + " identifier disappeared before being able to process the LCN");
 
 276      * if the operation parameters of the last instantiation is non querieable error is propagated
 
 279     public void testUnableToQueryOperationParams() throws Exception {
 
 280         recievedLcn.setOperation(OperationType.TERMINATE);
 
 281         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 282         RuntimeException expectedException = new RuntimeException();
 
 283         when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
 
 286             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 288         } catch (Exception e) {
 
 290             Mockito.verifyZeroInteractions(nsLcmApi);
 
 291             assertEquals(expectedException, e.getCause());
 
 292             verify(logger).error("Unable to detect last instantiation operation", e.getCause());
 
 297      * if unable to query all operation executions from CBAM the error is propagated
 
 300     public void testUnableToQueryCurrentOperations() throws Exception {
 
 301         recievedLcn.setOperation(OperationType.TERMINATE);
 
 302         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 303         RuntimeException expectedException = new RuntimeException();
 
 304         when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
 
 307             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 309         } catch (Exception e) {
 
 311             assertEquals(expectedException, e.getCause());
 
 312             verify(logger).error("Unable to retrieve the operation executions for the VNF myVnfId", e.getCause());
 
 317      * if unable to query the given operation execution from CBAM the error is propagated
 
 320     public void testUnableToQueryCurrentOperation() throws Exception {
 
 321         recievedLcn.setOperation(OperationType.TERMINATE);
 
 322         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 323         RuntimeException expectedException = new RuntimeException();
 
 324         when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(recievedLcn.getLifecycleOperationOccurrenceId(), NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
 
 327             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 329         } catch (Exception e) {
 
 331             assertEquals(expectedException, e.getCause());
 
 332             verify(logger).error("Unable to retrieve the operation execution with instantiationOperationExecutionId identifier", e.getCause());
 
 337      * test that waitForTerminationToBeProcessed outwaits the successfull processing of the termination notification
 
 340     public void testWaitForTermination() throws Exception {
 
 342         //add an non processed notification
 
 343         VnfLifecycleChangeNotification nonProcessedEvent = new VnfLifecycleChangeNotification();
 
 344         nonProcessedEvent.setStatus(OperationStatus.FINISHED);
 
 345         nonProcessedEvent.setOperation(OperationType.TERMINATE);
 
 346         OperationExecution secondTerminationOperationExecution = new OperationExecution();
 
 347         secondTerminationOperationExecution.setOperationType(OperationType.TERMINATE);
 
 348         secondTerminationOperationExecution.setId("secondId");
 
 349         secondTerminationOperationExecution.setOperationParams(buildTerminationParams());
 
 350         nonProcessedEvent.setLifecycleOperationOccurrenceId(secondTerminationOperationExecution.getId());
 
 351         lifecycleChangeNotificationManager.handleLcn(nonProcessedEvent);
 
 352         addEmptyModifiedConnectionPoints(terminationOperation);
 
 353         //add second termination
 
 354         recievedLcn.setOperation(OperationType.TERMINATE);
 
 355         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 356         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
 
 357         ExecutorService executorService = Executors.newCachedThreadPool();
 
 358         Future<Boolean> waitExitedWithSuccess = executorService.submit(new Callable<Boolean>() {
 
 360             public Boolean call() throws Exception {
 
 362                     lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
 
 364                 } catch (Exception e) {
 
 370         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 372         assertTrue(waitExitedWithSuccess.get());
 
 376      * the processing of the start notification does not trigger the deletion of the VNF
 
 379     public void testStartLcnForTerminate() throws Exception {
 
 380         recievedLcn.setOperation(OperationType.TERMINATE);
 
 381         recievedLcn.setStatus(OperationStatus.STARTED);
 
 382         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
 
 383         ExecutorService executorService = Executors.newCachedThreadPool();
 
 384         Future<Boolean> waitExitedWithSuccess = executorService.submit(() -> {
 
 386                 lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
 
 388             } catch (Exception e) {
 
 392         //processing the start notification
 
 393         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 396             waitExitedWithSuccess.get(10, TimeUnit.MILLISECONDS);
 
 398         } catch (Exception e) {
 
 400         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 402         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 404         assertTrue(waitExitedWithSuccess.get());
 
 405         assertEquals(empty(), affectedConnectionPoints.getValue());
 
 409      * Forceful termination results in an empty affected connection points
 
 412     public void testMissingPreResultForForcefullTermination() {
 
 414         recievedLcn.setOperation(OperationType.INSTANTIATE);
 
 415         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 416         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
 
 417         JsonObject additionalData = new JsonObject();
 
 418         additionalData.add("operationResult", new JsonObject());
 
 419         ((JsonObject) terminationOperation.getOperationParams()).addProperty("terminationType", "FORCEFUL");
 
 420         terminationOperation.setAdditionalData(additionalData);
 
 421         terminationOperation.setStatus(OperationStatus.FINISHED);
 
 422         terminationOperation.setOperationType(OperationType.TERMINATE);
 
 424         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 425         assertFalse(affectedConnectionPoints.getValue().isPresent());
 
 426         verify(logger).warn("Unable to send information related to affected connection points during forceful termination");
 
 430      * Failures in affected connection point processing are tolerated for failed operation
 
 431      * (because the POST script was not able to run)
 
 434     public void testFailedOperations() throws Exception {
 
 436         recievedLcn.setOperation(OperationType.INSTANTIATE);
 
 437         recievedLcn.setStatus(OperationStatus.FAILED);
 
 438         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
 
 439         instantiationOperation.setAdditionalData(null);
 
 440         instantiationOperation.setStatus(OperationStatus.FAILED);
 
 442         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 444         assertFalse(affectedConnectionPoints.getValue().isPresent());
 
 445         verify(logger).warn("The operation failed and the affected connection points were not reported");
 
 450      * affected connection points are passed to the actual notification processor
 
 453     public void testAffectedConnectionPointProcessing() throws Exception {
 
 455         recievedLcn.setOperation(OperationType.INSTANTIATE);
 
 456         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 457         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
 
 458         instantiationOperation.setStatus(OperationStatus.FAILED);
 
 459         addEmptyModifiedConnectionPoints(instantiationOperation);
 
 460         OperationResult operationResult = new OperationResult();
 
 461         ReportedAffectedConnectionPoints affectedCp = new ReportedAffectedConnectionPoints();
 
 462         ReportedAffectedCp cp = new ReportedAffectedCp();
 
 464         affectedCp.getPost().add(cp);
 
 465         operationResult.operationResult = affectedCp;
 
 466         instantiationOperation.setAdditionalData(new Gson().toJsonTree(operationResult));
 
 469         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 471         assertTrue(affectedConnectionPoints.getValue().isPresent());
 
 472         ReportedAffectedConnectionPoints actualCps = new Gson().fromJson(new Gson().toJsonTree(affectedConnectionPoints.getValue().get()), ReportedAffectedConnectionPoints.class);
 
 473         assertEquals(1, actualCps.getPost().size());
 
 477      * Failures in affected connection point processing are tolerated for failed operation
 
 478      * (because the POST script was not able to run)
 
 481     public void testMissingOperationResult() throws Exception {
 
 483         recievedLcn.setOperation(OperationType.INSTANTIATE);
 
 484         recievedLcn.setStatus(OperationStatus.FAILED);
 
 485         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
 
 486         instantiationOperation.setStatus(OperationStatus.FAILED);
 
 487         addEmptyModifiedConnectionPoints(instantiationOperation);
 
 488         JsonObject additionalData = (JsonObject) instantiationOperation.getAdditionalData();
 
 489         additionalData.remove("operationResult");
 
 491         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 493         assertFalse(affectedConnectionPoints.getValue().isPresent());
 
 494         verify(logger).warn("The operation failed and the affected connection points were not reported");
 
 498      * test end notification scenario for failed scale-out
 
 499      * - LCN is sent to VF-C, but the
 
 502     public void testMissingPreResultForFailedOperation() {
 
 504         recievedLcn.setOperation(OperationType.SCALE);
 
 505         recievedLcn.setStatus(OperationStatus.FAILED);
 
 506         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
 
 507         ScaleVnfRequest request = new ScaleVnfRequest();
 
 508         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
 
 509         request.setType(ScaleDirection.OUT);
 
 510         scaleOperation.setOperationParams(request);
 
 511         scaleOperation.setAdditionalData(null);
 
 512         scaleOperation.setStatus(OperationStatus.FAILED);
 
 513         scaleOperation.setOperationType(OperationType.SCALE);
 
 515         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 516         assertFalse(affectedConnectionPoints.getValue().isPresent());
 
 517         verify(logger).warn("The operation failed and the affected connection points were not reported");
 
 521      * if the cbam_post is missing error handling should be applied
 
 524     public void testMissingPostResultForFailedOperation() {
 
 526         recievedLcn.setOperation(OperationType.SCALE);
 
 527         recievedLcn.setStatus(OperationStatus.FAILED);
 
 528         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
 
 529         ScaleVnfRequest request = new ScaleVnfRequest();
 
 530         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
 
 531         request.setType(ScaleDirection.OUT);
 
 532         scaleOperation.setOperationParams(request);
 
 533         scaleOperation.setStatus(OperationStatus.FAILED);
 
 534         addEmptyModifiedConnectionPoints(scaleOperation);
 
 535         ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject().remove("cbam_post");
 
 536         scaleOperation.setOperationType(OperationType.SCALE);
 
 539         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 540         assertFalse(affectedConnectionPoints.getValue().isPresent());
 
 541         verify(logger).warn("The operation failed and the affected connection points were not reported");
 
 545      * if invalid type is specified for cbam_post error handling should be applied
 
 548     public void testInvalidPost() {
 
 550         recievedLcn.setOperation(OperationType.SCALE);
 
 551         recievedLcn.setStatus(OperationStatus.FAILED);
 
 552         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
 
 553         ScaleVnfRequest request = new ScaleVnfRequest();
 
 554         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
 
 555         request.setType(ScaleDirection.OUT);
 
 556         scaleOperation.setOperationParams(request);
 
 557         scaleOperation.setStatus(OperationStatus.FAILED);
 
 558         addEmptyModifiedConnectionPoints(scaleOperation);
 
 559         JsonObject operationResult = ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject();
 
 560         operationResult.remove("cbam_post");
 
 561         operationResult.addProperty("cbam_post", "");
 
 562         scaleOperation.setOperationType(OperationType.SCALE);
 
 564         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 565         assertFalse(affectedConnectionPoints.getValue().isPresent());
 
 566         verify(logger).warn("The operation failed and the affected connection points were not reported");
 
 571      * test end notification success scenario for scale-out
 
 572      * - LCN is sent to VF-C
 
 575     public void testMissingPreResult() {
 
 577         recievedLcn.setOperation(OperationType.SCALE);
 
 578         recievedLcn.setStatus(OperationStatus.FINISHED);
 
 579         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
 
 580         ScaleVnfRequest request = new ScaleVnfRequest();
 
 581         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
 
 582         request.setType(ScaleDirection.OUT);
 
 583         scaleOperation.setOperationParams(request);
 
 584         JsonObject additionalData = new JsonObject();
 
 585         additionalData.add("operationResult", new JsonObject());
 
 586         scaleOperation.setAdditionalData(additionalData);
 
 587         scaleOperation.setStatus(OperationStatus.FINISHED);
 
 588         scaleOperation.setOperationType(OperationType.SCALE);
 
 589         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
 
 590         JsonObject operationParams = new JsonObject();
 
 593             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
 
 595         } catch (Exception e) {
 
 596             assertEquals("All operations must return the { \"operationResult\" : { \"cbam_pre\" : [<fillMeOut>], \"cbam_post\" : [<fillMeOut>] } } structure", e.getMessage());
 
 600     private JsonObject buildTerminationParams() {
 
 601         JsonObject root = new JsonObject();
 
 602         root.add("terminationType", new JsonPrimitive("GRACEFULL"));
 
 606     private OperationExecution buildOperation(OffsetDateTime baseTime, OperationType operationType) {
 
 607         OperationExecution operation = new OperationExecution();
 
 608         operation.setStartTime(baseTime);
 
 609         operation.setOperationType(operationType);
 
 613     class OperationResult {
 
 614         ReportedAffectedConnectionPoints operationResult;