Merge "remove sub process error handling that silent successes"
[so.git] / adapters / etsi-sol003-adapter / etsi-sol003-lcm / etsi-sol003-lcm-adapter / src / main / java / org / onap / so / adapters / etsisol003adapter / lcm / notificationhandling / NotificationHandler.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.adapters.etsisol003adapter.lcm.notificationhandling;
22
23 import static org.slf4j.LoggerFactory.getLogger;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import org.json.JSONException;
28 import org.json.JSONObject;
29 import org.onap.aai.domain.yang.GenericVnf;
30 import org.onap.aai.domain.yang.Relationship;
31 import org.onap.aai.domain.yang.Vserver;
32 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.aai.AaiHelper;
33 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.aai.AaiServiceProvider;
34 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.aai.OamIpAddressSource;
35 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.aai.OamIpAddressSource.OamIpAddressType;
36 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.vnfm.VnfmServiceProvider;
37 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.vnfm.model.InlineResponse201;
38 import org.onap.so.adapters.etsisol003adapter.lcm.extclients.vnfm.model.InlineResponse201VimConnectionInfo;
39 import org.onap.so.adapters.etsisol003adapter.lcm.jobmanagement.JobManager;
40 import org.onap.so.adapters.etsisol003adapter.lcm.lcn.model.LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs;
41 import org.onap.so.adapters.etsisol003adapter.lcm.lcn.model.LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs.ChangeTypeEnum;
42 import org.onap.so.adapters.etsisol003adapter.lcm.lcn.model.VnfLcmOperationOccurrenceNotification;
43 import org.onap.so.adapters.etsisol003adapter.lcm.lcn.model.VnfLcmOperationOccurrenceNotification.OperationStateEnum;
44 import org.slf4j.Logger;
45
46 /**
47  * Performs updates to AAI based on a received notification. The updates are executed in a separate thread so as the
48  * notification response to the VNFM is not delayed.
49  */
50 public class NotificationHandler implements Runnable {
51     private static Logger logger = getLogger(NotificationHandler.class);
52     private final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification;
53     private final AaiHelper aaiHelper;
54     private final AaiServiceProvider aaiServiceProvider;
55     private final VnfmServiceProvider vnfmServiceProvider;
56     private final JobManager jobManager;
57     private final InlineResponse201 vnfInstance;
58
59     public NotificationHandler(final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification,
60             final AaiHelper aaiHelper, final AaiServiceProvider aaiServiceProvider,
61             final VnfmServiceProvider vnfmServiceProvider, final JobManager jobManager,
62             final InlineResponse201 vnfInstance) {
63         this.vnfLcmOperationOccurrenceNotification = vnfLcmOperationOccurrenceNotification;
64         this.aaiHelper = aaiHelper;
65         this.aaiServiceProvider = aaiServiceProvider;
66         this.vnfmServiceProvider = vnfmServiceProvider;
67         this.jobManager = jobManager;
68         this.vnfInstance = vnfInstance;
69     }
70
71     @Override
72     public void run() {
73         try {
74             if (vnfLcmOperationOccurrenceNotification.getOperationState().equals(OperationStateEnum.COMPLETED)) {
75                 switch (vnfLcmOperationOccurrenceNotification.getOperation()) {
76                     case INSTANTIATE:
77                         handleVnfInstantiate();
78                         break;
79                     case TERMINATE:
80                         handleVnfTerminate();
81                         break;
82                     default:
83                 }
84             }
85         } catch (final Exception exception) {
86             logger.error("Error encountered handling notification, AAI may not be updated correctly "
87                     + vnfLcmOperationOccurrenceNotification, exception);
88         }
89     }
90
91     private void handleVnfInstantiate() {
92         if (vnfLcmOperationOccurrenceNotification.getOperationState().equals(OperationStateEnum.COMPLETED)) {
93             handleVnfInstantiateCompleted();
94         }
95     }
96
97     private void handleVnfInstantiateCompleted() {
98         final GenericVnf genericVnf = aaiServiceProvider
99                 .invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).getGenericVnf().get(0);
100
101         final GenericVnf genericVnfPatch = new GenericVnf();
102         genericVnfPatch.setVnfId(genericVnf.getVnfId());
103         setOamIpAddress(genericVnfPatch, vnfInstance);
104         genericVnfPatch.setOrchestrationStatus("Created");
105         aaiServiceProvider.invokePatchGenericVnf(genericVnfPatch);
106
107         addVservers(vnfLcmOperationOccurrenceNotification, genericVnf.getVnfId(), vnfInstance.getVimConnectionInfo());
108
109         logger.debug("Finished handling notification for vnfm: " + vnfInstance.getId());
110     }
111
112     private void setOamIpAddress(final GenericVnf genericVnf, final InlineResponse201 vnfInstance) {
113         final OamIpAddressSource oamIpAddressSource = aaiHelper.getOamIpAddressSource(vnfInstance.getId());
114         if (oamIpAddressSource == null) {
115             logger.warn("No source indicated for OAM IP address, no value will be set in AAI");
116             return;
117         }
118         if (oamIpAddressSource.getType().equals(OamIpAddressType.LITERAL)) {
119             genericVnf.setIpv4OamAddress(oamIpAddressSource.getValue());
120         } else {
121             try {
122                 logger.debug("ConfigurableProperties: " + vnfInstance.getVnfConfigurableProperties());
123                 if (vnfInstance.getVnfConfigurableProperties() == null) {
124                     logger.warn("No ConfigurableProperties, cannot set OAM IP Address");
125                 }
126                 final JSONObject properties = new JSONObject((Map) vnfInstance.getVnfConfigurableProperties());
127                 genericVnf.setIpv4OamAddress(properties.get(oamIpAddressSource.getValue()).toString());
128             } catch (final JSONException jsonException) {
129                 logger.error("Error getting vnfIpAddress", jsonException);
130             }
131         }
132     }
133
134     private void handleVnfTerminate() {
135         switch (vnfLcmOperationOccurrenceNotification.getOperationState()) {
136             case COMPLETED:
137                 handleVnfTerminateCompleted();
138                 break;
139             case FAILED:
140             case ROLLING_BACK:
141                 handleVnfTerminateFailed();
142                 break;
143             default:
144         }
145     }
146
147     private void handleVnfTerminateFailed() {
148         try {
149             final GenericVnf genericVnf = aaiServiceProvider
150                     .invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).getGenericVnf().get(0);
151             deleteVserversFromAai(vnfLcmOperationOccurrenceNotification, genericVnf);
152         } finally {
153             jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId(),
154                     false);
155         }
156     }
157
158     private void handleVnfTerminateCompleted() {
159         GenericVnf genericVnf = null;
160         boolean vServersDeletedFromAai = false;
161         boolean identifierDeletedFromVnfm = false;
162         boolean genericVnfUpdated = false;
163         try {
164             genericVnf = aaiServiceProvider.invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref())
165                     .getGenericVnf().get(0);
166             vServersDeletedFromAai = deleteVserversFromAai(vnfLcmOperationOccurrenceNotification, genericVnf);
167             identifierDeletedFromVnfm = deleteVnfIdentifierOnVnfm(genericVnf);
168             genericVnfUpdated = patchVnfInAai(genericVnf.getVnfId(), "Assigned", identifierDeletedFromVnfm ? "" : null);
169         } finally {
170             jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId(),
171                     vServersDeletedFromAai && identifierDeletedFromVnfm && genericVnfUpdated);
172             jobManager.vnfDeleted(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId());
173         }
174     }
175
176     private void addVservers(final VnfLcmOperationOccurrenceNotification notification, final String vnfId,
177             final List<InlineResponse201VimConnectionInfo> vnfInstancesVimConnectionInfo) {
178         final Map<String, InlineResponse201VimConnectionInfo> vimConnectionIdToVimConnectionInfo = new HashMap<>();
179         for (final InlineResponse201VimConnectionInfo vimConnectionInfo : vnfInstancesVimConnectionInfo) {
180             vimConnectionIdToVimConnectionInfo.put(vimConnectionInfo.getId(), vimConnectionInfo);
181         }
182
183         for (final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc : notification.getAffectedVnfcs()) {
184             final InlineResponse201VimConnectionInfo vimConnectionInfo =
185                     getVimConnectionInfo(vimConnectionIdToVimConnectionInfo, vnfc);
186             if (ChangeTypeEnum.ADDED.equals(vnfc.getChangeType())) {
187                 final Vserver vserver = aaiHelper.createVserver(vnfc);
188                 aaiServiceProvider.invokePutVserver(getCloudOwner(vimConnectionInfo), getCloudRegion(vimConnectionInfo),
189                         getTenant(vimConnectionInfo), vserver);
190
191                 aaiServiceProvider.invokePutVserverToVnfRelationship(getCloudOwner(vimConnectionInfo),
192                         getCloudRegion(vimConnectionInfo), getTenant(vimConnectionInfo), vserver, vnfId);
193             }
194         }
195     }
196
197     private boolean deleteVserversFromAai(final VnfLcmOperationOccurrenceNotification notification,
198             final GenericVnf vnf) {
199         try {
200             for (final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc : notification.getAffectedVnfcs()) {
201                 if (ChangeTypeEnum.REMOVED.equals(vnfc.getChangeType())) {
202
203                     final Relationship relationshipToVserver = aaiHelper.deleteRelationshipWithDataValue(vnf, "vserver",
204                             "vserver.vserver-id", vnfc.getComputeResource().getResourceId());
205
206                     aaiServiceProvider.invokeDeleteVserver(
207                             aaiHelper.getRelationshipData(relationshipToVserver, "cloud-region.cloud-owner"),
208                             aaiHelper.getRelationshipData(relationshipToVserver, "cloud-region.cloud-region-id"),
209                             aaiHelper.getRelationshipData(relationshipToVserver, "tenant.tenant-id"),
210                             vnfc.getComputeResource().getResourceId());
211                 }
212             }
213             return true;
214         } catch (final Exception exception) {
215             logger.error(
216                     "Error encountered deleting vservers based on received notification, AAI may not be updated correctly "
217                             + vnfLcmOperationOccurrenceNotification,
218                     exception);
219             return false;
220         }
221     }
222
223     private boolean deleteVnfIdentifierOnVnfm(final GenericVnf genericVnf) {
224         try {
225             vnfmServiceProvider.deleteVnf(aaiHelper.getAssignedVnfm(genericVnf), genericVnf.getSelflink());
226             return true;
227         } catch (final Exception exception) {
228             logger.error("Exception deleting the identifier " + genericVnf.getSelflink()
229                     + " from the VNFM. The VNF has been terminated successfully but the identifier will remain on the VNFM.",
230                     exception);
231             return false;
232         }
233     }
234
235     private boolean patchVnfInAai(final String vnfId, final String orchestrationStatus, final String selfLink) {
236         try {
237             final GenericVnf genericVnfPatch = new GenericVnf();
238             genericVnfPatch.setVnfId(vnfId);
239             genericVnfPatch.setOrchestrationStatus(orchestrationStatus);
240             if (selfLink != null) {
241                 genericVnfPatch.setSelflink(selfLink);
242             }
243             aaiServiceProvider.invokePatchGenericVnf(genericVnfPatch);
244             return true;
245         } catch (final Exception exception) {
246             logger.error(
247                     "Error encountered setting orchestration status and/or self link based on received notification, AAI may not be updated correctly "
248                             + vnfLcmOperationOccurrenceNotification,
249                     exception);
250             return false;
251         }
252     }
253
254     private InlineResponse201VimConnectionInfo getVimConnectionInfo(
255             final Map<String, InlineResponse201VimConnectionInfo> vimConnectionIdToVimConnectionInfo,
256             final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc) {
257         final String vimConnectionId = vnfc.getComputeResource().getVimConnectionId();
258         return vimConnectionIdToVimConnectionInfo.get(vimConnectionId);
259     }
260
261     private String getCloudOwner(final InlineResponse201VimConnectionInfo vimConnectionInfo) {
262         final String vimId = vimConnectionInfo.getVimId();
263         return vimId.substring(0, vimId.indexOf("_"));
264     }
265
266     private String getCloudRegion(final InlineResponse201VimConnectionInfo vimConnectionInfo) {
267         final String vimId = vimConnectionInfo.getVimId();
268         return vimId.substring(vimId.indexOf("_") + 1);
269     }
270
271     private String getTenant(final InlineResponse201VimConnectionInfo vimConnectionInfo) {
272         final JSONObject vimConnectionJsonObject = new JSONObject(vimConnectionInfo);
273         return vimConnectionJsonObject.getJSONObject("accessInfo").get("projectId").toString();
274     }
275
276 }