fe7545d0f4640e29324868d5ea9e30a1ec314a92
[appc.git] / appc-dg / appc-dg-shared / appc-dg-common / src / main / java / org / onap / appc / dg / common / impl / VnfExecutionFlowImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.appc.dg.common.impl;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.att.eelf.i18n.EELFResourceManager;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import org.onap.appc.dg.common.VnfExecutionFlow;
36 import org.onap.appc.dg.dependencymanager.DependencyManager;
37 import org.onap.appc.dg.dependencymanager.exception.DependencyModelNotFound;
38 import org.onap.appc.dg.dependencymanager.impl.DependencyModelFactory;
39 import org.onap.appc.dg.flowbuilder.FlowBuilder;
40 import org.onap.appc.dg.flowbuilder.exception.InvalidDependencyModelException;
41 import org.onap.appc.dg.flowbuilder.impl.FlowBuilderFactory;
42 import org.onap.appc.dg.objects.DependencyTypes;
43 import org.onap.appc.dg.objects.FlowStrategies;
44 import org.onap.appc.dg.objects.InventoryModel;
45 import org.onap.appc.dg.objects.Node;
46 import org.onap.appc.dg.objects.VnfcDependencyModel;
47 import org.onap.appc.dg.objects.VnfcFlowModel;
48 import org.onap.appc.domainmodel.Vnf;
49 import org.onap.appc.domainmodel.Vnfc;
50 import org.onap.appc.domainmodel.Vserver;
51 import org.onap.appc.exceptions.APPCException;
52 import org.onap.appc.i18n.Msg;
53 import org.onap.appc.metadata.objects.DependencyModelIdentifier;
54 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
55
56 public class VnfExecutionFlowImpl implements VnfExecutionFlow {
57
58     private final EELFLogger logger = EELFManager.getInstance().getLogger(VnfExecutionFlowImpl.class);
59     private static final String VNFC_FLOW = "vnfcFlow[";
60     private static final String VNF_VNFC = "vnf.vnfc[";
61
62     /**
63      * Constructor <p>Used through blueprint
64      */
65     public VnfExecutionFlowImpl() {
66         // do nothing
67     }
68
69     @Override
70     public void getVnfExecutionFlowData(Map<String, String> params, SvcLogicContext context) {
71         String dependencyType = params.get(Constants.DEPENDENCY_TYPE);
72         String flowStrategy = params.get(Constants.FLOW_STRATEGY);
73         DependencyModelIdentifier modelIdentifier = readDependencyModelIdentifier(params);
74         VnfcDependencyModel dependencyModel;
75         try {
76             validateInput(dependencyType, flowStrategy, params);
77
78             if (logger.isTraceEnabled()) {
79                 logger.trace("Input received from DG Node : dependencyType = " + dependencyType +
80                     " , flowStrategy = " + flowStrategy +
81                     ", DependencyModelIdentifier = " + modelIdentifier.toString());
82             }
83
84             DependencyManager dependencyManager = DependencyModelFactory.createDependencyManager();
85             dependencyModel = dependencyManager.getVnfcDependencyModel(
86                 modelIdentifier, DependencyTypes.findByString(dependencyType));
87         } catch (DependencyModelNotFound e) {
88             String msg = EELFResourceManager
89                 .format(Msg.DEPENDENCY_MODEL_NOT_FOUND, params.get(Constants.VNF_TYPE), e.getMessage());
90             logger.error(msg);
91             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, msg);
92             context.setAttribute("dependencyModelFound", "false");
93             return;
94         } catch (InvalidDependencyModelException e) {
95             String msg = EELFResourceManager
96                 .format(Msg.INVALID_DEPENDENCY_MODEL, params.get(Constants.VNF_TYPE), e.getMessage());
97             logger.error(msg);
98             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, msg);
99             throw new RuntimeException(e.getMessage(), e);
100         } catch (APPCException e) {
101             logger.error(e.getMessage());
102             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, e.getMessage());
103             throw new RuntimeException(e.getMessage(), e);
104         } catch (RuntimeException e) {
105             logger.error(e.getMessage());
106             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, e.getMessage());
107             throw e;
108         }
109
110         context.setAttribute("dependencyModelFound", "true");
111         if (logger.isDebugEnabled()) {
112             logger.debug("Dependency Model = " + dependencyModel);
113         }
114         logger.info("Building Inventory Model from DG context");
115         InventoryModel inventoryModel = null;
116         try {
117             inventoryModel = readInventoryModel(context);
118         } catch (APPCException e) {
119             logger.error(e.getMessage());
120             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, e.getMessage());
121             throw new RuntimeException(e.getMessage(), e);
122         }
123         if (logger.isDebugEnabled()) {
124             logger.debug("Inventory Model = " + inventoryModel);
125         }
126
127         if (logger.isDebugEnabled()) {
128             logger.debug("Validating inventory model with dependency model");
129         }
130         try {
131             validateInventoryModelWithDependencyModel(dependencyModel, inventoryModel);
132         } catch (APPCException e) {
133             logger.error(e.getMessage());
134             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, e.getMessage());
135             throw new RuntimeException(e.getMessage(), e);
136         }
137         logger.info("Creating flow builder");
138         FlowBuilder flowBuilder = FlowBuilderFactory.getInstance().getFlowBuilder(
139             FlowStrategies.findByString(flowStrategy));
140
141         logger.info("Building Vnf flow model");
142         VnfcFlowModel flowModel;
143         try {
144             flowModel = flowBuilder.buildFlowModel(dependencyModel, inventoryModel);
145         } catch (InvalidDependencyModelException e) {
146             String msg = EELFResourceManager
147                 .format(Msg.INVALID_DEPENDENCY_MODEL, params.get(Constants.VNF_TYPE), e.getMessage());
148             logger.error(msg);
149             context.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, msg);
150             throw new RuntimeException(e.getMessage(), e);
151         }
152
153         // remove VNFCs from the flow model where vserver list is empty
154         reconcileFlowModel(flowModel);
155         populateContext(flowModel, context);
156         if (logger.isDebugEnabled()) {
157             logContext(context);
158         }
159         String msg = EELFResourceManager
160             .format(Msg.SUCCESS_EVENT_MESSAGE, "GetVnfExecutionFlowData", "VNF ID " + params.get(Constants.VNF_TYPE));
161         context.setAttribute(org.onap.appc.Constants.ATTRIBUTE_SUCCESS_MESSAGE, msg);
162     }
163
164     private void validateInput(String dependencyType, String flowStrategy, Map<String, String> params)
165         throws APPCException {
166         DependencyTypes dependencyTypes = DependencyTypes.findByString(dependencyType);
167         if (dependencyTypes == null) {
168             throw new APPCException("Dependency type from the input : " + dependencyType + " is invalid.");
169         }
170         FlowStrategies flowStrategies = FlowStrategies.findByString(flowStrategy);
171         if (flowStrategies == null) {
172             throw new APPCException("Flow Strategy from the input : " + flowStrategy + " is invalid.");
173         }
174         String vnfType = params.get(Constants.VNF_TYPE);
175         if (vnfType == null || vnfType.length() == 0) {
176             throw new APPCException("Vnf Type is not passed in the input");
177         }
178         String vnfVersion = params.get(Constants.VNF_VERION);
179         if (vnfVersion == null || vnfVersion.length() == 0) {
180             throw new APPCException("Vnf Version not found");
181         }
182     }
183
184     private void logContext(SvcLogicContext context) {
185         for (String key : context.getAttributeKeySet()) {
186             logger.debug(key + " = " + context.getAttribute(key) + "\n");
187         }
188     }
189
190     private void populateContext(VnfcFlowModel flowModel, SvcLogicContext context) {
191         int flowIndex = 0;
192         Iterator<List<Vnfc>> iterator = flowModel.getModelIterator();
193         while (iterator.hasNext()) {
194             for (Vnfc vnfc : iterator.next()) {
195                 context.setAttribute(VNFC_FLOW + flowIndex + "].vnfcName", vnfc.getVnfcName());
196                 context.setAttribute(VNFC_FLOW + flowIndex + "].vnfcType", vnfc.getVnfcType());
197                 context.setAttribute(VNFC_FLOW + flowIndex + "].resilienceType", vnfc.getResilienceType());
198                 context
199                     .setAttribute(VNFC_FLOW + flowIndex + "].vmCount", Integer.toString(vnfc.getVserverList().size()));
200                 int vmIndex = 0;
201                 for (Vserver vm : vnfc.getVserverList()) {
202                     context.setAttribute(VNFC_FLOW + flowIndex + "].vm[" + vmIndex + "].url", vm.getUrl());
203                     vmIndex++;
204                 }
205                 flowIndex++;
206             }
207         }
208         context.setAttribute("vnfcFlowCount", Integer.toString(flowIndex));
209     }
210
211     private InventoryModel readInventoryModel(SvcLogicContext context) throws APPCException {
212         String vnfId = context.getAttribute("input.action-identifiers.vnf-id");
213         String vnfType = context.getAttribute("vnf.type");
214         String vnfVersion = context.getAttribute("vnf.version");
215         String vnfcCountStr = context.getAttribute("vnf.vnfcCount");
216         Integer vnfcCount = Integer.parseInt(vnfcCountStr);
217         Vnf vnf = createVnf(vnfId, vnfType, vnfVersion);
218         for (Integer i = 0; i < vnfcCount; i++) {
219             String vnfcName = context.getAttribute(VNF_VNFC + i + "].name");
220             String vnfcType = context.getAttribute(VNF_VNFC + i + "].type");
221             String vmCountStr = context.getAttribute(VNF_VNFC + i + "].vm_count");
222             if (vnfcType == null || vnfcType.length() == 0) {
223                 throw new APPCException("Could not retrieve VNFC Type from DG Context for vnf.vnfc[" + i + "].type");
224             }
225             Integer vmCount = Integer.parseInt(vmCountStr);
226             Vnfc vnfc = createVnfc(vnfcName, vnfcType);
227             for (Integer j = 0; j < vmCount; j++) {
228                 String vmURL = context.getAttribute(VNF_VNFC + i + "].vm[" + j + "].url");
229                 Vserver vm = createVserver(vmURL);
230                 vm.setVnfc(vnfc);
231                 vnfc.addVserver(vm);
232                 vnf.addVserver(vm);
233             }
234         }
235         return new InventoryModel(vnf);
236     }
237
238     private Vserver createVserver(String vmURL) {
239         Vserver vserver = new Vserver();
240         vserver.setUrl(vmURL);
241         return vserver;
242     }
243
244     private Vnfc createVnfc(String vnfcName, String vnfcType) {
245         Vnfc vnfc = new Vnfc();
246         vnfc.setVnfcName(vnfcName);
247         vnfc.setVnfcType(vnfcType);
248         return vnfc;
249     }
250
251     private Vnf createVnf(String vnfId, String vnfType, String vnfVersion) {
252         Vnf vnf = new Vnf();
253         vnf.setVnfType(vnfType);
254         vnf.setVnfId(vnfId);
255         vnf.setVnfVersion(vnfVersion);
256         return vnf;
257     }
258
259     private DependencyModelIdentifier readDependencyModelIdentifier(Map<String, String> params) {
260         String vnfType = params.get(Constants.VNF_TYPE);
261         String catalogVersion = params.get(Constants.VNF_VERION);
262         return new DependencyModelIdentifier(vnfType, catalogVersion);
263     }
264
265     private void validateInventoryModelWithDependencyModel(VnfcDependencyModel dependencyModel,
266         InventoryModel inventoryModel) throws APPCException {
267         Set<String> dependencyModelVnfcSet = new HashSet<>();
268         Set<String> dependencyModelMandatoryVnfcSet = new HashSet<>();
269         Set<String> inventoryModelVnfcsSet = new HashSet<>();
270         for (Node<Vnfc> node : dependencyModel.getDependencies()) {
271             dependencyModelVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
272             if (node.getChild().isMandatory()) {
273                 dependencyModelMandatoryVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
274             }
275         }
276         for (Vnfc vnfc : inventoryModel.getVnf().getVnfcs()) {
277             inventoryModelVnfcsSet.add(vnfc.getVnfcType().toLowerCase());
278         }
279         // if dependency model and inventory model contains same set of VNFCs, validation succeed and hence return
280         if (dependencyModelVnfcSet.equals(inventoryModelVnfcsSet)) {
281             return;
282         }
283         if (inventoryModelVnfcsSet.size() >= dependencyModelVnfcSet.size()) {
284             Set<String> difference = new HashSet<>(inventoryModelVnfcsSet);
285             difference.removeAll(dependencyModelVnfcSet);
286             logger.error("Dependency model is missing following vnfc type(s): " + difference);
287             throw new APPCException("Dependency model is missing following vnfc type(s): " + difference);
288         } else {
289             Set<String> difference = new HashSet<>(dependencyModelMandatoryVnfcSet);
290             difference.removeAll(inventoryModelVnfcsSet);
291             if (difference.size() > 0) {
292                 logger.error("Inventory model is missing following mandatory vnfc type(s): " + difference);
293                 throw new APPCException("Inventory model is missing following mandatory vnfc type(s): " + difference);
294             }
295         }
296     }
297
298     private void reconcileFlowModel(VnfcFlowModel flowModel) {
299         Iterator<List<Vnfc>> flowIterator = flowModel.getModelIterator();
300         while (flowIterator.hasNext()) {
301             Iterator<Vnfc> vnfcIterator = flowIterator.next().iterator();
302             while (vnfcIterator.hasNext()) {
303                 Vnfc vnfc = vnfcIterator.next();
304                 if (vnfc.getVserverList().size() == 0) {
305                     if (logger.isDebugEnabled()) {
306                         logger.debug("No vservers present for Vnfc type: " + vnfc.getVnfcType()
307                             + ". Hence, removing it from the flow model.");
308                     }
309                     vnfcIterator.remove();
310                 }
311             }
312         }
313     }
314
315 }