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