579454c5c87e0262538d485b425d77f604960805
[policy/distribution.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.distribution.reception.decoding.pdpx;
22
23 import com.google.common.collect.ImmutableMap;
24 import com.google.gson.Gson;
25 import com.google.gson.GsonBuilder;
26 import com.google.gson.reflect.TypeToken;
27
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
35 import org.onap.policy.common.logging.flexlogger.FlexLogger;
36 import org.onap.policy.common.logging.flexlogger.Logger;
37 import org.onap.policy.distribution.reception.decoding.PolicyDecodingException;
38 import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
39 import org.onap.sdc.toscaparser.api.CapabilityAssignment;
40 import org.onap.sdc.toscaparser.api.CapabilityAssignments;
41 import org.onap.sdc.toscaparser.api.NodeTemplate;
42 import org.onap.sdc.toscaparser.api.RequirementAssignment;
43 import org.onap.sdc.toscaparser.api.RequirementAssignments;
44 import org.onap.sdc.toscaparser.api.elements.Metadata;
45
46 /**
47  * Extract concerned info from NodeTemplate, currently ONLY HPA Feature.
48  *
49  * @author Libo Zhu (libo.zhu@intel.com)
50  */
51 public class ExtractFromNode {
52
53     private static final String CONFIGURATION_VALUE = "configurationValue";
54     private static final Logger LOGGER = FlexLogger.getLogger(ExtractFromNode.class);
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_memory_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 generated PdpxPolicy if it has
79      * 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         Metadata metaData = sdcCsarHelper.getNodeTemplateMetadata(node);
89         LOGGER.debug("the meta data of this nodetemplate = " + metaData);
90         final List<NodeTemplate> lnodeChild = sdcCsarHelper.getNodeTemplateChildren(node);
91         LOGGER.debug("the size of lnodeChild = " + lnodeChild.size());
92
93         // Store all the VDUs under one VNF
94         final List<NodeTemplate> lnodeVdu = new ArrayList<>();
95         // Store all the Cps under one VNF
96         final List<NodeTemplate> lnodeVduCp = new ArrayList<>();
97         for (final NodeTemplate nodeChild : lnodeChild) {
98             final String type = sdcCsarHelper.getTypeOfNodeTemplate(nodeChild);
99             LOGGER.debug("the type of this nodeChild = " + type);
100             LOGGER.debug("the meta data of this nodeChild = " + sdcCsarHelper.getNodeTemplateMetadata(nodeChild));
101             if (type.equalsIgnoreCase(VDU_TYPE)) {
102                 lnodeVdu.add(nodeChild);
103             } else if (type.equalsIgnoreCase(VDU_CP_TYPE)) {
104                 lnodeVduCp.add(nodeChild);
105             }
106         }
107         LOGGER.debug("the size of vdu is =" + lnodeVdu.size());
108         LOGGER.debug("the size of cp is =" + lnodeVduCp.size());
109
110         final Content content = new Content();
111         content.getResources().add(metaData.getValue("name"));
112         content.setIdentity(content.getPolicyType() + "_" + metaData.getValue("name"));
113         extractInfoVdu(lnodeVdu, content);
114         extractInfoVduCp(lnodeVduCp, content);
115         if (content.getFlavorFeatures().isEmpty()) {
116             return null;
117         }
118         return content;
119     }
120
121
122     /**
123      * ExtractInfofromVdu, supported hpa features, All under the capability of tosca.nodes.nfv.Vdu.Compute.
124      *
125      * @param lnodeVdu the list of Vdu node
126      *
127      * @param content to be change based on lnodeVdu
128      */
129     public void extractInfoVdu(final List<NodeTemplate> lnodeVdu, final Content content) {
130         // each VDU <=> FlavorFeature
131         for (final NodeTemplate node : lnodeVdu) {
132             final Attribute flavorAttribute = new Attribute();
133             flavorAttribute.setAttributeName("flavorName");
134             flavorAttribute.setAttributeValue("");
135             final Directive flavorDirective = new Directive();
136             flavorDirective.setType("flavor_directives");
137             flavorDirective.getAttributes().add(flavorAttribute);
138             final FlavorFeature flavorFeature = new FlavorFeature();
139             flavorFeature.setId(node.toString());
140             LOGGER.debug("the name of node =" + node.toString());
141             flavorFeature.getDirectives().add(flavorDirective);
142
143             final CapabilityAssignments capabilityAssignments = sdcCsarHelper.getCapabilitiesOf(node);
144             final CapabilityAssignment capabilityAssignment =
145                     capabilityAssignments.getCapabilityByName("virtual_compute");
146             if (capabilityAssignment != null) {
147                 generateBasicCapability(capabilityAssignment, flavorFeature);
148                 generateHugePages(capabilityAssignment, flavorFeature);
149             }
150             content.getFlavorFeatures().add(flavorFeature);
151         }
152     }
153
154     /**
155      * GenerateBasicCapability, supported hpa features, All under the capability of tosca.nodes.nfv.Vdu.Compute.
156      *
157      * @param capabilityAssignment represents the capability of node
158      *
159      * @param flavorFeature represents all the features of specified flavor
160      */
161     private void generateBasicCapability(final CapabilityAssignment capabilityAssignment,
162             final FlavorFeature flavorFeature) {
163         // the format is xxx MB/GB like 4096 MB
164         final String virtualMemSize =
165                 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, VIRTUAL_MEM_SIZE_PATH);
166         if (virtualMemSize != null) {
167             LOGGER.debug("the virtualMemSize = " + virtualMemSize);
168             final HpaFeatureAttribute hpaFeatureAttribute =
169                     generateHpaFeatureAttribute("virtualMemSize", virtualMemSize);
170             final FlavorProperty flavorProperty = new FlavorProperty();
171             flavorProperty.setHpaFeature(BASIC_CAPABILITIES_HPA_FEATURE);
172             flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
173             flavorFeature.getFlavorProperties().add(flavorProperty);
174         }
175
176         // the format is int like 2
177         final String numVirtualCpu =
178                 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, NUM_VIRTUAL_CPU_PATH);
179         if (numVirtualCpu != null) {
180             LOGGER.debug("the numVirtualCpu = " + numVirtualCpu);
181             final HpaFeatureAttribute hpaFeatureAttribute = generateHpaFeatureAttribute("numVirtualCpu", numVirtualCpu);
182             final String cpuArchitecture =
183                     sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, CPU_ARCHITECTURE_PATH);
184             final FlavorProperty flavorProperty = new FlavorProperty();
185             flavorProperty.setHpaFeature(BASIC_CAPABILITIES_HPA_FEATURE);
186             if (cpuArchitecture != null) {
187                 flavorProperty.setArchitecture(cpuArchitecture);
188             }
189             flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
190             flavorFeature.getFlavorProperties().add(flavorProperty);
191         }
192     }
193
194     /**
195      * GenerateHpaFeatureAttribute based on the value of featureValue. the format: "hpa-attribute-key": "pciVendorId",
196      * "hpa-attribute-value": "1234", "operator": "=", "unit": "xxx".
197      *
198      * @param hpaAttributeKey get from the high layer tosca DM
199      *
200      * @param featureValue get from the high layer tosca DM
201      *
202      */
203     private HpaFeatureAttribute generateHpaFeatureAttribute(final String hpaAttributeKey, final String featureValue) {
204         // based on input featureValue, return back a suitable hpaFeatureAttribute
205         final HpaFeatureAttribute hpaFeatureAttribute = new HpaFeatureAttribute();
206         hpaFeatureAttribute.setHpaAttributeKey(hpaAttributeKey);
207         final String modifiedValue = featureValue.replace(" ", "");
208         final Matcher matcher = PATTERN.matcher(modifiedValue);
209         if (matcher.find()) {
210             LOGGER.debug("operator " + matcher.group(1) + ", value = " + matcher.group(2)
211                     + ", unit = " + matcher.group(3));
212             if ( matcher.group(1).length() == 0 ) {
213                 hpaFeatureAttribute.setOperator("=");
214             } else {
215                 hpaFeatureAttribute.setOperator(matcher.group(1));
216             }
217             hpaFeatureAttribute.setHpaAttributeValue(matcher.group(2));
218             hpaFeatureAttribute.setUnit(matcher.group(3));
219         }
220         return hpaFeatureAttribute;
221     }
222
223     /**
224      * GenerateHugePages, supported hpa features, All under the capability of tosca.nodes.nfv.Vdu.Compute. The format is
225      * a map like: {"schemaVersion": "0", "schemaSelector": "", "hardwarePlatform": "generic", "mandatory": "true",
226      * "configurationValue": "2 MB"}
227      *
228      * @param capabilityAssignment represents the capability of node
229      *
230      * @param flavorFeature represents all the features of specified flavor
231      */
232     private void generateHugePages(final CapabilityAssignment capabilityAssignment, final FlavorFeature flavorFeature) {
233         final String memoryPageSize =
234                 sdcCsarHelper.getCapabilityPropertyLeafValue(capabilityAssignment, MEMORY_PAGE_SIZE_PATH);
235         LOGGER.debug("the memoryPageSize = " + memoryPageSize);
236         if (memoryPageSize != null) {
237             final Map<String, String> retMap =
238                     gson.fromJson(memoryPageSize, new TypeToken<HashMap<String, String>>() {}.getType());
239             LOGGER.debug("the retMap = " + retMap);
240             final String memoryPageSizeValue = retMap.get(CONFIGURATION_VALUE);
241             final String mandatory = retMap.get("mandatory");
242             if (memoryPageSizeValue == null) {
243                 return;
244             }
245             final HpaFeatureAttribute hpaFeatureAttribute =
246                     generateHpaFeatureAttribute("memoryPageSize", memoryPageSizeValue);
247             final FlavorProperty flavorProperty = new FlavorProperty();
248             flavorProperty.setHpaFeature(HUGE_PAGES_HPA_FEATURE);
249             if (mandatory != null) {
250                 flavorProperty.setMandatory(mandatory);
251             }
252             flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
253             flavorFeature.getFlavorProperties().add(flavorProperty);
254         }
255     }
256
257     /**
258      * ExtractInfoVduCp, supported hpa features, under the virtual_network_interface_requirements of
259      * tosca.nodes.nfv.VduCp.
260      *
261      * @param lnodeVduCp the list of VduCp node
262      *
263      * @param content to be change based on lnodeVduCp
264      * @throws PolicyDecodingException if extract CP fails
265      */
266     public void extractInfoVduCp(final List<NodeTemplate> lnodeVduCp, final Content content)
267             throws PolicyDecodingException {
268         // each CP will binds to a VDU so need the vdu flavor map info.
269         final Map<String, FlavorFeature> vduFlavorMap = new HashMap<>();
270         for (final FlavorFeature flavorFeature : content.getFlavorFeatures()) {
271             LOGGER.debug("the id = " + flavorFeature.getId());
272             vduFlavorMap.put(flavorFeature.getId(), flavorFeature);
273         }
274         for (final NodeTemplate node : lnodeVduCp) {
275             final String interfaceType =
276                     sdcCsarHelper.getNodeTemplatePropertyLeafValue(node, NETWORK_INTERFACE_TYPE_PATH);
277             LOGGER.debug("the interfaceType = " + interfaceType);
278             Map<String, Object> retMap = new HashMap<>();
279             if (interfaceType != null) {
280                 retMap = gson.fromJson(interfaceType, new TypeToken<HashMap<String, Object>>() {}.getType());
281                 LOGGER.debug("the retMap = " + retMap);
282             }
283
284             String networkHpaFeature;
285             if (retMap.containsKey(CONFIGURATION_VALUE)
286                 && NETWORK_HPA_FEATURE_MAP.containsKey(retMap.get(CONFIGURATION_VALUE).toString())) {
287                 final String interfaceTypeValue = retMap.get(CONFIGURATION_VALUE).toString();
288                 networkHpaFeature = NETWORK_HPA_FEATURE_MAP.get(interfaceTypeValue);
289                 LOGGER.debug(" the networkHpaFeature is =" + networkHpaFeature);
290             } else {
291                 LOGGER.debug(" no networkHpaFeature defined in interfaceType");
292                 continue;
293             }
294
295             final RequirementAssignments requriements =
296                 sdcCsarHelper.getRequirementsOf(node).getRequirementsByName("virtual_binding");
297             for (final RequirementAssignment requriement: requriements.getAll()) {
298                 final String nodeTemplateName = requriement.getNodeTemplateName();
299                 LOGGER.debug("getNodeTemplateName =" + nodeTemplateName);
300                 if (nodeTemplateName == null) {
301                     continue;
302                 }
303                 if (!vduFlavorMap.containsKey(nodeTemplateName)) {
304                     throw new PolicyDecodingException("vdu Flavor Map should contains the key " + nodeTemplateName);
305                 }
306                 generateNetworkFeature(networkHpaFeature, node, vduFlavorMap.get(nodeTemplateName));
307             }
308         }
309     }
310
311     /**
312      * GenerateNetworkFeature, all pci feature are grouped into FlavorFeature together. The format is a map like:
313      * {"schemaVersion": "0", "schemaSelector": "", "hardwarePlatform": "generic", "mandatory": "true",
314      * "configurationValue": "2 MB"}
315      *
316      * @param networkHpaFeature represents the specified Hpa feature
317      * @param node represents the CP Node
318      * @param flavorFeature represents all the features of specified flavor
319      */
320     private void generateNetworkFeature(final String networkHpaFeature, final NodeTemplate node,
321             final FlavorFeature flavorFeature) {
322         final FlavorProperty flavorProperty = new FlavorProperty();
323         flavorProperty.setHpaFeature(networkHpaFeature);
324         final String[] pciKeys = { "pciVendorId", "pciDeviceId", "pciNumDevices", "physicalNetwork" };
325         for (final String pciKey : pciKeys) {
326             LOGGER.debug("the pciKey = " + pciKey);
327             final String pciKeyPath = NETWORK_PCI_PATH + "#" + pciKey;
328             final String pciValue = sdcCsarHelper.getNodeTemplatePropertyLeafValue(node, pciKeyPath);
329             if (pciValue != null) {
330                 LOGGER.debug("the pciValue = " + pciValue);
331                 final Map<String, String> retMap =
332                         gson.fromJson(pciValue, new TypeToken<HashMap<String, String>>() {}.getType());
333                 final String pciConfigValue = retMap.get(CONFIGURATION_VALUE);
334                 if (pciConfigValue == null) {
335                     return;
336                 }
337                 final HpaFeatureAttribute hpaFeatureAttribute = generateHpaFeatureAttribute(pciKey, pciConfigValue);
338                 flavorProperty.getHpaFeatureAttributes().add(hpaFeatureAttribute);
339             }
340         }
341         flavorFeature.getFlavorProperties().add(flavorProperty);
342     }
343 }