Sending workflow data from UI to SO
[vid.git] / vid-app-common / src / main / java / org / onap / vid / services / ChangeManagementServiceImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.vid.services;
22
23 import com.fasterxml.jackson.databind.node.ArrayNode;
24 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
25 import org.apache.commons.lang3.tuple.ImmutablePair;
26 import org.apache.commons.lang3.tuple.Pair;
27 import org.hibernate.NonUniqueObjectException;
28 import org.json.JSONObject;
29 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
30 import org.onap.portalsdk.core.service.DataAccessService;
31 import org.onap.portalsdk.core.util.SystemProperties;
32 import org.onap.vid.changeManagement.*;
33 import org.onap.vid.controller.ControllersUtils;
34 import org.onap.vid.exceptions.GenericUncheckedException;
35 import org.onap.vid.exceptions.NotFoundException;
36 import org.onap.vid.model.VNFDao;
37 import org.onap.vid.model.VidWorkflow;
38 import org.onap.vid.mso.MsoBusinessLogic;
39 import org.onap.vid.mso.MsoResponseWrapper;
40 import org.onap.vid.mso.MsoResponseWrapperInterface;
41 import org.onap.vid.mso.RestObject;
42 import org.onap.vid.mso.RestObjectWithRequestInfo;
43 import org.onap.vid.mso.rest.Request;
44 import org.onap.vid.scheduler.SchedulerProperties;
45 import org.onap.vid.scheduler.SchedulerRestInterfaceIfc;
46 import org.onap.vid.utils.SystemPropertiesWrapper;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.http.HttpStatus;
49 import org.springframework.http.ResponseEntity;
50 import org.springframework.stereotype.Service;
51 import org.springframework.util.StringUtils;
52 import org.springframework.web.multipart.MultipartFile;
53
54 import javax.servlet.http.HttpServletRequest;
55 import javax.ws.rs.BadRequestException;
56 import java.io.IOException;
57 import java.util.*;
58 import java.util.stream.Collectors;
59
60
61 @Service
62 public class ChangeManagementServiceImpl implements ChangeManagementService {
63
64     private static final String PRIMARY_KEY = "payload";
65     private static final Set<String> REQUIRED_KEYS = new HashSet<>(Arrays.asList("request-parameters", "configuration-parameters"));
66     private final DataAccessService dataAccessService;
67     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ChangeManagementServiceImpl.class);
68     private MsoBusinessLogic msoBusinessLogic;
69     private final SchedulerRestInterfaceIfc restClient;
70     private final CloudOwnerService cloudOwnerService;
71     private final SystemPropertiesWrapper systemPropertiesWrapper;
72
73     @Autowired
74     private CsvService csvService;
75
76     @Autowired
77     public ChangeManagementServiceImpl(DataAccessService dataAccessService, MsoBusinessLogic msoBusinessLogic, SchedulerRestInterfaceIfc schedulerRestInterface, CloudOwnerService cloudOwnerService, SystemPropertiesWrapper systemPropertiesWrapper) {
78         this.dataAccessService = dataAccessService;
79         this.msoBusinessLogic = msoBusinessLogic;
80         this.restClient = schedulerRestInterface;
81         this.cloudOwnerService = cloudOwnerService;
82         this.systemPropertiesWrapper = systemPropertiesWrapper;
83     }
84
85     @Override
86     public Collection<Request> getMSOChangeManagements() {
87             return msoBusinessLogic.getOrchestrationRequestsForDashboard();
88     }
89
90     protected RequestDetails findRequestByVnfName(List<RequestDetails> requests, String vnfName) {
91
92         if (requests == null)
93             return null;
94
95         for (RequestDetails requestDetails : requests) {
96             if (requestDetails.getVnfName().equals(vnfName)) {
97                 return requestDetails;
98             }
99         }
100
101         return null;
102     }
103
104     @Override
105     public ResponseEntity<String> doChangeManagement(ChangeManagementRequest request, String vnfName) {
106         if (request == null)
107             return null;
108         ResponseEntity<String> response;
109         RequestDetails currentRequestDetails = findRequestByVnfName(request.getRequestDetails(), vnfName);
110         MsoResponseWrapperInterface msoResponseWrapperObject = null;
111         if (currentRequestDetails != null) {
112
113             String serviceInstanceId = extractServiceInstanceId(currentRequestDetails, request.getRequestType());
114             String vnfInstanceId = extractVnfInstanceId(currentRequestDetails, request.getRequestType());
115             String requestType = request.getRequestType();
116             try {
117                 switch (requestType.toLowerCase()) {
118                     case ChangeManagementRequest.UPDATE: {
119                         cloudOwnerService.enrichRequestWithCloudOwner(currentRequestDetails);
120                         msoResponseWrapperObject = msoBusinessLogic.updateVnf(currentRequestDetails, serviceInstanceId, vnfInstanceId);
121                         break;
122                     }
123                     case ChangeManagementRequest.REPLACE: {
124                         cloudOwnerService.enrichRequestWithCloudOwner(currentRequestDetails);
125                         msoResponseWrapperObject = msoBusinessLogic.replaceVnf(currentRequestDetails, serviceInstanceId, vnfInstanceId);
126                         break;
127                     }
128                     case ChangeManagementRequest.VNF_IN_PLACE_SOFTWARE_UPDATE: {
129                         cloudOwnerService.enrichRequestWithCloudOwner(currentRequestDetails);
130                         msoResponseWrapperObject = msoBusinessLogic.updateVnfSoftware(currentRequestDetails, serviceInstanceId, vnfInstanceId);
131                         break;
132                     }
133                     case ChangeManagementRequest.CONFIG_UPDATE: {
134                         msoResponseWrapperObject = msoBusinessLogic.updateVnfConfig(currentRequestDetails, serviceInstanceId, vnfInstanceId);
135                         break;
136                     }
137                     case ChangeManagementRequest.SCALE_OUT:{
138                         msoResponseWrapperObject = msoBusinessLogic.scaleOutVfModuleInstance(currentRequestDetails, serviceInstanceId, vnfInstanceId);
139                         break;
140                     }
141                     default:
142                         throw new GenericUncheckedException("Failure during doChangeManagement with request " + request.toString());
143                 }
144                 response = new ResponseEntity<>(msoResponseWrapperObject.getResponse(), HttpStatus.OK);
145                 return response;
146             } catch (Exception e) {
147                 logger.error("Failure during doChangeManagement with request " + request.toString(), e);
148                 throw e;
149             }
150
151         }
152
153         // AH:TODO: return ChangeManagementResponse
154         return null;
155     }
156
157     private String extractVnfInstanceId(RequestDetails currentRequestDetails, String requestType) {
158         if (currentRequestDetails.getVnfInstanceId() == null) {
159             logger.error("Failed to extract vnfInstanceId");
160             throw new BadRequestException("No vnfInstanceId in request " + requestType);
161         }
162         return currentRequestDetails.getVnfInstanceId();
163     }
164
165     protected String extractServiceInstanceId(RequestDetails currentRequestDetails, String requestType) {
166         try {
167             String serviceInstanceId = currentRequestDetails.getRelatedInstList().get(0).getRelatedInstance().getInstanceId();
168             serviceInstanceId.toString(); //throw exception in case that serviceInstanceId is null...
169             return serviceInstanceId;
170         } catch (Exception e) {
171             logger.error("Failed to extract serviceInstanceId");
172             throw new BadRequestException("No instanceId in request " + requestType);
173         }
174     }
175
176     @Override
177     public RestObjectWithRequestInfo<ArrayNode> getSchedulerChangeManagementsWithRequestInfo() {
178         String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_GET_SCHEDULES);
179         RestObject<ArrayNode> restObject = new RestObject<>();
180         ArrayNode jsonArray = new ArrayNode(new JsonNodeFactory(true));
181         restObject.set(jsonArray);
182         return restClient.Get(jsonArray, path, restObject);
183     }
184
185     @Override
186     public ArrayNode getSchedulerChangeManagements() {
187         RestObjectWithRequestInfo<ArrayNode> responseWithRequestInfo = getSchedulerChangeManagementsWithRequestInfo();
188         return responseWithRequestInfo.getRestObject().get();
189     }
190
191     @Override
192     public Pair<String, Integer> deleteSchedule(String scheduleId) {
193         try {
194             String path = String.format(SystemProperties.getProperty(SchedulerProperties.SCHEDULER_DELETE_SCHEDULE), scheduleId);
195             RestObject<String> restObject = new RestObject<>();
196             String str = "";
197             restObject.set(str);
198             restClient.Delete(str, "", path, restObject);
199             String restCallResult = restObject.get();
200             return new ImmutablePair<>(restCallResult, restObject.getStatusCode());
201         } catch (Exception e) {
202             logger.error(e.getMessage(), e);
203             return new ImmutablePair<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value());
204         }
205     }
206
207     @Override
208     public VnfWorkflowRelationResponse addVnfWorkflowRelation(VnfWorkflowRelationRequest vnfWorkflowRelationRequest) {
209         VnfWorkflowRelationResponse vnfWorkflowRelationResponse = new VnfWorkflowRelationResponse();
210         for (WorkflowsDetail workflowsDetail : vnfWorkflowRelationRequest.getWorkflowsDetails()) {
211             if (StringUtils.isEmpty(workflowsDetail.getVnfDetails().getUUID()) ||
212                     StringUtils.isEmpty(workflowsDetail.getVnfDetails().getInvariantUUID())) {
213                 vnfWorkflowRelationResponse.getErrors().add("Using empty UUID or invariantUUID is not allowed. Relation details: " + workflowsDetail.toString());
214                 continue;
215             }
216             @SuppressWarnings("unchecked") List<VNFDao> vnfList = dataAccessService.getList(VNFDao.class, getVnfQueryString(workflowsDetail.getVnfDetails().getUUID(), workflowsDetail.getVnfDetails().getInvariantUUID()), null, null);
217             if (vnfList.isEmpty()) {
218                 vnfList.add(saveNewVnf(workflowsDetail));
219             }
220             @SuppressWarnings("unchecked") List<VidWorkflow> workflowList = dataAccessService.getList(VidWorkflow.class, String.format(" where wokflowName = '%s'", workflowsDetail.getWorkflowName()), null, null);
221             if (workflowList.isEmpty()) {
222                 vnfWorkflowRelationResponse.getErrors().add("Not Found instance of workflow " + workflowsDetail.getWorkflowName() + " for vnf with UUID " + workflowsDetail.getVnfDetails().getUUID() + " and with invariantUUID " + workflowsDetail.getVnfDetails().getInvariantUUID());
223                 continue;
224             }
225             vnfList.get(0).getWorkflows().add(workflowList.get(0));
226             try {
227                 dataAccessService.saveDomainObject(vnfList.get(0), null);
228             } catch (NonUniqueObjectException e) {
229                 //In case the relation already exists, we continue running on the list
230             }
231         }
232         return vnfWorkflowRelationResponse;
233     }
234
235     @Override
236     public VnfWorkflowRelationResponse deleteVnfWorkflowRelation(VnfWorkflowRelationRequest vnfWorkflowRelationRequest) {
237         VnfWorkflowRelationResponse vnfWorkflowRelationResponse = new VnfWorkflowRelationResponse();
238         for (WorkflowsDetail workflowsDetail : vnfWorkflowRelationRequest.getWorkflowsDetails()) {
239             @SuppressWarnings("unchecked") List<VNFDao> vnfList = dataAccessService.getList(VNFDao.class, getVnfQueryString(workflowsDetail.getVnfDetails().getUUID(), workflowsDetail.getVnfDetails().getInvariantUUID()), null, null);
240             if (vnfList.size() != 1) {
241                 vnfWorkflowRelationResponse.getErrors().add("Found " + vnfList.size() + " instances of vnf with UUID " + workflowsDetail.getVnfDetails().getUUID() + " and vnfInvariantUUID " + workflowsDetail.getVnfDetails().getInvariantUUID());
242                 continue;
243             }
244             VidWorkflow vidWorkflow = getWorkflowOfVnf(vnfList.get(0), workflowsDetail.getWorkflowName());
245             if (vidWorkflow == null) {
246                 vnfWorkflowRelationResponse.getErrors().add("Not Found instance of workflow " + workflowsDetail.getWorkflowName() + " for vnf with UUID " + workflowsDetail.getVnfDetails().getUUID() + " and with invariantUUID " + workflowsDetail.getVnfDetails().getInvariantUUID());
247                 continue;
248             }
249             vnfList.get(0).getWorkflows().remove(vidWorkflow);
250             dataAccessService.saveDomainObject(vnfList.get(0), null);
251         }
252         return vnfWorkflowRelationResponse;
253
254     }
255
256     @Override
257     public List<String> getWorkflowsForVnf(GetVnfWorkflowRelationRequest getVnfWorkflowRelationRequest) {
258         List<VNFDao> vnfDaoList = new ArrayList<>();
259         List<Set<String>> workflowsList = new ArrayList<>();
260         getVnfDaoList(vnfDaoList, getVnfWorkflowRelationRequest);
261         getWorkflowsList(workflowsList, vnfDaoList);
262         return intersectWorkflows(workflowsList);
263     }
264
265     private void getVnfDaoList(List<VNFDao> vnfDaoList, GetVnfWorkflowRelationRequest getVnfWorkflowRelationRequest) {
266         for (VnfDetails vnfDetails : getVnfWorkflowRelationRequest.getVnfDetails()) {
267             @SuppressWarnings("unchecked") List<VNFDao> vnfList = dataAccessService.getList(VNFDao.class, getVnfQueryString(vnfDetails.getUUID(), vnfDetails.getInvariantUUID()), null, null);
268             if (vnfList.size() != 1) {
269                 throw new NotFoundException("Found" + vnfList.size() + " instances of vnf with UUID" + vnfDetails.getUUID() + " and vnfInvariantUUID" + vnfDetails.getInvariantUUID());
270             }
271             vnfDaoList.add(vnfList.get(0));
272         }
273     }
274
275     private void getWorkflowsList(List<Set<String>> workflowsList, List<VNFDao> vnfDaoList) {
276         for (VNFDao vnfDao : vnfDaoList) {
277             Set<String> tempWorkflows = vnfDao.getWorkflows().stream().map(VidWorkflow::getWokflowName).collect(Collectors.toSet());
278             workflowsList.add(tempWorkflows);
279         }
280     }
281
282     private List<String> intersectWorkflows(List<Set<String>> workflowsList) {
283         Set<String> workflows = workflowsList.get(0);
284         for (Set<String> workflow : workflowsList) {
285             workflows.retainAll(workflow);
286         }
287         return new ArrayList<>(workflows);
288     }
289
290     private String getVnfQueryString(String UUID, String invariantUUID) {
291         return " where vnfInvariantUUID = '" + invariantUUID + "' and vnfUUID = '" + UUID + "'";
292     }
293
294     private VidWorkflow getWorkflowOfVnf(VNFDao vnfDao, String workflowName) {
295         VidWorkflow vidWorkflowRes = null;
296         for (VidWorkflow vidWorkflow : vnfDao.getWorkflows()) {
297             if (vidWorkflow.getWokflowName().equals(workflowName)) {
298                 vidWorkflowRes = vidWorkflow;
299             }
300         }
301         return vidWorkflowRes;
302     }
303
304     private VNFDao saveNewVnf(WorkflowsDetail workflowsDetail) {
305         VNFDao vnfDao = new VNFDao();
306         vnfDao.setVnfUUID(workflowsDetail.getVnfDetails().getUUID());
307         vnfDao.setVnfInvariantUUID(workflowsDetail.getVnfDetails().getInvariantUUID());
308         dataAccessService.saveDomainObject(vnfDao, null);
309         return vnfDao;
310     }
311
312     @Override
313     public VnfWorkflowRelationAllResponse getAllVnfWorkflowRelations() {
314         @SuppressWarnings("unchecked") List<VNFDao> vnfList = dataAccessService.getList(VNFDao.class, null);
315         return new VnfWorkflowRelationAllResponse(
316                 vnfList.stream()
317                         .map(VnfDetailsWithWorkflows::new)
318                         .collect(Collectors.toList()));
319     }
320
321     @Override
322     public String uploadConfigUpdateFile(MultipartFile file) {
323         JSONObject json = null;
324         try {
325             json = csvService.convertCsvToJson(csvService.readCsv(file));
326         } catch (InstantiationException | IllegalAccessException | IOException e) {
327             throw new BadRequestException("Invalid csv file", e);
328         }
329         if (!validateJsonOutput(json))
330             throw new BadRequestException("Invalid csv file");
331         json = json.getJSONObject(PRIMARY_KEY);
332         json = new JSONObject().put(PRIMARY_KEY, json.toString());
333         return json.toString();
334     }
335
336     @Override
337     public MsoResponseWrapper invokeVnfWorkflow(HttpServletRequest request,WorkflowRequestDetail requestBody, UUID serviceInstanceId, UUID vnfInstanceId, UUID workflow_UUID) {
338         String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(request);
339         return msoBusinessLogic.invokeVnfWorkflow(requestBody, userId, serviceInstanceId, vnfInstanceId, workflow_UUID);
340     }
341
342     private boolean validateJsonOutput(org.json.JSONObject json) {
343         if (!json.has(PRIMARY_KEY) || !json.getJSONObject(PRIMARY_KEY).keySet().containsAll(REQUIRED_KEYS))
344             return false;
345         return true;
346     }
347 }