Clamp uses new Loop implementation by default
[clamp.git] / src / main / java / org / onap / clamp / clds / service / CldsService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
6  *                             reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  * Modifications copyright (c) 2018 Nokia
21  * ===================================================================
22  *
23  */
24
25 package org.onap.clamp.clds.service;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.google.gson.JsonElement;
30 import com.google.gson.JsonObject;
31 import com.google.gson.reflect.TypeToken;
32 import java.io.IOException;
33 import java.lang.reflect.Type;
34 import java.util.Date;
35 import java.util.List;
36 import java.util.UUID;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.ws.rs.BadRequestException;
39 import javax.xml.transform.TransformerException;
40 import org.apache.camel.Produce;
41 import org.json.simple.parser.ParseException;
42 import org.onap.clamp.clds.camel.CamelProxy;
43 import org.onap.clamp.clds.client.DcaeDispatcherServices;
44 import org.onap.clamp.clds.client.DcaeInventoryServices;
45 import org.onap.clamp.clds.config.ClampProperties;
46 import org.onap.clamp.clds.dao.CldsDao;
47 import org.onap.clamp.clds.exception.policy.PolicyClientException;
48 import org.onap.clamp.clds.exception.sdc.SdcCommunicationException;
49 import org.onap.clamp.clds.model.CldsEvent;
50 import org.onap.clamp.clds.model.CldsInfo;
51 import org.onap.clamp.clds.model.CldsModel;
52 import org.onap.clamp.clds.model.CldsModelProp;
53 import org.onap.clamp.clds.model.CldsMonitoringDetails;
54 import org.onap.clamp.clds.model.CldsTemplate;
55 import org.onap.clamp.clds.model.DcaeEvent;
56 import org.onap.clamp.clds.model.ValueItem;
57 import org.onap.clamp.clds.model.properties.ModelProperties;
58 import org.onap.clamp.clds.model.sdc.SdcServiceInfo;
59 import org.onap.clamp.clds.sdc.controller.installer.CsarInstaller;
60 import org.onap.clamp.clds.transform.XslTransformer;
61 import org.onap.clamp.clds.util.JsonUtils;
62 import org.onap.clamp.clds.util.LoggingUtils;
63 import org.onap.clamp.clds.util.ONAPLogConstants;
64 import org.slf4j.event.Level;
65 import org.springframework.beans.factory.annotation.Autowired;
66 import org.springframework.beans.factory.annotation.Value;
67 import org.springframework.http.HttpStatus;
68 import org.springframework.http.ResponseEntity;
69 import org.springframework.stereotype.Component;
70 import org.springframework.web.client.HttpClientErrorException;
71
72 /**
73  * Service to save and retrieve the CLDS model attributes.
74  */
75 @Component
76 public class CldsService extends SecureServiceBase {
77
78     /**
79      * The constant LIST_OF_SDC_SERVICE_INFO_TYPE.
80      */
81     public static final Type LIST_OF_SDC_SERVICE_INFO_TYPE = new TypeToken<List<SdcServiceInfo>>() {
82         }.getType();
83     @Produce(uri = "direct:processSubmit")
84     private CamelProxy camelProxy;
85     /**
86      * The constant securityLogger.
87      */
88     protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
89     /**
90      * The constant logger.
91      */
92     protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CldsService.class);
93
94     /**
95      * The constant GLOBAL_PROPERTIES_KEY.
96      */
97     public static final String GLOBAL_PROPERTIES_KEY = "files.globalProperties";
98     private final String cldsPermissionTypeClManage;
99     private final String cldsPermissionTypeClEvent;
100     private final String cldsPermissionTypeFilterVf;
101     private final String cldsPermissionInstance;
102     /**
103      * The Permission read cl.
104      */
105     final SecureServicePermission permissionReadCl;
106     /**
107      * The Permission update cl.
108      */
109     final SecureServicePermission permissionUpdateCl;
110     /**
111      * The Permission read template.
112      */
113     final SecureServicePermission permissionReadTemplate;
114     /**
115      * The Permission update template.
116      */
117     final SecureServicePermission permissionUpdateTemplate;
118     /**
119      * The Permission read tosca.
120      */
121     final SecureServicePermission permissionReadTosca;
122     /**
123      * The Permission update tosca.
124      */
125     final SecureServicePermission permissionUpdateTosca;
126
127     private final CldsDao cldsDao;
128     private final XslTransformer cldsBpmnTransformer;
129     private final ClampProperties refProp;
130     private final DcaeDispatcherServices dcaeDispatcherServices;
131     private final DcaeInventoryServices dcaeInventoryServices;
132     private LoggingUtils util = new LoggingUtils(logger);
133
134     @Autowired
135     private HttpServletRequest request;
136
137     /**
138      * Instantiates a new Clds service.
139      *
140      * @param cldsDao                    the clds dao
141      * @param cldsBpmnTransformer        the clds bpmn transformer
142      * @param refProp                    the ref prop
143      * @param dcaeDispatcherServices     the dcae dispatcher services
144      * @param dcaeInventoryServices      the dcae inventory services
145      * @param cldsPersmissionTypeCl      the clds persmission type cl
146      * @param cldsPermissionTypeClManage the clds permission type cl manage
147      * @param cldsPermissionTypeClEvent  the clds permission type cl event
148      * @param cldsPermissionTypeFilterVf the clds permission type filter vf
149      * @param cldsPermissionTypeTemplate the clds permission type template
150      * @param cldsPermissionTypeTosca    the clds permission type tosca
151      * @param cldsPermissionInstance     the clds permission instance
152      */
153     @Autowired
154     public CldsService(CldsDao cldsDao, XslTransformer cldsBpmnTransformer, ClampProperties refProp,
155         DcaeDispatcherServices dcaeDispatcherServices,
156         DcaeInventoryServices dcaeInventoryServices,
157         @Value("${clamp.config.security.permission.type.cl:permission-type-cl}")
158                                    String cldsPersmissionTypeCl,
159         @Value("${clamp.config.security.permission.type.cl.manage:permission-type-cl-manage}")
160                                    String cldsPermissionTypeClManage,
161         @Value("${clamp.config.security.permission.type.cl.event:permission-type-cl-event}")
162                                    String cldsPermissionTypeClEvent,
163         @Value("${clamp.config.security.permission.type.filter.vf:permission-type-filter-vf}")
164                                    String cldsPermissionTypeFilterVf,
165         @Value("${clamp.config.security.permission.type.template:permission-type-template}")
166                                    String cldsPermissionTypeTemplate,
167         @Value("${clamp.config.security.permission.type.tosca:permission-type-tosca}")
168                                    String cldsPermissionTypeTosca,
169         @Value("${clamp.config.security.permission.instance:dev}")
170                                    String cldsPermissionInstance) {
171         this.cldsDao = cldsDao;
172         this.cldsBpmnTransformer = cldsBpmnTransformer;
173         this.refProp = refProp;
174         this.dcaeDispatcherServices = dcaeDispatcherServices;
175         this.dcaeInventoryServices = dcaeInventoryServices;
176         this.cldsPermissionTypeClManage = cldsPermissionTypeClManage;
177         this.cldsPermissionTypeClEvent = cldsPermissionTypeClEvent;
178         this.cldsPermissionTypeFilterVf = cldsPermissionTypeFilterVf;
179         this.cldsPermissionInstance = cldsPermissionInstance;
180         permissionReadCl = SecureServicePermission.create(cldsPersmissionTypeCl, cldsPermissionInstance, "read");
181         permissionUpdateCl = SecureServicePermission.create(cldsPersmissionTypeCl, cldsPermissionInstance, "update");
182         permissionReadTemplate = SecureServicePermission.create(cldsPermissionTypeTemplate, cldsPermissionInstance,
183             "read");
184         permissionUpdateTemplate = SecureServicePermission.create(cldsPermissionTypeTemplate, cldsPermissionInstance,
185             "update");
186         permissionReadTosca = SecureServicePermission.create(cldsPermissionTypeTosca, cldsPermissionInstance, "read");
187         permissionUpdateTosca = SecureServicePermission.create(cldsPermissionTypeTosca, cldsPermissionInstance,
188             "update");
189     }
190
191     /**
192      * Gets clds details.
193      * list of CLDS-Monitoring-Details: CLOSELOOP_NAME | Close loop name
194      * used in the CLDS application (prefix: ClosedLoop- + unique ClosedLoop ID)
195      * MODEL_NAME | Model Name in CLDS application SERVICE_TYPE_ID | TypeId returned
196      * from the DCAE application when the ClosedLoop is submitted
197      * (DCAEServiceTypeRequest generated in DCAE application). DEPLOYMENT_ID | Id
198      * generated when the ClosedLoop is deployed in DCAE. TEMPLATE_NAME | Template
199      * used to generate the ClosedLoop model. ACTION_CD | Current state of the
200      * ClosedLoop in CLDS application.
201      * @return the clds details
202      */
203     public List<CldsMonitoringDetails> getCldsDetails() {
204         util.entering(request, "CldsService: GET model details");
205         Date startTime = new Date();
206         List<CldsMonitoringDetails> cldsMonitoringDetailsList = cldsDao.getCldsMonitoringDetails();
207         // audit log
208         LoggingUtils.setTimeContext(startTime, new Date());
209         auditLogger.info("GET cldsDetails completed");
210         util.exiting("200", "Get cldsDetails success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
211         return cldsMonitoringDetailsList;
212     }
213
214     /**
215      * Gets clds info.
216      * CLDS IFO service will return 3 things 1. User Name 2. CLDS code version that
217      * is currently installed from pom.xml file 3. User permissions
218      * @return the clds info
219      */
220     public CldsInfo getCldsInfo() {
221         util.entering(request, "CldsService: GET cldsInfo");
222         Date startTime = new Date();
223         LoggingUtils.setTimeContext(startTime, new Date());
224
225         CldsInfoProvider cldsInfoProvider = new CldsInfoProvider(this);
226         CldsInfo cldsInfo = cldsInfoProvider.getCldsInfo();
227
228         // audit log
229         LoggingUtils.setTimeContext(startTime, new Date());
230         securityLogger.info("GET cldsInfo completed");
231         util.exiting("200", "Get cldsInfo success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
232         return cldsInfo;
233     }
234
235     /**
236      * REST service that retrieves BPMN for a CLDS model name from the database.
237      * This is subset of the json getModel. This is only expected to be used for
238      * testing purposes, not by the UI.
239      *
240      * @param modelName the model name
241      * @return bpmn xml text - content of bpmn given name
242      */
243     public String getBpmnXml(String modelName) {
244         util.entering(request, "CldsService: GET model bpmn");
245         Date startTime = new Date();
246         isAuthorized(permissionReadCl);
247         logger.info("GET bpmnText for modelName={}", modelName);
248         CldsModel model = CldsModel.retrieve(cldsDao, modelName, false);
249         // audit log
250         LoggingUtils.setTimeContext(startTime, new Date());
251         auditLogger.info("GET model bpmn completed");
252         util.exiting("200", "Get model bpmn success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
253         return model.getBpmnText();
254     }
255
256     /**
257      * REST service that retrieves image for a CLDS model name from the database.
258      * This is subset of the json getModel. This is only expected to be used for
259      * testing purposes, not by the UI.
260      *
261      * @param modelName the model name
262      * @return image xml text - content of image given name
263      */
264     public String getImageXml(String modelName) {
265         util.entering(request, "CldsService: GET model image");
266         Date startTime = new Date();
267         isAuthorized(permissionReadCl);
268         logger.info("GET imageText for modelName={}", modelName);
269         CldsModel model = CldsModel.retrieve(cldsDao, modelName, false);
270         // audit log
271         LoggingUtils.setTimeContext(startTime, new Date());
272         auditLogger.info("GET model image completed");
273         util.exiting("200", "Get model image success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
274         return model.getImageText();
275     }
276
277     /**
278      * REST service that retrieves a CLDS model by name from the database.
279      *
280      * @param modelName the model name
281      * @return clds model - clds model for the given model name
282      */
283     public CldsModel getModel(String modelName) {
284         util.entering(request, "CldsService: GET model");
285         Date startTime = new Date();
286         isAuthorized(permissionReadCl);
287         logger.debug("GET model for  modelName={}", modelName);
288         CldsModel cldsModel = CldsModel.retrieve(cldsDao, modelName, false);
289         isAuthorizedForVf(cldsModel);
290         // Try an update for DCAE status
291         // Checking condition whether our CLDS model can call Inventory Method
292         try {
293             // Method to call dcae inventory and invoke insert event method
294             if (cldsModel.canDcaeInventoryCall()
295                 && !cldsModel.getTemplateName().startsWith(CsarInstaller.TEMPLATE_NAME_PREFIX)) {
296                 dcaeInventoryServices.setEventInventory(cldsModel, getUserId());
297             }
298             // This is a blocking call
299             if (cldsModel.getEvent().isActionCd(CldsEvent.ACTION_DEPLOY)
300                 && !CldsModel.STATUS_ACTIVE.equals(cldsModel.getStatus()) && cldsModel.getDeploymentId() != null
301                 && cldsModel.getDeploymentStatusUrl() != null) {
302                 checkDcaeDeploymentStatus(cldsModel, CldsEvent.ACTION_DEPLOY, false);
303                 // Refresh the model object in any cases for new event
304                 cldsModel = CldsModel.retrieve(cldsDao, cldsModel.getName(), false);
305             }
306         } catch (Exception e) {
307             LoggingUtils.setErrorContext("900", "Set event inventory error");
308             logger.error("getModel set event Inventory error:" + e);
309         }
310         // audit log
311         LoggingUtils.setTimeContext(startTime, new Date());
312         auditLogger.info("GET model completed");
313         util.exiting("200", "Get model success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
314         return cldsModel;
315     }
316
317     /**
318      * REST service that saves a CLDS model by name in the database.
319      *
320      * @param modelName the model name
321      * @param cldsModel the clds model
322      * @return the clds model
323      */
324     public CldsModel putModel(String modelName, CldsModel cldsModel) {
325         util.entering(request, "CldsService: PUT model");
326         Date startTime = new Date();
327         isAuthorized(permissionUpdateCl);
328         isAuthorizedForVf(cldsModel);
329         logger.info("PUT model for  modelName={}", modelName);
330         logger.info("PUT bpmnText={}", cldsModel.getBpmnText());
331         logger.info("PUT propText={}", cldsModel.getPropText());
332         logger.info("PUT imageText={}", cldsModel.getImageText());
333         fillInCldsModel(cldsModel);
334         cldsModel.save(cldsDao, getUserId());
335
336         // audit log
337         LoggingUtils.setTimeContext(startTime, new Date());
338         auditLogger.info("PUT model completed");
339         util.exiting("200", "Put model success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
340         return cldsModel;
341     }
342
343     /**
344      * REST service that retrieves a list of CLDS model names.
345      *
346      * @return model names in JSON
347      */
348     public List<ValueItem> getModelNames() {
349         util.entering(request, "CldsService: GET model names");
350         Date startTime = new Date();
351         isAuthorized(permissionReadCl);
352         logger.info("GET list of model names");
353         List<ValueItem> names = cldsDao.getModelNames();
354         // audit log
355         LoggingUtils.setTimeContext(startTime, new Date());
356         auditLogger.info("GET model names completed");
357         util.exiting("200", "Get model names success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
358         return names;
359     }
360
361     private void fillInCldsModel(CldsModel model) {
362         if (model.getTemplateName() != null) {
363             CldsTemplate template = cldsDao.getTemplate(model.getTemplateName());
364             if (template != null) {
365                 model.setTemplateId(template.getId());
366                 model.setDocText(template.getPropText());
367                 // This is to provide the Bpmn XML when Template part in UI
368                 // is
369                 // disabled
370                 model.setBpmnText(template.getBpmnText());
371             }
372         }
373     }
374
375     /**
376      * REST service that saves and processes an action for a CLDS model by name.
377      *
378      * @param action    the action
379      * @param modelName the model name
380      * @param test      the test
381      * @param model     the model
382      * @return response entity
383      * @throws TransformerException In case of issues when doing the XSLT of the BPMN flow
384      * @throws ParseException       In case of issues when parsing the JSON
385      */
386     public ResponseEntity<?> putModelAndProcessAction(String action, String modelName, String test, CldsModel model)
387         throws TransformerException, ParseException {
388         util.entering(request, "CldsService: Process model action");
389         Date startTime = new Date();
390         String errorMessage = "";
391         String actionCd = "";
392         try {
393             actionCd = action.toUpperCase();
394             SecureServicePermission permisionManage = SecureServicePermission.create(cldsPermissionTypeClManage,
395                 cldsPermissionInstance, actionCd);
396             isAuthorized(permisionManage);
397             isAuthorizedForVf(model);
398             String userId = getUserId();
399             logger.info("PUT actionCd={}", actionCd);
400             logger.info("PUT modelName={}", modelName);
401             logger.info("PUT test={}", test);
402             logger.info("PUT bpmnText={}", model.getBpmnText());
403             logger.info("PUT propText={}", model.getPropText());
404             logger.info("PUT userId={}", userId);
405             logger.info("PUT getTypeId={}", model.getTypeId());
406             logger.info("PUT deploymentId={}", model.getDeploymentId());
407             this.fillInCldsModel(model);
408             // save model to db just in case
409             model.save(cldsDao, getUserId());
410
411             // get vars and format if necessary
412             String prop = model.getPropText();
413             String bpmn = model.getBpmnText();
414             String docText = model.getDocText();
415             String controlName = model.getControlName();
416             String bpmnJson = cldsBpmnTransformer.doXslTransformToString(bpmn);
417             logger.info("PUT bpmnJson={}", bpmnJson);
418             // Test flag coming from UI or from Clamp config
419             boolean isTest = Boolean.parseBoolean(test)
420                 || Boolean.parseBoolean(refProp.getStringValue("action.test.override"));
421             logger.info("PUT isTest={}", isTest);
422             boolean isInsertTestEvent = Boolean.parseBoolean(refProp.getStringValue("action.insert.test.event"));
423             logger.info("PUT isInsertTestEvent={}", isInsertTestEvent);
424             // determine if requested action is permitted
425             model.validateAction(actionCd);
426             logger.info("modelProp - " + prop);
427             logger.info("docText - " + docText);
428             try {
429                 String result = camelProxy.executeAction(actionCd, prop, bpmnJson, modelName, controlName, docText,
430                     isTest, userId, isInsertTestEvent, model.getEvent().getActionCd());
431                 logger.info("Starting Camel flow on request, result is: ", result);
432             } catch (SdcCommunicationException | PolicyClientException | BadRequestException e) {
433                 logger.error("Exception occured during invoking Camel process", e);
434                 errorMessage = e.getMessage();
435             }
436             // audit log
437             LoggingUtils.setTimeContext(startTime, new Date());
438             auditLogger.info("Process model action completed");
439         } catch (Exception e) {
440             logger.error("Exception occured during putModelAndProcessAction", e);
441             errorMessage = e.getMessage();
442         }
443
444         if (null == errorMessage || (null != errorMessage && !errorMessage.isEmpty())) {
445             CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), actionCd, CldsEvent.ACTION_STATE_ERROR,
446                 null);
447             // Need a refresh as new events have been inserted
448             model = CldsModel.retrieve(cldsDao, modelName, false);
449             if (null == errorMessage) {
450                 errorMessage = "No response from Policy";
451             }
452             model.setErrorMessageForUi(errorMessage);
453             util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "putModelAndProcessAction failed", Level.INFO,
454                 ONAPLogConstants.ResponseStatus.ERROR);
455             return new ResponseEntity<>(model, HttpStatus.INTERNAL_SERVER_ERROR);
456         } else {
457             // Need a refresh as new events have been inserted, could have been deleted so
458             // not blocking call
459             model = CldsModel.retrieve(cldsDao, modelName, true);
460             util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
461             return new ResponseEntity<>(model, HttpStatus.OK);
462         }
463     }
464
465     /**
466      * REST service that accepts events for a model.
467      *
468      * @param test      the test
469      * @param dcaeEvent the dcae event
470      * @return the string
471      */
472     public String postDcaeEvent(String test, DcaeEvent dcaeEvent) {
473         util.entering(request, "CldsService: Post dcae event");
474         Date startTime = new Date();
475         String userid = null;
476         // TODO: allow auth checking to be turned off by removing the permission
477         // type property
478         if (cldsPermissionTypeClEvent != null && cldsPermissionTypeClEvent.length() > 0) {
479             SecureServicePermission permissionEvent = SecureServicePermission.create(cldsPermissionTypeClEvent,
480                 cldsPermissionInstance, dcaeEvent.getEvent());
481             isAuthorized(permissionEvent);
482             userid = getUserId();
483         }
484         // Flag indicates whether it is triggered by Validation Test button from
485         // UI
486         boolean isTest = Boolean.parseBoolean(test);
487         int instanceCount = 0;
488         if (dcaeEvent.getInstances() != null) {
489             instanceCount = dcaeEvent.getInstances().size();
490         }
491         String msgInfo = "event=" + dcaeEvent.getEvent() + " serviceUUID=" + dcaeEvent.getServiceUUID()
492             + " resourceUUID=" + dcaeEvent.getResourceUUID() + " artifactName=" + dcaeEvent.getArtifactName()
493             + " instance count=" + instanceCount + " isTest=" + isTest;
494         logger.info("POST dcae event {}", msgInfo);
495         if (isTest) {
496             logger.warn("Ignorning test event from DCAE");
497         } else {
498             if (DcaeEvent.EVENT_DEPLOYMENT.equalsIgnoreCase(dcaeEvent.getEvent())) {
499                 CldsModel.insertModelInstance(cldsDao, dcaeEvent, userid);
500             } else {
501                 CldsEvent.insEvent(cldsDao, dcaeEvent.getControlName(), userid, dcaeEvent.getCldsActionCd(),
502                     CldsEvent.ACTION_STATE_RECEIVED, null);
503             }
504         }
505         // audit log
506         LoggingUtils.setTimeContext(startTime, new Date());
507         auditLogger.info("Post dcae event completed");
508         util.exiting("200", "Post dcae event success", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
509         return msgInfo;
510     }
511
512     /**
513      * REST service that retrieves total properties required by UI.
514      *
515      * @return the sdc properties
516      * @throws IOException In case of issues
517      */
518     public String getSdcProperties() throws IOException {
519         return refProp.getJsonTemplate(GLOBAL_PROPERTIES_KEY).toString();
520     }
521
522
523     /**
524      * Determine if the user is authorized for a particular VF by its invariant
525      * UUID.
526      *
527      * @param vfInvariantUuid the vf invariant uuid
528      * @return boolean or throws NotAuthorizedException
529      */
530     public boolean isAuthorizedForVf(String vfInvariantUuid) {
531         if (cldsPermissionTypeFilterVf != null && !cldsPermissionTypeFilterVf.isEmpty()) {
532             SecureServicePermission permission = SecureServicePermission.create(cldsPermissionTypeFilterVf,
533                 cldsPermissionInstance, vfInvariantUuid);
534             return isAuthorized(permission);
535         } else {
536             // if CLDS_PERMISSION_TYPE_FILTER_VF property is not provided, then
537             // VF filtering is turned off
538             logger.warn("VF filtering turned off");
539             return true;
540         }
541     }
542
543     /**
544      * Determine if the user is authorized for a particular VF by its invariant
545      * UUID. If not authorized, then NotAuthorizedException is thrown.
546      *
547      * @param model The clds model
548      * @return boolean or throws NotAuthorizedException
549      */
550     private boolean isAuthorizedForVf(CldsModel model) {
551         String vf = ModelProperties.getVf(model);
552         if (vf == null || vf.length() == 0) {
553             logger.info("VF not found in model");
554             return true;
555         } else {
556             return isAuthorizedForVf(vf);
557         }
558     }
559
560     /**
561      * Deploy model response entity.
562      *
563      * @param modelName the model name
564      * @param model     the model
565      * @return the response entity
566      */
567     public ResponseEntity<CldsModel> deployModel(String modelName, CldsModel model) {
568         util.entering(request, "CldsService: Deploy model");
569         Date startTime = new Date();
570         String errorMessage = "";
571         try {
572             fillInCldsModel(model);
573             String bpmnJson = cldsBpmnTransformer.doXslTransformToString(model.getBpmnText());
574             logger.info("PUT bpmnJson={}", bpmnJson);
575             SecureServicePermission permisionManage = SecureServicePermission.create(cldsPermissionTypeClManage,
576                 cldsPermissionInstance, CldsEvent.ACTION_DEPLOY);
577             isAuthorized(permisionManage);
578             isAuthorizedForVf(model);
579             ModelProperties modelProp = new ModelProperties(modelName, model.getControlName(), CldsEvent.ACTION_DEPLOY,
580                 false, bpmnJson, model.getPropText());
581             checkForDuplicateServiceVf(modelName, model.getPropText());
582             String deploymentId = "";
583             // If model is already deployed then pass same deployment id
584             if (model.getDeploymentId() != null && !model.getDeploymentId().isEmpty()) {
585                 deploymentId = model.getDeploymentId();
586             } else {
587                 model.setDeploymentId(deploymentId = "closedLoop_" + UUID.randomUUID() + "_deploymentId");
588             }
589             model.setDeploymentStatusUrl(dcaeDispatcherServices.createNewDeployment(deploymentId, model.getTypeId(),
590                 modelProp.getGlobal().getDeployParameters()));
591             CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), CldsEvent.ACTION_DEPLOY,
592                 CldsEvent.ACTION_STATE_INITIATED, null);
593             model.save(cldsDao, getUserId());
594             // This is a blocking call
595             checkDcaeDeploymentStatus(model, CldsEvent.ACTION_DEPLOY, true);
596             // Refresh the model object in any cases for new event
597             model = CldsModel.retrieve(cldsDao, model.getName(), false);
598             // audit log
599             LoggingUtils.setTimeContext(startTime, new Date());
600             auditLogger.info("Deploy model completed");
601         } catch (Exception e) {
602             errorMessage = e.getMessage();
603             logger.error("Exception occured during deployModel", e);
604         }
605         if (!errorMessage.isEmpty()) {
606             model.setErrorMessageForUi(errorMessage);
607             util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "DeployModel failed", Level.INFO,
608                 ONAPLogConstants.ResponseStatus.ERROR);
609             return new ResponseEntity<>(model, HttpStatus.INTERNAL_SERVER_ERROR);
610         } else {
611             util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
612             return new ResponseEntity<>(model, HttpStatus.OK);
613         }
614     }
615
616     /**
617      * Un deploy model response entity.
618      *
619      * @param modelName the model name
620      * @param model     the model
621      * @return the response entity
622      */
623     public ResponseEntity<CldsModel> unDeployModel(String modelName, CldsModel model) {
624         util.entering(request, "CldsService: Undeploy model");
625         Date startTime = new Date();
626         String errorMessage = "";
627         try {
628             SecureServicePermission permisionManage = SecureServicePermission.create(cldsPermissionTypeClManage,
629                 cldsPermissionInstance, CldsEvent.ACTION_UNDEPLOY);
630             isAuthorized(permisionManage);
631             isAuthorizedForVf(model);
632             model.setDeploymentStatusUrl(
633                 dcaeDispatcherServices.deleteExistingDeployment(model.getDeploymentId(), model.getTypeId()));
634             CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), CldsEvent.ACTION_UNDEPLOY,
635                 CldsEvent.ACTION_STATE_INITIATED, null);
636             // clean the deployment ID
637             model.setDeploymentId(null);
638             model.save(cldsDao, getUserId());
639             // This is a blocking call
640             checkDcaeDeploymentStatus(model, CldsEvent.ACTION_UNDEPLOY, true);
641             // Refresh the model object in any cases for new event
642             model = CldsModel.retrieve(cldsDao, model.getName(), false);
643             // audit log
644             LoggingUtils.setTimeContext(startTime, new Date());
645             auditLogger.info("Undeploy model completed");
646         } catch (Exception e) {
647             errorMessage = e.getMessage();
648             logger.error("Exception occured during unDeployModel", e);
649         }
650         if (!errorMessage.isEmpty()) {
651             model.setErrorMessageForUi(errorMessage);
652             util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "UndeployModel failed", Level.INFO,
653                 ONAPLogConstants.ResponseStatus.ERROR);
654             return new ResponseEntity<>(model, HttpStatus.INTERNAL_SERVER_ERROR);
655         } else {
656             util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
657             return new ResponseEntity<>(model, HttpStatus.OK);
658         }
659     }
660
661     private void checkDcaeDeploymentStatus(CldsModel model, String cldsEvent, boolean withRetry)
662         throws InterruptedException {
663         String operationStatus = withRetry
664             ? dcaeDispatcherServices.getOperationStatusWithRetry(model.getDeploymentStatusUrl())
665             : dcaeDispatcherServices.getOperationStatus(model.getDeploymentStatusUrl());
666         if ("succeeded".equalsIgnoreCase(operationStatus)) {
667             logger.info(cldsEvent + " model (" + model.getName() + ") succeeded...Deployment Id is - "
668                 + model.getDeploymentId());
669             CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), cldsEvent,
670                 CldsEvent.ACTION_STATE_COMPLETED, null);
671         } else {
672             String info = "DCAE " + cldsEvent + " (" + model.getName() + ") failed...Operation Status is - "
673                 + operationStatus;
674             logger.info(info);
675             CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), cldsEvent, CldsEvent.ACTION_STATE_ERROR,
676                 null);
677             util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "DCAE operation(" + cldsEvent + ") failed",
678                 Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
679             throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR, info);
680         }
681     }
682
683     private void checkForDuplicateServiceVf(String modelName, String modelPropText) throws IOException {
684         JsonElement globalNode = JsonUtils.GSON.fromJson(modelPropText, JsonObject.class).get("global");
685         String service = JsonUtils.getStringValueByName(globalNode, "service");
686         List<String> resourceVf = JsonUtils.getStringValuesByName(globalNode, "vf");
687         if (service != null && resourceVf != null && !resourceVf.isEmpty()) {
688             List<CldsModelProp> cldsModelPropList = cldsDao.getDeployedModelProperties();
689             for (CldsModelProp cldsModelProp : cldsModelPropList) {
690                 JsonElement currentNode = JsonUtils.GSON
691                     .fromJson(cldsModelProp.getPropText(), JsonObject.class)
692                     .get("global");
693                 String currentService = JsonUtils.getStringValueByName(currentNode, "service");
694                 List<String> currentVf = JsonUtils.getStringValuesByName(currentNode, "vf");
695                 if (currentVf != null && !currentVf.isEmpty()) {
696                     if (!modelName.equalsIgnoreCase(cldsModelProp.getName()) && service.equalsIgnoreCase(currentService)
697                         && resourceVf.get(0).equalsIgnoreCase(currentVf.get(0))) {
698                         throw new BadRequestException("Same Service/VF already exists in " + cldsModelProp.getName()
699                             + " model, please select different Service/VF.");
700                     }
701                 }
702             }
703         }
704     }
705
706     /**
707      * Sets logging util.
708      *
709      * @param utilP the util p
710      */
711     // Created for the integration test
712     public void setLoggingUtil(LoggingUtils utilP) {
713         util = utilP;
714     }
715 }