449217f9e55b31768960db34650ce139b692d6c8
[vfc/nfvo/driver/vnfm/svnfm.git] /
1 /*
2  * Copyright 2016-2017, Nokia Corporation
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification;
17
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;
33
34 import static java.util.Optional.empty;
35
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;
41
42 public class TestLifecycleChangeNotificationManager extends TestBase {
43
44     @InjectMocks
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();
52
53     private ArgumentCaptor<OperationExecution> currentOperationExecution = ArgumentCaptor.forClass(OperationExecution.class);
54     private ArgumentCaptor<Optional> affectedConnectionPoints = ArgumentCaptor.forClass(Optional.class);
55
56     private List<VnfInfo> vnfs = new ArrayList<>();
57     private VnfInfo vnf = new VnfInfo();
58
59     @Before
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));
88         vnfs.add(vnf);
89         vnf.setId(VNF_ID);
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));
96     }
97
98     private void prepOperation(OperationExecution operationExecution) {
99         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
100         operationExecution.setOperationParams(root);
101         switch (operationExecution.getOperationType()) {
102             case TERMINATE:
103                 root.getAsJsonObject().addProperty("terminationType", "GRACEFULL");
104         }
105         when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(operationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(operationExecution));
106         operationExecutions.add(operationExecution);
107     }
108
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);
114     }
115
116     /**
117      * The first instantiation before the current operation is selected
118      */
119     @Test
120     public void testLastInstantiationSelection() {
121         List<OperationExecution> operations = new ArrayList<>();
122
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);
127
128         operations.add(operation);
129         operations.add(operationScale);
130         operations.add(operationClosestInstantiate);
131         operations.add(operationFurthers);
132         assertEquals(operationClosestInstantiate, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation));
133     }
134
135     /**
136      * The instantiation operation itself is valid as the last instantiation operation
137      */
138     @Test
139     public void testInstantiationSufficesTheLastInstantiation() {
140         OffsetDateTime baseTime = OffsetDateTime.now();
141         List<OperationExecution> operations = new ArrayList<>();
142
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);
146
147         operations.add(operation);
148         operations.add(operationScale);
149         operations.add(operationFurthers);
150         assertEquals(operation, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation));
151     }
152
153     /**
154      * If no instantiation operation is found for before the selected operation
155      */
156     @Test
157     public void testNoInstantiation() {
158         OffsetDateTime baseTime = OffsetDateTime.now();
159         List<OperationExecution> operations = new ArrayList<>();
160
161         OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE);
162         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
163
164         operations.add(operation);
165         operations.add(operationScale);
166         try {
167             LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation);
168             fail();
169         } catch (NoSuchElementException e) {
170
171         }
172     }
173
174     /**
175      * the operations are ordered from newest (first) to oldest (last)
176      */
177     @Test
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));
187     }
188
189     /**
190      * if VNF listing fails the processing of the notifications is aborted
191      */
192     @Test
193     public void testUnableToListVnfs() throws Exception {
194         RuntimeException expectedException = new RuntimeException();
195         when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
196         //when
197         try {
198             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
199             fail();
200         } catch (Exception e) {
201             assertEquals(expectedException, e.getCause());
202             verify(logger).error("Unable to list VNFs / query VNF", expectedException);
203         }
204     }
205
206     /**
207      * if VNF query fails the processing of the notifications is aborted
208      */
209     @Test
210     public void testUnableToQueryVnf() throws Exception {
211         RuntimeException expectedException = new RuntimeException();
212         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
213         //when
214         try {
215             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
216             fail();
217         } catch (Exception e) {
218             assertEquals(expectedException, e.getCause());
219             verify(logger).error("Unable to list VNFs / query VNF", expectedException);
220         }
221     }
222
223     /**
224      * if the VNF is not managed by this VNFM the LCN is dropped
225      */
226     @Test
227     public void testNonManagedVnf() throws Exception {
228         vnf.getExtensions().clear();
229         //when
230         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
231         //verify
232         Mockito.verifyZeroInteractions(operationExecutionApi);
233         verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed VNF");
234     }
235
236     /**
237      * LCN is not logged in case of non info log level
238      */
239     @Test
240     public void testNoLogging() throws Exception {
241         vnf.getExtensions().clear();
242         when(logger.isInfoEnabled()).thenReturn(false);
243         //when
244         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
245         //verify
246         verify(logger, never()).info(eq("Received LCN: {}"), anyString());
247     }
248
249     /**
250      * if the VNF is not managed by this VNFM the LCN is dropped
251      */
252     @Test
253     public void testManagedByOtherVnf() throws Exception {
254         vnf.getExtensions().get(0).setValue("unknownVnfmId");
255         //when
256         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
257         //verify
258         Mockito.verifyZeroInteractions(operationExecutionApi);
259         verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed by the VNFM with id unknownVnfmId");
260     }
261
262     /**
263      * if the VNF disappeared before processing the LCN
264      */
265     @Test
266     public void testDisappearedVnf() throws Exception {
267         vnfs.clear();
268         //when
269         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
270         //verify
271         Mockito.verifyZeroInteractions(operationExecutionApi);
272         verify(logger).warn("The VNF with " + VNF_ID + " identifier disappeared before being able to process the LCN");
273     }
274
275     /**
276      * if the operation parameters of the last instantiation is non querieable error is propagated
277      */
278     @Test
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);
284         //when
285         try {
286             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
287             fail();
288         } catch (Exception e) {
289             //verify
290             Mockito.verifyZeroInteractions(nsLcmApi);
291             assertEquals(expectedException, e.getCause());
292             verify(logger).error("Unable to detect last instantiation operation", e.getCause());
293         }
294     }
295
296     /**
297      * if unable to query all operation executions from CBAM the error is propagated
298      */
299     @Test
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);
305         //when
306         try {
307             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
308             fail();
309         } catch (Exception e) {
310             //verify
311             assertEquals(expectedException, e.getCause());
312             verify(logger).error("Unable to retrieve the operation executions for the VNF myVnfId", e.getCause());
313         }
314     }
315
316     /**
317      * if unable to query the given operation execution from CBAM the error is propagated
318      */
319     @Test
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);
325         //when
326         try {
327             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
328             fail();
329         } catch (Exception e) {
330             //verify
331             assertEquals(expectedException, e.getCause());
332             verify(logger).error("Unable to retrieve the operation execution with instantiationOperationExecutionId identifier", e.getCause());
333         }
334     }
335
336     /**
337      * test that waitForTerminationToBeProcessed outwaits the successfull processing of the termination notification
338      */
339     @Test
340     public void testWaitForTermination() throws Exception {
341         //given
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>() {
359             @Override
360             public Boolean call() throws Exception {
361                 try {
362                     lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
363                     return true;
364                 } catch (Exception e) {
365                     return false;
366                 }
367             }
368         });
369         //when
370         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
371         //verify
372         assertTrue(waitExitedWithSuccess.get());
373     }
374
375     /**
376      * the processing of the start notification does not trigger the deletion of the VNF
377      */
378     @Test
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(() -> {
385             try {
386                 lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
387                 return true;
388             } catch (Exception e) {
389                 return false;
390             }
391         });
392         //processing the start notification
393         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
394         //verify
395         try {
396             waitExitedWithSuccess.get(10, TimeUnit.MILLISECONDS);
397             fail();
398         } catch (Exception e) {
399         }
400         recievedLcn.setStatus(OperationStatus.FINISHED);
401         //when
402         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
403         //verify
404         assertTrue(waitExitedWithSuccess.get());
405         assertEquals(empty(), affectedConnectionPoints.getValue());
406     }
407
408     /**
409      * Forceful termination results in an empty affected connection points
410      */
411     @Test
412     public void testMissingPreResultForForcefullTermination() {
413         //given
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);
423         //when
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");
427     }
428
429     /**
430      * Forceful termination results in an empty affected connection points
431      */
432     @Test
433     public void testGracefullTermination() {
434         //given
435         recievedLcn.setOperation(OperationType.INSTANTIATE);
436         recievedLcn.setStatus(OperationStatus.FINISHED);
437         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
438         ((JsonObject) terminationOperation.getOperationParams()).addProperty("terminationType", "GRACEFUL");
439         addEmptyModifiedConnectionPoints(terminationOperation);
440         terminationOperation.setStatus(OperationStatus.FINISHED);
441         terminationOperation.setOperationType(OperationType.TERMINATE);
442         //when
443         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
444         assertTrue(affectedConnectionPoints.getValue().isPresent());
445     }
446
447     /**
448      * Failures in affected connection point processing are tolerated for failed operation
449      * (because the POST script was not able to run)
450      */
451     @Test
452     public void testFailedOperations() throws Exception {
453         //given
454         recievedLcn.setOperation(OperationType.INSTANTIATE);
455         recievedLcn.setStatus(OperationStatus.FAILED);
456         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
457         instantiationOperation.setAdditionalData(null);
458         instantiationOperation.setStatus(OperationStatus.FAILED);
459         //when
460         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
461         //verify
462         assertFalse(affectedConnectionPoints.getValue().isPresent());
463         verify(logger).warn("The operation failed and the affected connection points were not reported");
464     }
465
466
467     /**
468      * affected connection points are passed to the actual notification processor
469      */
470     @Test
471     public void testAffectedConnectionPointProcessing() throws Exception {
472         //given
473         recievedLcn.setOperation(OperationType.INSTANTIATE);
474         recievedLcn.setStatus(OperationStatus.FINISHED);
475         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
476         instantiationOperation.setStatus(OperationStatus.FAILED);
477         addEmptyModifiedConnectionPoints(instantiationOperation);
478         OperationResult operationResult = new OperationResult();
479         ReportedAffectedConnectionPoints affectedCp = new ReportedAffectedConnectionPoints();
480         ReportedAffectedCp cp = new ReportedAffectedCp();
481         cp.setCpId("cpId");
482         affectedCp.getPost().add(cp);
483         operationResult.operationResult = affectedCp;
484         instantiationOperation.setAdditionalData(new Gson().toJsonTree(operationResult));
485
486         //when
487         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
488         //verify
489         assertTrue(affectedConnectionPoints.getValue().isPresent());
490         ReportedAffectedConnectionPoints actualCps = new Gson().fromJson(new Gson().toJsonTree(affectedConnectionPoints.getValue().get()), ReportedAffectedConnectionPoints.class);
491         assertEquals(1, actualCps.getPost().size());
492     }
493
494     /**
495      * Failures in affected connection point processing are tolerated for failed operation
496      * (because the POST script was not able to run)
497      */
498     @Test
499     public void testMissingOperationResult() throws Exception {
500         //given
501         recievedLcn.setOperation(OperationType.INSTANTIATE);
502         recievedLcn.setStatus(OperationStatus.FAILED);
503         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
504         instantiationOperation.setStatus(OperationStatus.FAILED);
505         addEmptyModifiedConnectionPoints(instantiationOperation);
506         JsonObject additionalData = (JsonObject) instantiationOperation.getAdditionalData();
507         additionalData.remove("operationResult");
508         //when
509         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
510         //verify
511         assertFalse(affectedConnectionPoints.getValue().isPresent());
512         verify(logger).warn("The operation failed and the affected connection points were not reported");
513     }
514
515     /**
516      * test end notification scenario for failed scale-out
517      * - LCN is sent to VF-C, but the
518      */
519     @Test
520     public void testMissingPreResultForFailedOperation() {
521         //given
522         recievedLcn.setOperation(OperationType.SCALE);
523         recievedLcn.setStatus(OperationStatus.FAILED);
524         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
525         ScaleVnfRequest request = new ScaleVnfRequest();
526         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
527         request.setType(ScaleDirection.OUT);
528         scaleOperation.setOperationParams(request);
529         scaleOperation.setAdditionalData(null);
530         scaleOperation.setStatus(OperationStatus.FAILED);
531         scaleOperation.setOperationType(OperationType.SCALE);
532         //when
533         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
534         assertFalse(affectedConnectionPoints.getValue().isPresent());
535         verify(logger).warn("The operation failed and the affected connection points were not reported");
536     }
537
538     /**
539      * if the cbam_post is missing error handling should be applied
540      */
541     @Test
542     public void testMissingPostResultForFailedOperation() {
543         //given
544         recievedLcn.setOperation(OperationType.SCALE);
545         recievedLcn.setStatus(OperationStatus.FAILED);
546         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
547         ScaleVnfRequest request = new ScaleVnfRequest();
548         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
549         request.setType(ScaleDirection.OUT);
550         scaleOperation.setOperationParams(request);
551         scaleOperation.setStatus(OperationStatus.FAILED);
552         addEmptyModifiedConnectionPoints(scaleOperation);
553         ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject().remove("cbam_post");
554         scaleOperation.setOperationType(OperationType.SCALE);
555
556         //when
557         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
558         assertFalse(affectedConnectionPoints.getValue().isPresent());
559         verify(logger).warn("The operation failed and the affected connection points were not reported");
560     }
561
562     /**
563      * if invalid type is specified for cbam_post error handling should be applied
564      */
565     @Test
566     public void testInvalidPost() {
567         //given
568         recievedLcn.setOperation(OperationType.SCALE);
569         recievedLcn.setStatus(OperationStatus.FAILED);
570         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
571         ScaleVnfRequest request = new ScaleVnfRequest();
572         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
573         request.setType(ScaleDirection.OUT);
574         scaleOperation.setOperationParams(request);
575         scaleOperation.setStatus(OperationStatus.FAILED);
576         addEmptyModifiedConnectionPoints(scaleOperation);
577         JsonObject operationResult = ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject();
578         operationResult.remove("cbam_post");
579         operationResult.addProperty("cbam_post", "");
580         scaleOperation.setOperationType(OperationType.SCALE);
581         //when
582         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
583         assertFalse(affectedConnectionPoints.getValue().isPresent());
584         verify(logger).warn("The operation failed and the affected connection points were not reported");
585     }
586
587
588     /**
589      * test end notification success scenario for scale-out
590      * - LCN is sent to VF-C
591      */
592     @Test
593     public void testMissingPreResult() {
594         //given
595         recievedLcn.setOperation(OperationType.SCALE);
596         recievedLcn.setStatus(OperationStatus.FINISHED);
597         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
598         ScaleVnfRequest request = new ScaleVnfRequest();
599         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
600         request.setType(ScaleDirection.OUT);
601         scaleOperation.setOperationParams(request);
602         JsonObject additionalData = new JsonObject();
603         additionalData.add("operationResult", new JsonObject());
604         scaleOperation.setAdditionalData(additionalData);
605         scaleOperation.setStatus(OperationStatus.FINISHED);
606         scaleOperation.setOperationType(OperationType.SCALE);
607         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
608         JsonObject operationParams = new JsonObject();
609         //when
610         try {
611             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
612             fail();
613         } catch (Exception e) {
614             assertEquals("All operations must return the { \"operationResult\" : { \"cbam_pre\" : [<fillMeOut>], \"cbam_post\" : [<fillMeOut>] } } structure", e.getMessage());
615         }
616     }
617
618     private JsonObject buildTerminationParams() {
619         JsonObject root = new JsonObject();
620         root.add("terminationType", new JsonPrimitive("GRACEFULL"));
621         return root;
622     }
623
624     private OperationExecution buildOperation(OffsetDateTime baseTime, OperationType operationType) {
625         OperationExecution operation = new OperationExecution();
626         operation.setStartTime(baseTime);
627         operation.setOperationType(operationType);
628         return operation;
629     }
630
631     class OperationResult {
632         ReportedAffectedConnectionPoints operationResult;
633     }
634
635 }