3 * * ============LICENSE_START=======================================================
4 * * Copyright (C) 2019 Nordix Foundation.
5 * * ================================================================================
6 * * Licensed under the Apache License, Version 2.0 (the "License");
7 * * you may not use this file except in compliance with the License.
8 * * You may obtain a copy of the License at
10 * * http://www.apache.org/licenses/LICENSE-2.0
12 * * Unless required by applicable law or agreed to in writing, software
13 * * distributed under the License is distributed on an "AS IS" BASIS,
14 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * * See the License for the specific language governing permissions and
16 * * limitations under the License.
18 * * SPDX-License-Identifier: Apache-2.0
19 * * ============LICENSE_END=========================================================
23 package org.openecomp.core.impl;
25 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CONSTRAINTS;
26 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE;
27 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION;
28 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA;
29 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GET_INPUT;
30 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.PROPERTIES;
31 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIRED;
32 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
34 import java.util.AbstractMap;
35 import java.util.HashMap;
36 import java.util.List;
38 import java.util.Objects;
39 import java.util.stream.Collectors;
40 import org.apache.commons.collections.MapUtils;
41 import org.onap.sdc.tosca.datatypes.model.Constraint;
42 import org.onap.sdc.tosca.datatypes.model.EntrySchema;
43 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
44 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
45 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
46 import org.onap.sdc.tosca.datatypes.model.TopologyTemplate;
47 import org.openecomp.core.converter.ServiceTemplateReaderService;
48 import org.openecomp.sdc.tosca.services.DataModelUtil;
50 public class ToscaSolConverterPnf extends AbstractToscaSolConverter {
52 private static final String PNF_EXT_CP_TYPE = "tosca.nodes.nfv.PnfExtCp";
53 private static final String EXT_CP_TYPE = "org.openecomp.resource.cp.v2.extCP";
54 private static final String LAYER_PROTOCOLS = "layer_protocols";
55 private static final String ASSIGNMENT_METHOD = "assingment_method";
56 private static final String DHCP = "dhcp";
57 private static final String IP_V4 = "ipv4";
58 private static final String IP_V6 = "ipv6";
59 private static final String IP_VERSION = "ip_version";
60 private static final String IP_REQUIREMENTS = "ip_requirements";
61 private static final String IP_REQUIREMENTS_TYPE = "org.openecomp.datatypes.network.IpRequirements";
62 private ServiceTemplate serviceTemplate;
63 private ServiceTemplateReaderService readerService;
66 * For PNF the node templates are converted ETSI node types to ecomp node types. All other data i.e. inputs,
67 * substitution mappings and outputs are simply dropped at this stage. The equivalent ecomp data will be added when
68 * the vsp is imported into the catalog.
70 * @param serviceTemplate - the service template
71 * @param readerService - the reader service
74 public void convertTopologyTemplate(final ServiceTemplate serviceTemplate,
75 final ServiceTemplateReaderService readerService) {
76 this.serviceTemplate = serviceTemplate;
77 this.readerService = readerService;
78 convertNodeTemplatesToEcompTypes();
79 addEmptyNodeTemplatesIfNoneDefined();
83 * Copies a input from the reader (input) to the service template (output)
84 * @param inputName the name of the input to copy
86 private void copyTopologyTemplateInput(final String inputName) {
87 final Map<String, Object> inputMap = readerService.getInputs();
88 if (MapUtils.isEmpty(inputMap)) {
91 final Map propertyMap = (Map) inputMap.get(inputName);
92 final Object requiredObj = propertyMap.get(REQUIRED.getElementName());
93 final Object constraintsObj = propertyMap.get(CONSTRAINTS.getElementName());
94 final Object entrySchemaObj = propertyMap.get(ENTRY_SCHEMA.getElementName());
96 EntrySchema entrySchema = null;
97 if (entrySchemaObj instanceof Map) {
98 final Map entrySchemaMap = ((Map) entrySchemaObj);
99 entrySchema = parseEntrySchema(entrySchemaMap);
101 final ParameterDefinition parameterDefinition =
102 DataModelUtil.createParameterDefinition(
103 (String) propertyMap.get(TYPE.getElementName()),
104 (String) propertyMap.get(DESCRIPTION.getElementName()),
105 requiredObj instanceof Boolean ? (Boolean) requiredObj : null,
106 constraintsObj instanceof List ? (List<Constraint>) constraintsObj : null,
108 propertyMap.get(DEFAULT_VALUE.getElementName()));
111 .addInputParameterToTopologyTemplate(serviceTemplate, inputName, parameterDefinition);
115 * PNF only has nfv.PNF and nfv.PnfExtCp types defined in ETSI SOL001 v2.5.1. - The PNF is mapped to the outer
116 * Abstract PNF container in ecomp model and hence nfv.PNF is dropped here. - nfv.PnfExtCp is mapped to ecomp
119 private void convertNodeTemplatesToEcompTypes() {
120 final Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
121 if (MapUtils.isEmpty(nodeTemplates)) {
125 nodeTemplates.entrySet().stream()
126 .filter(nodeTemplateEntry ->
127 PNF_EXT_CP_TYPE.equals(((Map<String, Object>) nodeTemplateEntry.getValue()).get(TYPE.getElementName())))
128 .forEach(nodeTemplateEntry ->
129 DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(),
130 convertToEcompConnectionPointNodeType((Map<String, Object>) nodeTemplateEntry.getValue())));
134 * Converts from the ETSI PnfExtCp node type to ecomp v2.extCP node type The following properties are mapped -
135 * layer_protocols is mapped to ip_requirements if it contains the values ipv4 and/or ipv6. All other data e.g.
136 * remaining properties, requirements, capabilities are not mapped over to ecomp equivalent
138 * @param pnfExtCp - the ETSI PnfExtCp map
139 * @return ecomp v2.extCP node type
141 private NodeTemplate convertToEcompConnectionPointNodeType(final Map<String, Object> pnfExtCp) {
142 final NodeTemplate nodeTemplate = new NodeTemplate();
143 nodeTemplate.setType(EXT_CP_TYPE);
144 final Map<String, Object> properties = (Map<String, Object>) pnfExtCp.get(PROPERTIES.getElementName());
146 properties.entrySet().stream()
147 .filter(propertyMap -> LAYER_PROTOCOLS.equals(propertyMap.getKey()))
148 .forEach(propertyMap -> {
149 final Object propertyValue = propertyMap.getValue();
150 if (propertyValue instanceof List) {
151 // layer_protocols: [ ipv4, ipv6, ... ]
152 final List<Map<String, Object>> ipRequirements =
153 convertToIpRequirementsProperty((List<String>) propertyValue);
154 if (!ipRequirements.isEmpty()) {
155 final Map<String, Object> convertedProperties = new HashMap<>();
156 convertedProperties.put(IP_REQUIREMENTS, ipRequirements);
157 nodeTemplate.setProperties(convertedProperties);
159 } else if (propertyValue instanceof AbstractMap) {
160 final Map propertyValueMap = (Map) propertyValue;
161 if (propertyValueMap.containsKey(GET_INPUT.getElementName())) {
162 // layer_protocols: {get_input: anInputName}
163 final Map<String, Object> convertedProperties = new HashMap<>();
164 convertedProperties.put(IP_REQUIREMENTS, propertyValueMap);
165 nodeTemplate.setProperties(convertedProperties);
166 final String getInputValue = (String) propertyValueMap.get(GET_INPUT.getElementName());
167 if (!isInputAlreadyAdded(getInputValue)) {
168 copyTopologyTemplateInput(getInputValue);
169 parseLayerProtocolsInputToIpRequirements(getInputValue);
178 * Checks if a topology template input was already added
180 * @param inputName The name of the input to check
182 * {@code true} if the input was found in the topology template structure
184 private boolean isInputAlreadyAdded(final String inputName) {
185 final TopologyTemplate topologyTemplate = serviceTemplate.getTopology_template();
186 if (topologyTemplate == null) {
190 final Map<String, ParameterDefinition> inputMap = topologyTemplate.getInputs();
191 if (MapUtils.isNotEmpty(inputMap)) {
192 return inputMap.keySet().contains(inputName);
199 * Parses a layer_protocol input to org.openecomp.datatypes.network.IpRequirements ecomp type.
201 * @param inputName The name of the input to parse
204 private void parseLayerProtocolsInputToIpRequirements(final String inputName) {
205 final TopologyTemplate topologyTemplate = serviceTemplate.getTopology_template();
206 final ParameterDefinition layerProtocolsInput = topologyTemplate.getInputs().get(inputName);
207 final EntrySchema entrySchema = layerProtocolsInput.getEntry_schema();
208 entrySchema.setType(IP_REQUIREMENTS_TYPE);
209 final List<String> defaultLayerProtocolList = (List<String>) layerProtocolsInput.get_default();
210 layerProtocolsInput.set_default(convertToIpRequirementsProperty(defaultLayerProtocolList));
214 * Converts each layer_protocols entry that is either {@link #IP_V4} or {@link #IP_V6} to the ecomp
215 * {@link #IP_REQUIREMENTS_TYPE}, ignoring other entry types.
217 * @param layerProtocols the PnfExtCp layer_protocols list
219 * A list of map representing a {@link #IP_REQUIREMENTS_TYPE} ecomp type
221 private List<Map<String, Object>> convertToIpRequirementsProperty(final List<String> layerProtocols) {
222 return layerProtocols.stream()
223 .filter(layerProtocol -> IP_V4.equals(layerProtocol) || IP_V6.equals(layerProtocol))
224 .map(this::createIpRequirementsEntry)
225 .collect(Collectors.toList());
229 * Creates a {@link #IP_REQUIREMENTS_TYPE} based on the ip version
230 * @param ipVersion the provided ip version, either {@link #IP_V4} or {@link #IP_V6}
232 * A map representing an {@link #IP_REQUIREMENTS_TYPE} ecomp type
234 private Map<String, Object> createIpRequirementsEntry(final String ipVersion) {
235 final int version = IP_V4.equals(ipVersion) ? 4 : 6;
236 final Map<String, Object> result = new HashMap<>();
237 result.put(IP_VERSION, version);
238 result.put(ASSIGNMENT_METHOD, DHCP);
243 * Fills missing required entries in the service template. Checks for topology_template entry and
244 * topology_template->node_templates entry.
246 private void addEmptyNodeTemplatesIfNoneDefined() {
247 TopologyTemplate topologyTemplate = serviceTemplate.getTopology_template();
248 if (Objects.isNull(topologyTemplate)) {
249 topologyTemplate = new TopologyTemplate();
250 serviceTemplate.setTopology_template(topologyTemplate);
252 if (topologyTemplate.getNode_templates() == null) {
253 topologyTemplate.setNode_templates(new HashMap<>());
258 * Parses an input entry schema
260 * @param entrySchemaMap the descriptor input entry schema map
262 * A parsed entry schema based on the provided map
264 private EntrySchema parseEntrySchema(Map entrySchemaMap) {
265 return DataModelUtil.createEntrySchema((String) entrySchemaMap.get(TYPE.getElementName())
266 , (String) entrySchemaMap.get(DESCRIPTION.getElementName())
267 , (List<Constraint>) entrySchemaMap.get(CONSTRAINTS.getElementName())