Add vm caps fixes to sequence-generator code (vm caps)
[appc.git] / appc-sequence-generator / appc-sequence-generator-bundle / src / main / java / org / onap / appc / seqgen / impl / StartSequenceGenerator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017-2018 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  * ============LICENSE_END=========================================================
22  */
23
24
25 package org.onap.appc.seqgen.impl;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import org.apache.commons.lang3.StringUtils;
30 import org.onap.appc.dg.flowbuilder.FlowBuilder;
31 import org.onap.appc.dg.flowbuilder.exception.InvalidDependencyModelException;
32 import org.onap.appc.dg.flowbuilder.impl.FlowBuilderFactory;
33 import org.onap.appc.dg.objects.FlowStrategies;
34 import org.onap.appc.dg.objects.InventoryModel;
35 import org.onap.appc.dg.objects.VnfcDependencyModel;
36 import org.onap.appc.dg.objects.VnfcFlowModel;
37 import org.onap.appc.domainmodel.Vnfc;
38 import org.onap.appc.domainmodel.Vserver;
39 import org.onap.appc.exceptions.APPCException;
40 import org.onap.appc.seqgen.SequenceGenerator;
41 import org.onap.appc.seqgen.objects.ActionIdentifier;
42 import org.onap.appc.seqgen.objects.CapabilityModel;
43 import org.onap.appc.seqgen.objects.Constants;
44 import org.onap.appc.seqgen.objects.PreCheckOption;
45 import org.onap.appc.seqgen.objects.Response;
46 import org.onap.appc.seqgen.objects.SequenceGeneratorInput;
47 import org.onap.appc.seqgen.objects.Transaction;
48
49 import java.util.HashMap;
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.List;
53 import java.util.Map;
54
55 import static org.onap.appc.seqgen.objects.Constants.Action;
56 import static org.onap.appc.seqgen.objects.Constants.ActionLevel;
57 import static org.onap.appc.seqgen.objects.Constants.ResponseAction;
58 import static org.onap.appc.seqgen.objects.Constants.ResponseMessage;
59 import static org.onap.appc.seqgen.objects.Constants.PreCheckOperator;
60 import static org.onap.appc.seqgen.objects.Constants.Capabilties;
61 import static org.onap.appc.seqgen.objects.Constants.CapabilityLevel;
62 import static org.onap.appc.seqgen.objects.Constants.RETRY_COUNT_VALUE;
63 import static org.onap.appc.seqgen.objects.Constants.WAIT_TIME;
64 import static org.onap.appc.seqgen.objects.Constants.RETRY_COUNT;
65 import static org.onap.appc.seqgen.objects.Constants.WAIT_TIME_VALUE;;
66
67 public class StartSequenceGenerator implements SequenceGenerator {
68
69     private static final EELFLogger logger = EELFManager.getInstance().getLogger(StartSequenceGenerator.class);
70
71     private List<Transaction> generateSequenceWithOutDependency(SequenceGeneratorInput input) throws Exception {
72
73         String payload = null;
74         PayloadGenerator payloadGenerator = new PayloadGenerator();
75         List<Transaction> transactionList = new LinkedList<>();
76         Integer transactionId = 1;
77         List<Vserver> vservers = input.getInventoryModel().getVnf().getVservers();
78         List<Integer> transactionIds = new LinkedList<>();
79         for (Vserver vm : vservers) {
80             // check vm-Start-capabilities for this vm's vnfc-function-code (before incrementing transactionId)
81             if (!vmSupportsStart(input, vm)) {
82                 continue;
83             }
84             Transaction transaction = new Transaction();
85             transaction.setTransactionId(transactionId);
86             transactionIds.add(transactionId++);
87             transaction.setAction(Action.START.getActionType());
88             transaction.setActionLevel(ActionLevel.VM.getAction());
89             ActionIdentifier actionIdentifier = new ActionIdentifier();
90             actionIdentifier.setvServerId(vm.getId());
91             transaction.setActionIdentifier(actionIdentifier);
92             String vmId = vm.getUrl();
93             String url = vm.getUrl();
94             payload = payloadGenerator.getPayload(input, vmId, url);
95             transaction.setPayload(payload);
96             if(vservers.size()>1){
97                 Response ignoreResponse = new Response();
98                 ignoreResponse.setResponseMessage(ResponseMessage.FAILURE.getResponse());
99                 Map<String, String> ignoreAction = new HashMap<>();
100                 ignoreAction.put(ResponseAction.STOP.getAction(), Boolean.TRUE.toString());
101                 ignoreResponse.setResponseAction(ignoreAction);
102                 transaction.addResponse(ignoreResponse);
103             }
104             transactionList.add(transaction);
105         }
106         return transactionList;
107     }
108
109     private boolean checkSingleTransaction(List<Vnfc> invVnfcList) {
110         int vServerCount=0;
111         for(Vnfc vnfc : invVnfcList) {
112             List<Vserver> vms = vnfc.getVserverList();
113             vServerCount=vServerCount+vms.size();
114         }
115         return vServerCount <= 1;
116     }
117
118     private void updateResponse(Transaction transaction) {
119         Response ignoreResponse = new Response();
120         ignoreResponse.setResponseMessage(ResponseMessage.FAILURE.getResponse());
121         Map<String, String> ignoreAction = new HashMap<>();
122         ignoreAction.put(ResponseAction.STOP.getAction(), Boolean.TRUE.toString());
123         ignoreResponse.setResponseAction(ignoreAction);
124         transaction.addResponse(ignoreResponse);
125     }
126
127     private List<Transaction> generateSequenceWithDependencyModel(VnfcFlowModel flowModel, SequenceGeneratorInput input) throws APPCException {
128         Integer waitTime = readWaitTime(input);
129         Integer retryCount = readRetryCount(input);
130         List<Transaction> transactionList = new LinkedList<>();
131         Integer transactionId = 1;
132         Iterator<List<Vnfc>> itr = flowModel.getModelIterator();
133         while (itr.hasNext()) {
134             List<Vnfc> vnfcs = itr.next();
135             for (Vnfc vnfc : vnfcs) {
136                 List<Vserver> vms = vnfc.getVserverList();
137                 List<Integer> transactionIds = new LinkedList<>();
138                 if(!vms.isEmpty()) {
139                     for (Vserver vm : vms) {
140                         // check vm-Start-capabilities for this vm's vnfc-function-code (before incrementing transactionId)
141                         if (!vmSupportsStart(input, vm)) {
142                             continue;
143                         }
144                         Transaction transaction = new Transaction();
145                         transaction.setTransactionId(transactionId);
146                         transactionIds.add(transactionId++);
147                         transaction.setAction(Action.START.getActionType());
148                         transaction.setActionLevel(ActionLevel.VM.getAction());
149                         ActionIdentifier actionIdentifier = new ActionIdentifier();
150                         actionIdentifier.setvServerId(vm.getId());
151                         transaction.setActionIdentifier(actionIdentifier);
152                         transaction.setPayload(input.getRequestInfo().getPayload());
153                         Response ignoreResponse = new Response();
154                         ignoreResponse.setResponseMessage(ResponseMessage.FAILURE.getResponse());
155                         Map<String, String> ignoreAction = new HashMap<>();
156                         ignoreAction.put(ResponseAction.STOP.getAction(), Boolean.TRUE.toString());
157                         ignoreResponse.setResponseAction(ignoreAction);
158                         transaction.addResponse(ignoreResponse);
159                         transactionList.add(transaction);
160                     }
161                     boolean startApplicationSupported = readApplicationStartCapability(input);
162                     if (startApplicationSupported) {
163                         Transaction startAppTransaction = new Transaction();
164                         startAppTransaction.setTransactionId(transactionId++);
165                         startAppTransaction.setAction(Action.START_APPLICATION.getActionType());
166                         startAppTransaction.setActionLevel(ActionLevel.VNFC.getAction());
167                         ActionIdentifier startActionIdentifier = new ActionIdentifier();
168                         startActionIdentifier.setVnfcName(vnfc.getVnfcName());
169                         startAppTransaction.setActionIdentifier(startActionIdentifier);
170                         startAppTransaction.setPayload(input.getRequestInfo().getPayload());
171
172                         List<PreCheckOption> preCheckOptions = buildPreCheckOptions(transactionIds);
173                         startAppTransaction.setPreCheckOperator(PreCheckOperator.ANY.getOperator());
174                         startAppTransaction.setPrecheckOptions(preCheckOptions);
175                         transactionList.add(startAppTransaction);
176                     }
177                     boolean healthCheckSupported = readHealthCheckCapabilites(input.getCapability());
178                     if (healthCheckSupported) {
179                         Transaction healthCheckTransaction = new Transaction();
180                         healthCheckTransaction.setTransactionId(transactionId++);
181                         healthCheckTransaction.setAction(Action.HEALTH_CHECK.getActionType());
182                         healthCheckTransaction.setActionLevel(ActionLevel.VNFC.getAction());
183                         ActionIdentifier healthCheckActionIdentifier = new ActionIdentifier();
184                         healthCheckActionIdentifier.setVnfcName(vnfc.getVnfcName());
185                         healthCheckTransaction.setActionIdentifier(healthCheckActionIdentifier);
186                         healthCheckTransaction.setPayload(input.getRequestInfo().getPayload());
187
188                         Response retryResponse = new Response();
189                         retryResponse.setResponseMessage(ResponseMessage.UNHEALTHY.getResponse());
190                         Map<String, String> retryAction = new HashMap<>();
191                         retryAction.put(ResponseAction.RETRY.getAction(), retryCount.toString());
192                         retryAction.put(ResponseAction.WAIT.getAction(), waitTime.toString());
193                         retryResponse.setResponseAction(retryAction);
194                         healthCheckTransaction.addResponse(retryResponse);
195
196                         Response healthyResponse = new Response();
197                         healthyResponse.setResponseMessage(ResponseMessage.HEALTHY.getResponse());
198                         Map<String, String> healthyAction = new HashMap<>();
199                         healthyAction.put(ResponseAction.CONTINUE.getAction().toLowerCase(), Boolean.TRUE.toString());
200                         healthyResponse.setResponseAction(healthyAction);
201                         healthCheckTransaction.addResponse(healthyResponse);
202
203                         Response failureResponse = new Response();
204                         failureResponse.setResponseMessage(ResponseMessage.FAILURE.getResponse());
205                         Map<String, String> failureResonseAction = new HashMap<>();
206                         failureResonseAction.put(ResponseAction.STOP.getAction(), Boolean.TRUE.toString());
207                         failureResponse.setResponseAction(failureResonseAction);
208                         healthCheckTransaction.addResponse(failureResponse);
209                         transactionList.add(healthCheckTransaction);
210                     }
211                 }
212             }
213         }
214         return transactionList;
215     }
216
217     private List<PreCheckOption> buildPreCheckOptions(List<Integer> transactionIds) {
218         List<PreCheckOption> preCheckOptions = new LinkedList<>();
219         for (Integer vmTransactionId : transactionIds) {
220             PreCheckOption option = new PreCheckOption();
221             option.setPreTransactionId(vmTransactionId);
222             option.setParamName("status");
223             option.setParamValue("success");
224             preCheckOptions.add(option);
225         }
226         return preCheckOptions;
227     }
228
229     @Override
230     public List<Transaction> generateSequence(SequenceGeneratorInput input) throws Exception {
231             if (input.getRequestInfo().getActionLevel().equals(ActionLevel.VNF.getAction()) && input.getDependencyModel() != null) {
232                 if(isVnfcPresent(input)) {
233                     FlowStrategies flowStrategy = readFlowStrategy(input);
234                     VnfcFlowModel flowModel = null;
235                     try {
236                         flowModel = buildFlowModel(input.getInventoryModel()
237                                 , input.getDependencyModel(), flowStrategy);
238                     } catch (InvalidDependencyModelException invalidDependencyModelException) {
239                         logger.error("Error Generating Sequence", invalidDependencyModelException);
240                         throw  new APPCException(invalidDependencyModelException.getMessage(), invalidDependencyModelException);
241                     }
242                     logger.debug("Flow Model " + flowModel);
243                     return generateSequenceWithDependencyModel(flowModel, input);
244                 }
245                  else throw new APPCException("Vnfc details is missing in the input");
246             } else {
247                 logger.info("Generating sequence without dependency model");
248                 return generateSequenceWithOutDependency(input);
249             }
250     }
251
252     private VnfcFlowModel buildFlowModel(InventoryModel inventoryModel, VnfcDependencyModel dependencyModel, FlowStrategies flowStrategy) throws APPCException, InvalidDependencyModelException {
253         FlowBuilder flowBuilder = FlowBuilderFactory.getInstance().getFlowBuilder(flowStrategy);
254         if (flowBuilder == null) {
255             throw new APPCException("Flow Strategy not supported " + flowStrategy);
256         }
257         return flowBuilder.buildFlowModel(dependencyModel, inventoryModel);
258     }
259
260     private FlowStrategies readFlowStrategy(SequenceGeneratorInput sequenceGeneratorInput) {
261         Map<String, String> tunableParams = sequenceGeneratorInput.getTunableParams();
262         FlowStrategies strategy=null;
263         String strategyStr = null;
264         if (tunableParams != null) {
265             strategyStr = tunableParams.get(Constants.STRATEGY);
266             strategy = FlowStrategies.findByString(strategyStr);
267         }
268         if (strategy == null)
269             strategy= FlowStrategies.FORWARD;
270         return strategy;
271     }
272
273     private boolean readHealthCheckCapabilites(CapabilityModel capabilities) {
274         if (capabilities == null) {
275             return true;
276         }
277         List<String> vnfcCapabilities = capabilities.getVnfcCapabilities();
278         if (vnfcCapabilities != null)
279             return vnfcCapabilities.stream()
280                     .anyMatch(p -> Capabilties.HEALTH_CHECK.getCapability().equalsIgnoreCase(p));
281
282         return false;
283     }
284
285     private boolean readApplicationStartCapability(SequenceGeneratorInput input) {
286         CapabilityModel capability = input.getCapability();
287         if (capability == null)
288             return true;
289         List<String> vnfcCapabilities = capability.getVnfcCapabilities();
290         if (vnfcCapabilities != null)
291             return vnfcCapabilities.stream()
292                     .anyMatch(p -> Capabilties.START_APPLICATION.getCapability().equalsIgnoreCase(p));
293
294         return false;
295     }
296
297     private Integer readRetryCount(SequenceGeneratorInput input) throws APPCException {
298         String paramValStr = input.getTunableParams().get(RETRY_COUNT);
299         if (StringUtils.isEmpty(paramValStr)) {
300             return RETRY_COUNT_VALUE;
301         }
302         try {
303             return Integer.parseInt(paramValStr);
304         } catch (NumberFormatException e) {
305             String message = "Invalid Number for Retry Count " + paramValStr;
306             logger.error(message, e);
307             throw new APPCException(message);
308         }
309     }
310
311     private boolean isVnfcPresent(SequenceGeneratorInput input){
312         boolean vnfcPresent=true;
313         List<Vserver> vservers = input.getInventoryModel().getVnf().getVservers();
314         for (Vserver vm : vservers) {
315             if(!(vm.getVnfc()!=null&& vm.getVnfc().getVnfcType()!=null&& vm.getVnfc().getVnfcName()!=null)){
316                 vnfcPresent=false;
317                 break;
318             }
319         }
320         return vnfcPresent;
321     }
322
323     private Integer readWaitTime(SequenceGeneratorInput input) throws APPCException {
324         String paramValStr = input.getTunableParams().get(WAIT_TIME);
325         if (StringUtils.isEmpty(paramValStr)) {
326             return WAIT_TIME_VALUE;
327         }
328         try {
329             return Integer.parseInt(paramValStr);
330         } catch (NumberFormatException e) {
331             String message = "Invalid Number for Wait Time " + paramValStr;
332             logger.error(message, e);
333             throw new APPCException(message);
334         }
335     }
336
337     private boolean vmSupportsStart(SequenceGeneratorInput input, Vserver vm) {
338         boolean vmSupported = true;
339         if (input.getCapability() == null) {
340             logger.info("vmSupportsStart: " + "Capabilities model is null, returning vmSupported=" + vmSupported);
341             return vmSupported;
342         }
343         Map<String, List<String>> vmCapabilities = input.getCapability().getVmCapabilities();
344         if (vmCapabilities != null) {
345             if (!vmCapabilities.isEmpty()) {
346                 List<String> vmCapsForThisAction = vmCapabilities.get(Action.START.getActionType());
347                 if (vmCapsForThisAction != null) {
348                     vmSupported = false;
349                     if (!vmCapsForThisAction.isEmpty()) {
350                         if (vm.getVnfc() != null) {
351                             String vnfcFunctionCode = vm.getVnfc().getVnfcFunctionCode();
352                             if (vnfcFunctionCode != null && !vnfcFunctionCode.isEmpty()) {
353                                 for (String s : vmCapabilities.get(Action.START.getActionType()) ) {
354                                     if (s.equalsIgnoreCase(vnfcFunctionCode)) {
355                                         vmSupported = true;
356                                         logger.info("vmSupportsStart: vnfcFunctionCode=" + vnfcFunctionCode + " found in vmCapabilities");
357                                         break;
358                                     }
359                                 }
360                             } else {
361                                 logger.info("vmSupportsStart: " + "Inventory vnfcFunctionCode is null or empty");
362                             }
363                         } else {
364                             logger.info("vmSupportsStart: " + "Inventory vnfc is null or empty");
365                         } 
366                     } else {
367                         logger.info("vmSupportsStart: " + "Given action in vm entry in Capabilities model is empty");
368                     }
369                 } else {
370                     logger.info("vmSupportsStart: " + "Given action in vm entry in Capabilities model is null");
371                 }
372             } else {
373                 logger.info("vmSupportsStart: " + "Vm entry in Capabilities model is empty");
374             }
375         } else {
376             logger.info("vmSupportsStart: " + "Vm entry in Capabilities model is null");
377         }
378
379         logger.info("vmSupportsStart: " + "returning vmSupported=" + vmSupported + ", " + ((vmSupported)?"including":"excluding") + " vm=" + vm.getId());
380         return vmSupported;
381     }
382 }