2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2018 Ericsson. All rights reserved.
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=========================================================
22 package org.onap.policy.distribution.reception.decoding.hpa;
24 import com.google.common.collect.ImmutableMap;
25 import com.google.gson.Gson;
26 import com.google.gson.GsonBuilder;
27 import com.google.gson.reflect.TypeToken;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
33 import java.util.regex.Matcher;
34 import java.util.regex.Pattern;
36 import org.onap.policy.distribution.reception.decoding.PolicyDecodingException;
37 import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
38 import org.onap.sdc.toscaparser.api.CapabilityAssignment;
39 import org.onap.sdc.toscaparser.api.CapabilityAssignments;
40 import org.onap.sdc.toscaparser.api.NodeTemplate;
41 import org.onap.sdc.toscaparser.api.RequirementAssignment;
42 import org.onap.sdc.toscaparser.api.RequirementAssignments;
43 import org.onap.sdc.toscaparser.api.elements.Metadata;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * Extract concerned info from NodeTemplate, currently ONLY HPA Feature.
50 * @author Libo Zhu (libo.zhu@intel.com)
52 public class ExtractFromNode {
54 private static final Logger LOGGER = LoggerFactory.getLogger(ExtractFromNode.class);
56 private static final String CONFIGURATION_VALUE = "configurationValue";
57 private static final String VDU_TYPE = "tosca.nodes.nfv.Vdu.Compute";
58 private static final String VDU_CP_TYPE = "tosca.nodes.nfv.VduCp";
59 private static final String VIRTUAL_MEM_SIZE_PATH = "virtual_memory#virtual_mem_size";
60 private static final String NUM_VIRTUAL_CPU_PATH = "virtual_cpu#num_virtual_cpu";
61 private static final String CPU_ARCHITECTURE_PATH = "virtual_cpu#cpu_architecture";
62 private static final String MEMORY_PAGE_SIZE_PATH = "virtual_memory#vdu_mem_requirements#memoryPageSize";
63 private static final String NETWORK_INTERFACE_TYPE_PATH =
64 "virtual_network_interface_requirements#network_interface_requirements#interfaceType";
65 private static final String NETWORK_PCI_PATH =
66 "virtual_network_interface_requirements#nic_io_requirements#logical_node_requirements";
67 private static final String BASIC_CAPABILITIES_HPA_FEATURE = "basicCapabilities";
68 private static final String HUGE_PAGES_HPA_FEATURE = "hugePages";
69 private static final Map<String, String> NETWORK_HPA_FEATURE_MAP =
70 ImmutableMap.of("SR-IOV", "sriovNICNetwork", "PCI-Passthrough", "pciePassthrough");
71 private static final Pattern PATTERN = Pattern.compile("(\\D*)(\\d+)(\\D*)");
72 private ISdcCsarHelper sdcCsarHelper;
73 final Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().disableHtmlEscaping().create();
75 public void setSdcCsarHelper(final ISdcCsarHelper sdcCsarHelper) {
76 this.sdcCsarHelper = sdcCsarHelper;
80 * ExtractInfo from VNF , each VNF may includes more than one VDUs and CPs return new
81 * generated OptimizationPolicy if it has got Hpa feature info or else return null.
83 * @param node the NodeTemplate
85 * @return the extracted info from input node
87 * @throws PolicyDecodingException if extract fails
89 public Content extractInfo(final NodeTemplate node) throws PolicyDecodingException {
90 final Metadata metaData = sdcCsarHelper.getNodeTemplateMetadata(node);
91 final Metadata metaDataOfService = sdcCsarHelper.getServiceMetadata();
92 LOGGER.debug("the meta data of this nodetemplate = {}", metaData);
93 final List<NodeTemplate> lnodeChild = sdcCsarHelper.getNodeTemplateChildren(node);
94 LOGGER.debug("the size of lnodeChild = {}", lnodeChild.size());
96 // Store all the VDUs under one VNF
97 final List<NodeTemplate> lnodeVdu = new ArrayList<>();
98 // Store all the Cps under one VNF
99 final List<NodeTemplate> lnodeVduCp = new ArrayList<>();
100 for (final NodeTemplate nodeChild : lnodeChild) {
101 final String type = sdcCsarHelper.getTypeOfNodeTemplate(nodeChild);
102 LOGGER.debug("the type of this nodeChild = {}", type);
103 LOGGER.debug("the meta data of this nodeChild = {}", sdcCsarHelper.getNodeTemplateMetadata(nodeChild));
104 if (type.equalsIgnoreCase(VDU_TYPE)) {
105 lnodeVdu.add(nodeChild);
106 } else if (type.equalsIgnoreCase(VDU_CP_TYPE)) {
107 lnodeVduCp.add(nodeChild);
110 LOGGER.debug("the size of vdu is = {}", lnodeVdu.size());
111 LOGGER.debug("the size of cp is = {}", lnodeVduCp.size());
113 final Content content = new Content();
114 content.getResources().add(metaData.getValue("name"));
115 content.getServices().add(metaDataOfService.getValue("name"));
116 content.setIdentity(content.getPolicyType() + "_" + metaData.getValue("name"));
117 extractInfoVdu(lnodeVdu, content);
118 extractInfoVduCp(lnodeVduCp, content);
119 if (content.getFlavorFeatures().isEmpty()) {
127 * ExtractInfofromVdu, supported hpa features, All under the capability of
128 * tosca.nodes.nfv.Vdu.Compute.
130 * @param lnodeVdu the list of Vdu node
132 * @param content to be change based on lnodeVdu
134 public void extractInfoVdu(final List<NodeTemplate> lnodeVdu, final Content content) {
135 // each VDU <=> FlavorFeature
136 for (final NodeTemplate node : lnodeVdu) {
137 final Attribute flavorAttribute = new Attribute();
138 flavorAttribute.setAttributeName("flavorName");
139 flavorAttribute.setAttributeValue("");
140 final Directive flavorDirective = new Directive();
141 flavorDirective.setType("flavor_directives");
142 flavorDirective.getAttributes().add(flavorAttribute);
143 final FlavorFeature flavorFeature = new FlavorFeature();
144 flavorFeature.setId(node.toString());
145 LOGGER.debug("the name of node = {}", node);
146 flavorFeature.getDirectives().add(flavorDirective);
148 final CapabilityAssignments capabilityAssignments = sdcCsarHelper.getCapabilitiesOf(node);
149 final CapabilityAssignment capabilityAssignment =
150 capabilityAssignments.getCapabilityByName("virtual_compute");
151 if (capabilityAssignment != null) {
152 generateBasicCapability(capabilityAssignment, flavorFeature);
153 generateHugePages(capabilityAssignment, flavorFeature);
155 content.getFlavorFeatures().add(flavorFeature);
160 * GenerateBasicCapability, supported hpa features, All under the capability of
161 * tosca.nodes.nfv.Vdu.Compute.
163 * @param capabilityAssignment represents the capability of node
165 * @param flavorFeature represents all the features of specified flavor
167 private void generateBasicCapability(final CapabilityAssignment capabilityAssignment,
168 final FlavorFeature flavorFeature) {
169 // the format is xxx MB/GB like 4096 MB
170 final String virtualMemSize =
171 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, VIRTUAL_MEM_SIZE_PATH);
172 if (virtualMemSize != null) {
173 LOGGER.debug("the virtualMemSize = {}", virtualMemSize);
174 final HpaFeatureAttribute hpaFeatureAttribute =
175 generateHpaFeatureAttribute("virtualMemSize", virtualMemSize);
176 final FlavorProperty flavorProperty = new FlavorProperty();
177 flavorProperty.setHpaFeature(BASIC_CAPABILITIES_HPA_FEATURE);
178 flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
179 flavorFeature.getFlavorProperties().add(flavorProperty);
182 // the format is int like 2
183 final String numVirtualCpu =
184 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, NUM_VIRTUAL_CPU_PATH);
185 if (numVirtualCpu != null) {
186 LOGGER.debug("the numVirtualCpu = {}", numVirtualCpu);
187 final HpaFeatureAttribute hpaFeatureAttribute = generateHpaFeatureAttribute("numVirtualCpu", numVirtualCpu);
188 final String cpuArchitecture =
189 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, CPU_ARCHITECTURE_PATH);
190 final FlavorProperty flavorProperty = new FlavorProperty();
191 flavorProperty.setHpaFeature(BASIC_CAPABILITIES_HPA_FEATURE);
192 if (cpuArchitecture != null) {
193 flavorProperty.setArchitecture(cpuArchitecture);
195 flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
196 flavorFeature.getFlavorProperties().add(flavorProperty);
201 * GenerateHpaFeatureAttribute based on the value of featureValue. the format:
202 * "hpa-attribute-key": "pciVendorId", "hpa-attribute-value": "1234", "operator": "=",
205 * @param hpaAttributeKey get from the high layer tosca DM
207 * @param featureValue get from the high layer tosca DM
210 private HpaFeatureAttribute generateHpaFeatureAttribute(final String hpaAttributeKey, final String featureValue) {
211 // based on input featureValue, return back a suitable hpaFeatureAttribute
212 final HpaFeatureAttribute hpaFeatureAttribute = new HpaFeatureAttribute();
213 hpaFeatureAttribute.setHpaAttributeKey(hpaAttributeKey);
214 final String modifiedValue = featureValue.replace(" ", "");
215 final Matcher matcher = PATTERN.matcher(modifiedValue);
216 if (matcher.find()) {
217 final String matcher1 = matcher.group(1);
218 final String matcher2 = matcher.group(2);
219 final String matcher3 = matcher.group(3);
220 LOGGER.debug("operator {} , value = {} , unit = {}", matcher1, matcher2, matcher3);
221 if (matcher.group(1).length() == 0) {
222 hpaFeatureAttribute.setOperator("=");
224 hpaFeatureAttribute.setOperator(matcher1);
226 hpaFeatureAttribute.setHpaAttributeValue(matcher2);
227 hpaFeatureAttribute.setUnit(matcher3);
229 return hpaFeatureAttribute;
233 * GenerateHugePages, supported hpa features, All under the capability of
234 * tosca.nodes.nfv.Vdu.Compute. The format is a map like: {"schemaVersion": "0",
235 * "schemaSelector": "", "hardwarePlatform": "generic", "mandatory": "true",
236 * "configurationValue": "2 MB"}
238 * @param capabilityAssignment represents the capability of node
240 * @param flavorFeature represents all the features of specified flavor
242 private void generateHugePages(final CapabilityAssignment capabilityAssignment, final FlavorFeature flavorFeature) {
243 final String memoryPageSize =
244 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, MEMORY_PAGE_SIZE_PATH);
245 LOGGER.debug("the memoryPageSize = {}", memoryPageSize);
246 if (memoryPageSize != null) {
247 final Map<String, String> retMap =
248 gson.fromJson(memoryPageSize, new TypeToken<HashMap<String, String>>() {}.getType());
249 LOGGER.debug("the retMap = {}", retMap);
250 final String memoryPageSizeValue = retMap.get(CONFIGURATION_VALUE);
251 final String mandatory = retMap.get("mandatory");
252 if (memoryPageSizeValue == null) {
255 final HpaFeatureAttribute hpaFeatureAttribute =
256 generateHpaFeatureAttribute("memoryPageSize", memoryPageSizeValue);
257 final FlavorProperty flavorProperty = new FlavorProperty();
258 flavorProperty.setHpaFeature(HUGE_PAGES_HPA_FEATURE);
259 if (mandatory != null) {
260 flavorProperty.setMandatory(mandatory);
262 flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
263 flavorFeature.getFlavorProperties().add(flavorProperty);
268 * ExtractInfoVduCp, supported hpa features, under the
269 * virtual_network_interface_requirements of tosca.nodes.nfv.VduCp.
271 * @param lnodeVduCp the list of VduCp node
273 * @param content to be change based on lnodeVduCp
274 * @throws PolicyDecodingException if extract CP fails
276 public void extractInfoVduCp(final List<NodeTemplate> lnodeVduCp, final Content content)
277 throws PolicyDecodingException {
278 // each CP will binds to a VDU so need the vdu flavor map info.
279 final Map<String, FlavorFeature> vduFlavorMap = new HashMap<>();
280 for (final FlavorFeature flavorFeature : content.getFlavorFeatures()) {
281 LOGGER.debug("the id = {}", flavorFeature.getId());
282 vduFlavorMap.put(flavorFeature.getId(), flavorFeature);
284 parseNodeVduCp(lnodeVduCp, vduFlavorMap);
288 * Parse the VduCp list.
290 * @param lnodeVduCp the lnodeVduCp
291 * @param vduFlavorMap the vduFlavorMap
292 * @throws PolicyDecodingException if any error occurs
294 private void parseNodeVduCp(final List<NodeTemplate> lnodeVduCp, final Map<String, FlavorFeature> vduFlavorMap)
295 throws PolicyDecodingException {
296 for (final NodeTemplate node : lnodeVduCp) {
297 final String interfaceType =
298 sdcCsarHelper.getNodeTemplatePropertyLeafValue(node, NETWORK_INTERFACE_TYPE_PATH);
299 LOGGER.debug("the interfaceType = {}", interfaceType);
300 Map<String, Object> retMap = new HashMap<>();
301 if (interfaceType != null) {
302 retMap = gson.fromJson(interfaceType, new TypeToken<HashMap<String, Object>>() {}.getType());
303 LOGGER.debug("the retMap = {}", retMap);
306 String networkHpaFeature;
307 if (retMap.containsKey(CONFIGURATION_VALUE)
308 && NETWORK_HPA_FEATURE_MAP.containsKey(retMap.get(CONFIGURATION_VALUE).toString())) {
309 final String interfaceTypeValue = retMap.get(CONFIGURATION_VALUE).toString();
310 networkHpaFeature = NETWORK_HPA_FEATURE_MAP.get(interfaceTypeValue);
311 LOGGER.debug(" the networkHpaFeature is = {}", networkHpaFeature);
313 LOGGER.debug(" no networkHpaFeature defined in interfaceType");
317 final RequirementAssignments requriements =
318 sdcCsarHelper.getRequirementsOf(node).getRequirementsByName("virtual_binding");
319 for (final RequirementAssignment requriement : requriements.getAll()) {
320 final String nodeTemplateName = requriement.getNodeTemplateName();
321 LOGGER.debug("getNodeTemplateName = {}", nodeTemplateName);
322 if (nodeTemplateName == null) {
325 if (!vduFlavorMap.containsKey(nodeTemplateName)) {
326 throw new PolicyDecodingException("vdu Flavor Map should contains the key " + nodeTemplateName);
328 generateNetworkFeature(networkHpaFeature, node, vduFlavorMap.get(nodeTemplateName));
334 * GenerateNetworkFeature, all pci feature are grouped into FlavorFeature together.
335 * The format is a map like: {"schemaVersion": "0", "schemaSelector": "",
336 * "hardwarePlatform": "generic", "mandatory": "true", "configurationValue": "2 MB"}
338 * @param networkHpaFeature represents the specified Hpa feature
339 * @param node represents the CP Node
340 * @param flavorFeature represents all the features of specified flavor
342 private void generateNetworkFeature(final String networkHpaFeature, final NodeTemplate node,
343 final FlavorFeature flavorFeature) {
344 final FlavorProperty flavorProperty = new FlavorProperty();
345 flavorProperty.setHpaFeature(networkHpaFeature);
346 final String[] pciKeys = {"pciVendorId", "pciDeviceId", "pciNumDevices", "physicalNetwork"};
347 for (final String pciKey : pciKeys) {
348 LOGGER.debug("the pciKey = {}", pciKey);
349 final String pciKeyPath = NETWORK_PCI_PATH + "#" + pciKey;
350 final String pciValue = sdcCsarHelper.getNodeTemplatePropertyLeafValue(node, pciKeyPath);
351 if (pciValue != null) {
352 LOGGER.debug("the pciValue = {}", pciValue);
353 final Map<String, String> retMap =
354 gson.fromJson(pciValue, new TypeToken<HashMap<String, String>>() {}.getType());
355 final String pciConfigValue = retMap.get(CONFIGURATION_VALUE);
356 if (pciConfigValue == null) {
359 final HpaFeatureAttribute hpaFeatureAttribute = generateHpaFeatureAttribute(pciKey, pciConfigValue);
360 flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
363 flavorFeature.getFlavorProperties().add(flavorProperty);