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