Update service object
[clamp.git] / src / main / java / org / onap / clamp / loop / CsarInstaller.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 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  * ===================================================================
21  *
22  */
23
24 package org.onap.clamp.loop;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFManager;
28 import com.google.gson.JsonObject;
29
30 import java.io.IOException;
31 import java.util.Arrays;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36
37 import org.json.simple.parser.ParseException;
38 import org.onap.clamp.clds.client.DcaeInventoryServices;
39 import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
40 import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse;
41 import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact;
42 import org.onap.clamp.clds.sdc.controller.installer.BlueprintParser;
43 import org.onap.clamp.clds.sdc.controller.installer.ChainGenerator;
44 import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
45 import org.onap.clamp.clds.sdc.controller.installer.MicroService;
46 import org.onap.clamp.clds.util.JsonUtils;
47 import org.onap.clamp.clds.util.drawing.SvgFacade;
48 import org.onap.clamp.loop.service.Service;
49 import org.onap.clamp.loop.service.ServiceRepository;
50 import org.onap.clamp.policy.Policy;
51 import org.onap.clamp.policy.microservice.MicroServicePolicy;
52 import org.onap.clamp.policy.operational.OperationalPolicy;
53 import org.onap.sdc.tosca.parser.api.IEntityDetails;
54 import org.onap.sdc.tosca.parser.elements.queries.EntityQuery;
55 import org.onap.sdc.tosca.parser.elements.queries.TopologyTemplateQuery;
56 import org.onap.sdc.tosca.parser.enums.EntityTemplateType;
57 import org.onap.sdc.tosca.parser.enums.SdcTypes;
58 import org.onap.sdc.toscaparser.api.NodeTemplate;
59 import org.onap.sdc.toscaparser.api.Property;
60 import org.springframework.beans.factory.annotation.Autowired;
61 import org.springframework.beans.factory.annotation.Qualifier;
62 import org.springframework.stereotype.Component;
63 import org.springframework.transaction.annotation.Propagation;
64 import org.springframework.transaction.annotation.Transactional;
65 import org.yaml.snakeyaml.Yaml;
66
67 /**
68  * This class will be instantiated by spring config, and used by Sdc Controller.
69  * There is no state kept by the bean. It's used to deploy the csar/notification
70  * received from SDC in DB.
71  */
72 @Component
73 @Qualifier("csarInstaller")
74 public class CsarInstaller {
75
76     private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarInstaller.class);
77     public static final String CONTROL_NAME_PREFIX = "ClosedLoop-";
78     public static final String GET_INPUT_BLUEPRINT_PARAM = "get_input";
79     // This will be used later as the policy scope
80     public static final String MODEL_NAME_PREFIX = "Loop_";
81
82     @Autowired
83     LoopsRepository loopRepository;
84
85     @Autowired
86     ServiceRepository serviceRepository;
87
88     @Autowired
89     BlueprintParser blueprintParser;
90
91     @Autowired
92     ChainGenerator chainGenerator;
93
94     @Autowired
95     DcaeInventoryServices dcaeInventoryService;
96
97     @Autowired
98     private SvgFacade svgFacade;
99
100    /**
101     * Verify whether Csar is deployed.
102     * 
103     * @param csar The Csar Handler
104     * @return The flag indicating whether Csar is deployed
105     * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
106     */
107     public boolean isCsarAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException {
108         boolean alreadyInstalled = true;
109         JsonObject serviceDetails = JsonUtils.GSON.fromJson(
110                 JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class);
111         alreadyInstalled = alreadyInstalled
112                 && serviceRepository.existsById(serviceDetails.get("UUID").getAsString());
113
114         for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
115             alreadyInstalled = alreadyInstalled
116                     && loopRepository.existsById(Loop.generateLoopName(csar.getSdcNotification().getServiceName(),
117                             csar.getSdcNotification().getServiceVersion(),
118                             blueprint.getValue().getResourceAttached().getResourceInstanceName(),
119                             blueprint.getValue().getBlueprintArtifactName()));
120         }
121         
122         return alreadyInstalled;
123     }
124
125     /**
126      * Install the service and loops from the csar.
127      * 
128      * @param csar The Csar Handler
129      * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
130      * @throws InterruptedException The InterruptedException
131      */
132     public void installTheCsar(CsarHandler csar) throws SdcArtifactInstallerException, InterruptedException {
133         logger.info("Installing the CSAR " + csar.getFilePath());
134         installTheLoop(csar, installTheService(csar));
135         logger.info("Successfully installed the CSAR " + csar.getFilePath());
136     }
137
138     /**
139      * Install the Loop from the csar.
140      * 
141      * @param csar The Csar Handler
142      * @param service The service object that is related to the loop
143      * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
144      * @throws InterruptedException The InterruptedException
145      */
146     @Transactional(propagation = Propagation.REQUIRED)
147     public void installTheLoop(CsarHandler csar, Service service) 
148             throws SdcArtifactInstallerException, InterruptedException {
149         try {
150             logger.info("Installing the Loops");
151             for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
152                 logger.info("Processing blueprint " + blueprint.getValue().getBlueprintArtifactName());
153                 loopRepository.save(createLoopFromBlueprint(csar, blueprint.getValue(), service));
154             }
155             logger.info("Successfully installed the Loops ");
156         } catch (IOException e) {
157             throw new SdcArtifactInstallerException("Exception caught during the Loop installation in database", e);
158         } catch (ParseException e) {
159             throw new SdcArtifactInstallerException("Exception caught during the Dcae query to get ServiceTypeId", e);
160         }
161     }
162
163     /**
164      * Install the Service from the csar.
165      * 
166      * @param csar The Csar Handler
167      * @return The service object
168      */
169     @Transactional
170     public Service installTheService(CsarHandler csar) {
171         logger.info("Start to install the Service from csar");
172         JsonObject serviceDetails = JsonUtils.GSON.fromJson(
173                 JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class);
174
175         // Add properties details for each type, VfModule, VF, VFC, ....
176         JsonObject resourcesProp = createServicePropertiesByType(csar);
177         resourcesProp.add("VFModule", createVfModuleProperties(csar));
178
179         Service modelService = new Service(serviceDetails, resourcesProp, 
180                 csar.getSdcNotification().getServiceVersion());
181
182         serviceRepository.save(modelService);
183         logger.info("Successfully installed the Service");
184         return modelService;
185     }
186
187     private Loop createLoopFromBlueprint(CsarHandler csar, BlueprintArtifact blueprintArtifact, Service service)
188             throws IOException, ParseException, InterruptedException {
189         Loop newLoop = new Loop();
190         newLoop.setBlueprint(blueprintArtifact.getDcaeBlueprint());
191         newLoop.setName(Loop.generateLoopName(csar.getSdcNotification().getServiceName(),
192                 csar.getSdcNotification().getServiceVersion(),
193                 blueprintArtifact.getResourceAttached().getResourceInstanceName(),
194                 blueprintArtifact.getBlueprintArtifactName()));
195         newLoop.setLastComputedState(LoopState.DESIGN);
196
197         List<MicroService> microServicesChain = chainGenerator
198                 .getChainOfMicroServices(blueprintParser.getMicroServices(blueprintArtifact.getDcaeBlueprint()));
199         if (microServicesChain.isEmpty()) {
200             microServicesChain = blueprintParser.fallbackToOneMicroService(blueprintArtifact.getDcaeBlueprint());
201         }
202         newLoop.setModelService(service);
203         newLoop.setMicroServicePolicies(
204                 createMicroServicePolicies(microServicesChain, csar, blueprintArtifact, newLoop));
205         newLoop.setOperationalPolicies(createOperationalPolicies(csar, blueprintArtifact, newLoop));
206
207         newLoop.setSvgRepresentation(svgFacade.getSvgImage(microServicesChain));
208         newLoop.setGlobalPropertiesJson(createGlobalPropertiesJson(blueprintArtifact, newLoop));
209
210         DcaeInventoryResponse dcaeResponse = queryDcaeToGetServiceTypeId(blueprintArtifact);
211         newLoop.setDcaeBlueprintId(dcaeResponse.getTypeId());
212         return newLoop;
213     }
214
215     private HashSet<OperationalPolicy> createOperationalPolicies(CsarHandler csar, BlueprintArtifact blueprintArtifact,
216             Loop newLoop) {
217         return new HashSet<>(Arrays.asList(new OperationalPolicy(Policy.generatePolicyName("OPERATIONAL",
218                 csar.getSdcNotification().getServiceName(), csar.getSdcNotification().getServiceVersion(),
219                 blueprintArtifact.getResourceAttached().getResourceInstanceName(),
220                 blueprintArtifact.getBlueprintArtifactName()), newLoop, new JsonObject())));
221     }
222
223     private HashSet<MicroServicePolicy> createMicroServicePolicies(List<MicroService> microServicesChain,
224             CsarHandler csar, BlueprintArtifact blueprintArtifact, Loop newLoop) throws IOException {
225         HashSet<MicroServicePolicy> newSet = new HashSet<>();
226
227         for (MicroService microService : microServicesChain) {
228             MicroServicePolicy microServicePolicy = new MicroServicePolicy(
229                     Policy.generatePolicyName(microService.getName(), csar.getSdcNotification().getServiceName(),
230                             csar.getSdcNotification().getServiceVersion(),
231                             blueprintArtifact.getResourceAttached().getResourceInstanceName(),
232                             blueprintArtifact.getBlueprintArtifactName()),
233                     microService.getModelType(), csar.getPolicyModelYaml().orElse(""), false,
234                     new HashSet<>(Arrays.asList(newLoop)));
235
236             newSet.add(microServicePolicy);
237             microService.setMappedNameJpa(microServicePolicy.getName());
238         }
239         return newSet;
240     }
241
242     private JsonObject createGlobalPropertiesJson(BlueprintArtifact blueprintArtifact, Loop newLoop) {
243         JsonObject globalProperties = new JsonObject();
244         globalProperties.add("dcaeDeployParameters", getAllBlueprintParametersInJson(blueprintArtifact, newLoop));
245         return globalProperties;
246     }
247
248     private static JsonObject createVfModuleProperties(CsarHandler csar) {
249         JsonObject vfModuleProps = new JsonObject();
250         // Loop on all Groups defined in the service (VFModule entries type:
251         // org.openecomp.groups.VfModule)
252         for (IEntityDetails entity : csar.getSdcCsarHelper().getEntity(
253                 EntityQuery.newBuilder(EntityTemplateType.GROUP).build(),
254                 TopologyTemplateQuery.newBuilder(SdcTypes.SERVICE).build(), false)) {
255             // Get all metadata info
256             JsonObject allVfProps = (JsonObject) JsonUtils.GSON.toJsonTree(entity.getMetadata().getAllProperties());
257             vfModuleProps.add(entity.getMetadata().getAllProperties().get("vfModuleModelName"), allVfProps);
258             // now append the properties section so that we can also have isBase,
259             // volume_group, etc ... fields under the VFmodule name
260             for (Entry<String, Property> additionalProp : entity.getProperties().entrySet()) {
261                 allVfProps.add(additionalProp.getValue().getName(),
262                         JsonUtils.GSON.toJsonTree(additionalProp.getValue().getValue()));
263             }
264         }
265         return vfModuleProps;
266     }
267
268     private static JsonObject createServicePropertiesByType(CsarHandler csar) {
269         JsonObject resourcesProp = new JsonObject();
270         // Iterate on all types defined in the tosca lib
271         for (SdcTypes type : SdcTypes.values()) {
272             JsonObject resourcesPropByType = new JsonObject();
273             // For each type, get the metadata of each nodetemplate
274             for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) {
275                 resourcesPropByType.add(nodeTemplate.getName(),
276                         JsonUtils.GSON.toJsonTree(nodeTemplate.getMetaData().getAllProperties()));
277             }
278             resourcesProp.add(type.getValue(), resourcesPropByType);
279         }
280         return resourcesProp;
281     }
282
283     private JsonObject getAllBlueprintParametersInJson(BlueprintArtifact blueprintArtifact, Loop newLoop) {
284         JsonObject node = new JsonObject();
285         Yaml yaml = new Yaml();
286         Map<String, Object> inputsNodes = ((Map<String, Object>) ((Map<String, Object>) yaml
287                 .load(blueprintArtifact.getDcaeBlueprint())).get("inputs"));
288         inputsNodes.entrySet().stream().filter(e -> !e.getKey().contains("policy_id")).forEach(elem -> {
289             Object defaultValue = ((Map<String, Object>) elem.getValue()).get("default");
290             if (defaultValue != null) {
291                 addPropertyToNode(node, elem.getKey(), defaultValue);
292             } else {
293                 node.addProperty(elem.getKey(), "");
294             }
295         });
296         // For Dublin only one micro service is expected
297         node.addProperty("policy_id", ((MicroServicePolicy) newLoop.getMicroServicePolicies().toArray()[0]).getName());
298         return node;
299     }
300
301     /**
302      * ll get the latest version of the artifact (version can be specified to DCAE
303      * call).
304      *
305      * @return The DcaeInventoryResponse object containing the dcae values
306      */
307     private DcaeInventoryResponse queryDcaeToGetServiceTypeId(BlueprintArtifact blueprintArtifact)
308             throws IOException, ParseException, InterruptedException {
309         return dcaeInventoryService.getDcaeInformation(blueprintArtifact.getBlueprintArtifactName(),
310                 blueprintArtifact.getBlueprintInvariantServiceUuid(),
311                 blueprintArtifact.getResourceAttached().getResourceInvariantUUID());
312     }
313
314     private void addPropertyToNode(JsonObject node, String key, Object value) {
315         if (value instanceof String) {
316             node.addProperty(key, (String) value);
317         } else if (value instanceof Number) {
318             node.addProperty(key, (Number) value);
319         } else if (value instanceof Boolean) {
320             node.addProperty(key, (Boolean) value);
321         } else if (value instanceof Character) {
322             node.addProperty(key, (Character) value);
323         } else {
324             node.addProperty(key, JsonUtils.GSON.toJson(value));
325         }
326     }
327 }