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