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