Merge "Implement serviceType handling for E2E network slicing"
[externalapi/nbi.git] / src / main / java / org / onap / nbi / apis / serviceorder / workflow / PostSoProcessor.java
1 /**
2  * Copyright (c) 2018 Orange
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14
15 package org.onap.nbi.apis.serviceorder.workflow;
16
17 import java.io.IOException;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23 import org.onap.nbi.apis.serviceorder.SoClient;
24 import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
25 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
26 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
27 import org.onap.nbi.apis.serviceorder.model.StateType;
28 import org.onap.nbi.apis.serviceorder.model.consumer.CloudConfiguration;
29 import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
30 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
31 import org.onap.nbi.apis.serviceorder.model.consumer.MSOE2EPayload;
32 import org.onap.nbi.apis.serviceorder.model.consumer.MSOPayload;
33 import org.onap.nbi.apis.serviceorder.model.consumer.ModelInfo;
34 import org.onap.nbi.apis.serviceorder.model.consumer.OwningEntity;
35 import org.onap.nbi.apis.serviceorder.model.consumer.ParametersModel;
36 import org.onap.nbi.apis.serviceorder.model.consumer.Project;
37 import org.onap.nbi.apis.serviceorder.model.consumer.RequestDetails;
38 import org.onap.nbi.apis.serviceorder.model.consumer.RequestInfo;
39 import org.onap.nbi.apis.serviceorder.model.consumer.RequestParameters;
40 import org.onap.nbi.apis.serviceorder.model.consumer.ResourceModel;
41 import org.onap.nbi.apis.serviceorder.model.consumer.ServiceModel;
42 import org.onap.nbi.apis.serviceorder.model.consumer.SubscriberInfo;
43 import org.onap.nbi.apis.serviceorder.model.consumer.UserParams;
44 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
45 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.beans.factory.annotation.Value;
50 import org.springframework.http.ResponseEntity;
51 import org.springframework.stereotype.Service;
52 import org.springframework.util.CollectionUtils;
53 import com.fasterxml.jackson.databind.JsonNode;
54 import com.fasterxml.jackson.databind.ObjectMapper;
55 import com.fasterxml.jackson.databind.node.ArrayNode;
56 import com.fasterxml.jackson.databind.node.ObjectNode;
57
58 @Service
59 public class PostSoProcessor {
60
61     private static final Logger LOGGER = LoggerFactory.getLogger(PostSoProcessor.class);
62
63     @Value("${onap.lcpCloudRegionId}")
64     private String lcpCloudRegionId;
65
66     @Value("${onap.tenantId}")
67     private String tenantId;
68
69     @Value("${so.owning.entity.id}")
70     private String soOwningEntityId;
71
72     @Value("${so.owning.entity.name}")
73     private String soOwningEntityName;
74
75     @Value("${so.project.name}")
76     private String soProjectName;
77
78     @Value("${onap.cloudOwner}")
79     private String cloudOwner;
80
81     @Autowired
82     private ServiceOrderService serviceOrderService;
83
84     @Autowired
85     private SoClient soClient;
86
87     public ResponseEntity<CreateServiceInstanceResponse> postServiceOrderItem(ServiceOrderInfo serviceOrderInfo,
88             ServiceOrderItem serviceOrderItem) {
89         ResponseEntity<CreateServiceInstanceResponse> response = null;
90         try {
91             response = postSORequest(serviceOrderItem, serviceOrderInfo);
92         } catch (NullPointerException e) {
93             LOGGER.error("Unable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
94             response = null;
95         }
96         return response;
97     }
98
99     public ResponseEntity<CreateE2EServiceInstanceResponse> postE2EServiceOrderItem(ServiceOrderInfo serviceOrderInfo,
100             ServiceOrderItem serviceOrderItem, ServiceOrder serviceOrder) {
101         ResponseEntity<CreateE2EServiceInstanceResponse> response;
102         try {
103             response = postE2ESORequest(serviceOrderItem, serviceOrderInfo, serviceOrder);
104         } catch (NullPointerException e) {
105             LOGGER.error("Unable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
106             response = null;
107         }
108         return response;
109     }
110
111     private ResponseEntity<CreateServiceInstanceResponse> postSORequest(ServiceOrderItem serviceOrderItem,
112             ServiceOrderInfo serviceOrderInfo) {
113         RequestDetails requestDetails = buildSoRequest(serviceOrderItem, serviceOrderInfo);
114         MSOPayload msoPayload = new MSOPayload(requestDetails);
115         ResponseEntity<CreateServiceInstanceResponse> response = null;
116
117         switch (serviceOrderItem.getAction()) {
118             case ADD:
119                 response = soClient.callCreateServiceInstance(msoPayload);
120                 break;
121             case DELETE:
122                 response = soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
123                 break;
124             case MODIFY:
125                 if (StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
126                     response = soClient.callCreateServiceInstance(msoPayload);
127                 }
128                 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
129                     response = soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
130                 }
131                 break;
132             default:
133                 break;
134         }
135         return response;
136     }
137
138     private ResponseEntity<CreateE2EServiceInstanceResponse> postE2ESORequest(ServiceOrderItem serviceOrderItem,
139             ServiceOrderInfo serviceOrderInfo, ServiceOrder serviceOrder) {
140         ServiceModel service = buildE2ESoRequest(serviceOrderItem,
141                 serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()).getCatalogResponse(),
142                 serviceOrderInfo.getSubscriberInfo(), serviceOrder);
143         MSOE2EPayload msoE2EPayload = new MSOE2EPayload(service);
144         ResponseEntity<CreateE2EServiceInstanceResponse> response = null;
145         switch (serviceOrderItem.getAction()) {
146             case ADD:
147                 response = soClient.callE2ECreateServiceInstance(msoE2EPayload);
148                 break;
149             case DELETE:
150                 response = soClient.callE2EDeleteServiceInstance(service.getGlobalSubscriberId(),
151                         service.getServiceType(), serviceOrderItem.getService().getId());
152                 break;
153             case MODIFY:
154                 if (StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
155                     response = soClient.callE2ECreateServiceInstance(msoE2EPayload);
156                 }
157                 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
158                     response = soClient.callE2EDeleteServiceInstance(service.getGlobalSubscriberId(),
159                             service.getServiceType(), serviceOrderItem.getService().getId());
160                 }
161                 break;
162             default:
163                 break;
164         }
165         return response;
166     }
167
168     /**
169      * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
170      *
171      * @param orderItem
172      * @param serviceOrderInfo
173      * @return
174      */
175     private RequestDetails buildSoRequest(ServiceOrderItem orderItem, ServiceOrderInfo serviceOrderInfo) {
176         RequestDetails requestDetails = new RequestDetails();
177
178         requestDetails.setSubscriberInfo(serviceOrderInfo.getSubscriberInfo());
179         Map<String, Object> sdcInfos =
180                 serviceOrderInfo.getServiceOrderItemInfos().get(orderItem.getId()).getCatalogResponse();
181         ModelInfo modelInfo = new ModelInfo();
182         modelInfo.setModelType("service");
183         modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
184         modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
185         modelInfo.setModelVersionId(orderItem.getService().getServiceSpecification().getId());
186         modelInfo.setModelName((String) sdcInfos.get("name"));
187         modelInfo.setModelVersion((String) sdcInfos.get("version"));
188         requestDetails.setModelInfo(modelInfo);
189
190         RequestInfo requestInfo = new RequestInfo();
191         requestInfo.setInstanceName(orderItem.getService().getName());
192         requestInfo.setSource("VID");
193         requestInfo.setSuppressRollback(false);
194         requestInfo.setRequestorId("NBI");
195         requestDetails.setRequestInfo(requestInfo);
196
197         RequestParameters requestParameters = new RequestParameters();
198         
199         String serviceTypeFromJson = orderItem.getService().getServicetype();
200         requestParameters.setSubscriptionServiceType(serviceTypeFromJson != null ? serviceTypeFromJson:(String) sdcInfos.get("name"));
201         requestParameters.setUserParams(
202                 retrieveUserParamsFromServiceCharacteristics(orderItem.getService().getServiceCharacteristic()));
203         requestParameters.setaLaCarte(true);
204         requestParameters.setTestApi("GR_API");
205         requestDetails.setRequestParameters(requestParameters);
206
207         CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId, cloudOwner);
208         requestDetails.setCloudConfiguration(cloudConfiguration);
209
210         OwningEntity owningEntity = new OwningEntity();
211         owningEntity.setOwningEntityId(serviceOrderInfo.getOwningEntityId());
212         owningEntity.setOwningEntityName(soOwningEntityName);
213         requestDetails.setOwningEntity(owningEntity);
214
215         Project project = new Project();
216         project.setProjectName(soProjectName);
217
218         requestDetails.setProject(project);
219
220         return requestDetails;
221     }
222
223     /**
224      * Build E2E SO CREATE request from the ServiceOrder and catalog informations from SDC
225      *
226      * @param serviceOrderItem
227      * @param serviceOrder
228      * @param sdcInfos
229      * @return
230      */
231     // ServiceOrderItem serviceOrderItem --> orderItem?
232     private ServiceModel buildE2ESoRequest(ServiceOrderItem serviceOrderItem, Map<String, Object> sdcInfos,
233             SubscriberInfo subscriberInfo, ServiceOrder serviceOrder) {
234
235         subscriberInfo.getGlobalSubscriberId();
236         ServiceModel service = new ServiceModel();
237         service.setName(serviceOrderItem.getService().getName());
238         service.setDescription(serviceOrder.getDescription());
239         service.setServiceUuid(serviceOrderItem.getService().getServiceSpecification().getId());
240         service.setServiceInvariantUuid((String) sdcInfos.get("invariantUUID"));
241         service.setGlobalSubscriberId(subscriberInfo.getGlobalSubscriberId());
242         String serviceTypeFromJson = serviceOrderItem.getService().getServicetype();
243         service.setServiceType(serviceTypeFromJson != null ? serviceTypeFromJson : (String) sdcInfos.get("name"));
244         ParametersModel parameters = new ParametersModel();
245         ArrayList<ResourceModel> resources = new ArrayList();
246
247         ArrayList<Object> resourceObjects = (ArrayList<Object>) sdcInfos.get("resourceSpecification");
248
249         for (int i = 0; i < resourceObjects.size(); i++) {
250
251             ResourceModel resourceModel = new ResourceModel((Map<String, Object>) resourceObjects.get(i));
252             ParametersModel resourceParameters = new ParametersModel();
253             resourceModel.setParameters(resourceParameters);
254             resources.add(resourceModel);
255
256         }
257         parameters.setResources(resources);
258         List<UserParams> userParams =
259                 retrieveUserParamsFromServiceCharacteristics(serviceOrderItem.getService().getServiceCharacteristic());
260
261         // If there are ServiceCharacteristics add them to requestInputs
262         if (!userParams.isEmpty()) {
263             Map<String, String> requestInputs = new HashMap<String, String>();
264             for (int i = 0; i < userParams.size(); i++) {
265                 requestInputs.put(userParams.get(i).getName(), userParams.get(i).getValue());
266             }
267
268             parameters.setRequestInputs(requestInputs);
269         }
270         service.setParameters(parameters);
271
272         return service;
273     }
274
275     /**
276      * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from
277      * SDC
278      */
279     private List<UserParams> retrieveUserParamsFromServiceCharacteristics(List<ServiceCharacteristic> characteristics) {
280         List<UserParams> userParams = new ArrayList<>();
281         UserParams userParam;
282
283         if (!CollectionUtils.isEmpty(characteristics)) {
284             for (ServiceCharacteristic characteristic : characteristics) {
285                 // Check is the characteristic is of type object, if proceed as before to allow for
286                 // backwards compatibility.
287                 if (characteristic.getValueType() != null && !characteristic.getValueType().isEmpty()
288                         && characteristic.getValueType().equals("object")) {
289                     ObjectMapper mapper = new ObjectMapper();
290                     JsonNode jsonNode = null;
291                     try {
292                         jsonNode = mapper.readTree(characteristic.getValue().getServiceCharacteristicValue());
293                     } catch (IOException e) {
294                         LOGGER.error("Failed to read object json {} , exception is ",
295                                 characteristic.getValue().getServiceCharacteristicValue(), e.getMessage());
296                     }
297                     ObjectNode objectNode = (ObjectNode) jsonNode;
298                     Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();
299                     while (iter.hasNext()) {
300                         Map.Entry<String, JsonNode> entry = iter.next();
301                         if (!entry.getValue().isArray()) {
302                             userParam = new UserParams(entry.getKey(), entry.getValue().asText());
303                         } else {
304                             ArrayNode arrayNode = (ArrayNode) entry.getValue();
305                             String arrayNodeValueString = arrayNode.toString();
306                             userParam = new UserParams(entry.getKey(), arrayNodeValueString);
307                         }
308                         userParams.add(userParam);
309                     }
310                 }
311                 // as UserParams for all other types, boolean, string, integer etc
312                 else {
313                     userParam = new UserParams(characteristic.getName(),
314                             characteristic.getValue().getServiceCharacteristicValue());
315                     userParams.add(userParam);
316                 }
317             }
318         }
319
320         return userParams;
321     }
322
323 }