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