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