2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.vendorsoftwareproduct.services;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.sdc.common.errors.CoreException;
26 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
27 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
28 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
29 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
30 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
31 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
32 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
33 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
34 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
35 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
36 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplateErrorBuilder;
37 import org.openecomp.sdc.tosca.errors.ToscaMissingSubstitutionMappingForReqCapErrorBuilder;
38 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
39 import org.openecomp.sdc.tosca.services.ToscaConstants;
40 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
41 import org.openecomp.sdc.tosca.services.yamlutil.ToscaExtensionYamlUtil;
42 import org.openecomp.sdc.vendorsoftwareproduct.types.ExtractCompositionDataContext;
43 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
44 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
45 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
46 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
47 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 import java.util.ArrayList;
52 import java.util.HashMap;
53 import java.util.List;
55 import java.util.Optional;
58 * The type Composition data extractor.
60 public class CompositionDataExtractor {
63 * The constant logger.
65 protected static Logger logger;
66 private static ToscaAnalyzerService toscaAnalyzerService;
69 logger = LoggerFactory.getLogger(CompositionDataExtractor.class);
70 toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
74 * Extract service composition data composition data.
76 * @param toscaServiceModel the tosca service model
77 * @return the composition data
79 public static CompositionData extractServiceCompositionData(ToscaServiceModel toscaServiceModel) {
80 ExtractCompositionDataContext context = new ExtractCompositionDataContext();
81 String entryDefinitionServiceTemplateFileName =
82 toscaServiceModel.getEntryDefinitionServiceTemplate();
83 ServiceTemplate entryDefinitionServiceTemplate =
84 toscaServiceModel.getServiceTemplates().get(entryDefinitionServiceTemplateFileName);
85 extractServiceCompositionData(entryDefinitionServiceTemplateFileName,
86 entryDefinitionServiceTemplate, toscaServiceModel, context);
88 CompositionData compositionData = new CompositionData();
89 compositionData.setNetworks(context.getNetworks());
90 compositionData.setComponents(context.getComponents());
91 return compositionData;
94 private static void extractServiceCompositionData(String serviceTemplateFileName,
95 ServiceTemplate serviceTemplate,
96 ToscaServiceModel toscaServiceModel,
97 ExtractCompositionDataContext context) {
98 if (context.getHandledServiceTemplates().contains(serviceTemplateFileName)) {
101 context.addNetworks(extractNetworks(serviceTemplate, toscaServiceModel));
102 extractComponents(serviceTemplate, toscaServiceModel, context);
103 handleSubstitution(serviceTemplate, toscaServiceModel, context);
104 context.addHandledServiceTemplates(serviceTemplateFileName);
107 private static void handleSubstitution(ServiceTemplate serviceTemplate,
108 ToscaServiceModel toscaServiceModel,
109 ExtractCompositionDataContext context) {
110 Map<String, NodeTemplate> substitutableNodeTemplates =
111 toscaAnalyzerService.getSubstitutableNodeTemplates(serviceTemplate);
113 if (substitutableNodeTemplates != null) {
114 for (String substitutableNodeTemplateId : substitutableNodeTemplates.keySet()) {
115 handleSubstitutableNodeTemplate(serviceTemplate, toscaServiceModel,
116 substitutableNodeTemplateId,
117 substitutableNodeTemplates.get(substitutableNodeTemplateId), context);
122 private static void handleSubstitutableNodeTemplate(ServiceTemplate serviceTemplate,
123 ToscaServiceModel toscaServiceModel,
124 String substitutableNodeTemplateId,
125 NodeTemplate substitutableNodeTemplate,
126 ExtractCompositionDataContext context) {
127 ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
128 Optional<String> substituteServiceTemplateFileName = toscaAnalyzerService
129 .getSubstituteServiceTemplateName(substitutableNodeTemplateId, substitutableNodeTemplate);
130 if (!substituteServiceTemplateFileName.isPresent()) {
131 throw new CoreException(
132 new ToscaInvalidSubstituteNodeTemplateErrorBuilder(substitutableNodeTemplateId).build());
134 if (context.getHandledServiceTemplates().contains(substituteServiceTemplateFileName.get())) {
138 ServiceTemplate substituteServiceTemplate =
139 toscaServiceModel.getServiceTemplates().get(substituteServiceTemplateFileName.get());
140 extractServiceCompositionData(substituteServiceTemplateFileName.get(),
141 substituteServiceTemplate, toscaServiceModel, context);
143 List<Map<String, RequirementAssignment>> substitutableRequirements =
144 substitutableNodeTemplate.getRequirements();
146 if (CollectionUtils.isEmpty(substitutableRequirements)) {
150 for (Map<String, RequirementAssignment> substitutableReq : substitutableRequirements) {
151 substitutableReq.keySet().stream().filter(reqId -> {
152 RequirementAssignment reqAssignment = toscaExtensionYamlUtil
153 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(substitutableReq.get(reqId)),
154 RequirementAssignment.class);
155 return isLinkToNetworkRequirementAssignment(reqAssignment);
156 }).forEach(reqId -> {
157 RequirementAssignment linkToNetworkRequirement = toscaExtensionYamlUtil
158 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(substitutableReq.get(reqId)),
159 RequirementAssignment.class);
160 String connectedNodeId = linkToNetworkRequirement.getNode();
161 Optional<NodeTemplate> connectedNodeTemplate =
162 toscaAnalyzerService.getNodeTemplateById(serviceTemplate, connectedNodeId);
164 if (connectedNodeTemplate.isPresent() && toscaAnalyzerService
165 .isTypeOf(connectedNodeTemplate.get(), ToscaNodeType.NETWORK.getDisplayName(),
166 serviceTemplate, toscaServiceModel)) {
167 Optional<Map.Entry<String, NodeTemplate>> mappedNodeTemplate = toscaAnalyzerService
168 .getSubstitutionMappedNodeTemplateByExposedReq(
169 substituteServiceTemplateFileName.get(), substituteServiceTemplate, reqId);
170 if (!mappedNodeTemplate.isPresent()) {
171 throw new CoreException(new ToscaMissingSubstitutionMappingForReqCapErrorBuilder(
172 ToscaMissingSubstitutionMappingForReqCapErrorBuilder.MappingExposedEntry
173 .REQUIREMENT, connectedNodeId).build());
176 if (toscaAnalyzerService.isTypeOf(mappedNodeTemplate.get().getValue(),
177 ToscaNodeType.NETWORK_PORT.getDisplayName(), serviceTemplate, toscaServiceModel)) {
178 Nic port = context.getNics().get(mappedNodeTemplate.get().getKey());
180 port.setNetworkName(connectedNodeId);
183 "Different ports define for the same component which is used in different "
184 + "substitution service templates.");
187 } else if (!connectedNodeTemplate.isPresent()) {
188 throw new CoreException(
189 new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", connectedNodeId).build());
195 private static boolean isLinkToNetworkRequirementAssignment(RequirementAssignment requirement) {
196 return toscaAnalyzerService.isDesiredRequirementAssignment(requirement,
197 ToscaCapabilityType.NETWORK_LINKABLE.getDisplayName(), null,
198 ToscaRelationshipType.NETWORK_LINK_TO.getDisplayName());
202 private static void connectPortToNetwork(Nic port, NodeTemplate portNodeTemplate) {
203 List<RequirementAssignment> linkRequirementsToNetwork =
204 toscaAnalyzerService.getRequirements(portNodeTemplate, ToscaConstants.LINK_REQUIREMENT_ID);
206 //port is connected to one network
207 for (RequirementAssignment linkRequirementToNetwork : linkRequirementsToNetwork) {
208 port.setNetworkName(linkRequirementToNetwork.getNode());
214 return Map with key - compute node template id, value - list of connected port node template id
216 private static Map<String, List<String>> getComputeToPortsConnection(
217 Map<String, NodeTemplate> portNodeTemplates) {
218 Map<String, List<String>> computeToPortConnection = new HashMap<>();
219 if (MapUtils.isEmpty(portNodeTemplates)) {
220 return computeToPortConnection;
222 for (String portId : portNodeTemplates.keySet()) {
223 List<RequirementAssignment> bindingRequirementsToCompute = toscaAnalyzerService
224 .getRequirements(portNodeTemplates.get(portId), ToscaConstants.BINDING_REQUIREMENT_ID);
225 for (RequirementAssignment bindingRequirementToCompute : bindingRequirementsToCompute) {
226 computeToPortConnection
227 .putIfAbsent(bindingRequirementToCompute.getNode(), new ArrayList<>());
228 computeToPortConnection.get(bindingRequirementToCompute.getNode()).add(portId);
233 return computeToPortConnection;
236 private static void extractComponents(ServiceTemplate serviceTemplate,
237 ToscaServiceModel toscaServiceModel,
238 ExtractCompositionDataContext context) {
239 Map<String, NodeTemplate> computeNodeTemplates = toscaAnalyzerService
240 .getNodeTemplatesByType(serviceTemplate, ToscaNodeType.COMPUTE.getDisplayName(),
242 if (MapUtils.isEmpty(computeNodeTemplates)) {
245 Map<String, NodeTemplate> portNodeTemplates = toscaAnalyzerService
246 .getNodeTemplatesByType(serviceTemplate, ToscaNodeType.NETWORK_PORT.getDisplayName(),
248 Map<String, List<String>> computeToPortsConnection =
249 getComputeToPortsConnection(portNodeTemplates);
250 Map<String, List<String>> computesGroupedByType =
251 getNodeTemplatesGroupedByType(computeNodeTemplates);
253 computesGroupedByType.keySet()
256 !context.getCreatedComponents().contains(nodeType))
257 .forEach(nodeType -> extractComponent(serviceTemplate, computeToPortsConnection,
258 computesGroupedByType, nodeType, context));
261 private static void extractComponent(ServiceTemplate serviceTemplate,
262 Map<String, List<String>> computeToPortsConnection,
263 Map<String, List<String>> computesGroupedByType,
264 String computeNodeType,
265 ExtractCompositionDataContext context) {
266 ComponentData component = new ComponentData();
267 component.setName(computeNodeType);
268 component.setDisplayName(getComponentDisplayName(component.getName()));
269 Component componentModel = new Component();
270 componentModel.setData(component);
272 String computeId = computesGroupedByType.get(computeNodeType).get(0);
273 List<String> connectedPortIds = computeToPortsConnection.get(computeId);
275 if (connectedPortIds != null) {
276 componentModel.setNics(new ArrayList<>());
277 for (String portId : connectedPortIds) {
278 Nic port = extractPort(serviceTemplate, portId);
279 componentModel.getNics().add(port);
280 context.addNic(portId, port);
283 context.addComponent(componentModel);
284 context.getCreatedComponents().add(computeNodeType);
287 private static Nic extractPort(ServiceTemplate serviceTemplate, String portNodeTemplateId) {
288 Optional<NodeTemplate> portNodeTemplate =
289 toscaAnalyzerService.getNodeTemplateById(serviceTemplate, portNodeTemplateId);
290 if (portNodeTemplate.isPresent()) {
291 Nic port = new Nic();
292 port.setName(portNodeTemplateId);
293 connectPortToNetwork(port, portNodeTemplate.get());
296 throw new CoreException(
297 new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", portNodeTemplateId).build());
302 private static Map<String, List<String>> getNodeTemplatesGroupedByType(
303 Map<String, NodeTemplate> nodeTemplates) {
304 Map<String, List<String>> nodeTemplatesGrouped =
305 new HashMap<>(); //key - node type, value - list of node ids with this type
306 for (String nodeId : nodeTemplates.keySet()) {
307 String nodeType = nodeTemplates.get(nodeId).getType();
308 nodeTemplatesGrouped.putIfAbsent(nodeType, new ArrayList<>());
309 nodeTemplatesGrouped.get(nodeType).add(nodeId);
311 return nodeTemplatesGrouped;
314 private static List<Network> extractNetworks(ServiceTemplate serviceTemplate,
315 ToscaServiceModel toscaServiceModel) {
316 List<Network> networks = new ArrayList<>();
317 Map<String, NodeTemplate> networkNodeTemplates = toscaAnalyzerService
318 .getNodeTemplatesByType(serviceTemplate, ToscaNodeType.NETWORK.getDisplayName(),
320 if (MapUtils.isEmpty(networkNodeTemplates)) {
323 for (String networkId : networkNodeTemplates.keySet()) {
324 Network network = new Network();
325 network.setName(networkId);
326 Optional<Boolean> networkDhcpValue =
327 getNetworkDhcpValue(serviceTemplate, networkNodeTemplates.get(networkId));
328 network.setDhcp(networkDhcpValue.isPresent() ? networkDhcpValue.get() : true);
329 networks.add(network);
335 //dhcp default value is true
336 private static Optional<Boolean> getNetworkDhcpValue(ServiceTemplate serviceTemplate,
337 NodeTemplate networkNodeTemplate) {
338 if (networkNodeTemplate == null) {
339 return Optional.empty();
341 if (networkNodeTemplate.getProperties() == null
342 || networkNodeTemplate.getProperties().get(ToscaConstants.DHCP_ENABLED_PROPERTY_NAME)
344 return Optional.of(true);
348 networkNodeTemplate.getProperties().get(ToscaConstants.DHCP_ENABLED_PROPERTY_NAME);
349 if (dhcp instanceof String) {
350 return Optional.of(Boolean.valueOf((String) dhcp));
351 } else if (dhcp instanceof Boolean) {
352 return Optional.of((Boolean) dhcp);
353 } else if (dhcp instanceof Map) {
354 String inputParameterName =
355 (String) ((Map) dhcp).get(ToscaFunctions.GET_INPUT.getDisplayName());
356 if (inputParameterName != null) {
357 ParameterDefinition inputParameterDefinition =
358 serviceTemplate.getTopology_template().getInputs().get(inputParameterName);
359 if (inputParameterDefinition != null) {
360 if (inputParameterDefinition.get_default() != null) {
361 return Optional.of(Boolean.valueOf(inputParameterDefinition.get_default().toString()));
364 throw new CoreException(
365 new ToscaInvalidEntryNotFoundErrorBuilder("Input Parameter", inputParameterName)
371 return Optional.of(true);
374 private static String getComponentDisplayName(String componentName) {
375 if (componentName == null) {
378 String delimiterChar = ".";
379 if (componentName.contains(delimiterChar)) {
380 return componentName.substring(componentName.lastIndexOf(delimiterChar) + 1);
382 return componentName;