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