2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.appc.seqgen.provider;
23 import com.att.eelf.configuration.EELFLogger;
24 import com.att.eelf.configuration.EELFManager;
25 import com.google.common.util.concurrent.Futures;
26 import org.apache.commons.lang.StringUtils;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
29 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
30 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
31 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceInput;
32 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutput;
33 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutputBuilder;
34 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.SequenceGeneratorService;
35 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.dependency.info.dependency.info.Vnfcs;
36 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.inventory.info.inventory.info.vnf.info.Vm;
37 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.StatusBuilder;
38 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.Transactions;
39 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.TransactionsBuilder;
40 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.ActionIdentifier;
41 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.*;
42 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.responses.ResponseActionBuilder;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
45 import org.onap.appc.dg.objects.InventoryModel;
46 import org.onap.appc.dg.objects.Node;
47 import org.onap.appc.dg.objects.VnfcDependencyModel;
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.domainmodel.lcm.VNFOperation;
52 import org.onap.appc.exceptions.APPCException;
53 import org.onap.appc.seqgen.SequenceGenerator;
54 import org.onap.appc.seqgen.impl.SequenceGeneratorFactory;
55 import org.onap.appc.seqgen.objects.Constants;
56 import org.onap.appc.seqgen.objects.PreCheckOption;
57 import org.onap.appc.seqgen.objects.RequestInfo;
58 import org.onap.appc.seqgen.objects.RequestInfoBuilder;
59 import org.onap.appc.seqgen.objects.Response;
60 import org.onap.appc.seqgen.objects.SequenceGeneratorInput;
61 import org.onap.appc.seqgen.objects.SequenceGeneratorInputBuilder;
62 import org.onap.appc.seqgen.objects.Transaction;
63 import java.util.HashMap;
64 import java.util.HashSet;
65 import java.util.LinkedList;
66 import java.util.List;
69 import java.util.concurrent.ExecutorService;
70 import java.util.concurrent.Executors;
71 import java.util.concurrent.Future;
74 public class SequenceGeneratorProvider implements AutoCloseable,SequenceGeneratorService{
75 protected DataBroker dataBroker;
76 protected RpcProviderRegistry rpcRegistry;
77 protected NotificationProviderService notificationService;
78 protected BindingAwareBroker.RpcRegistration<SequenceGeneratorService> rpcRegistration;
79 private final EELFLogger log = EELFManager.getInstance().getLogger(SequenceGeneratorProvider.class);
80 private final ExecutorService executor;
81 private final static String APP_NAME = "SequenceGeneratorProvider";
83 public SequenceGeneratorProvider(DataBroker dataBroker2, NotificationProviderService notificationProviderService
84 , RpcProviderRegistry rpcRegistry2) {
85 log.info("Creating provider for " + APP_NAME);
86 executor = Executors.newFixedThreadPool(1);
87 this.dataBroker = dataBroker2;
88 this.notificationService = notificationProviderService;
90 this.rpcRegistry = rpcRegistry2;
92 if (this.rpcRegistry != null) {
93 rpcRegistration = rpcRegistry.addRpcImplementation(SequenceGeneratorService.class, this);
95 log.info("Initialization complete for " + APP_NAME);
99 public void close() throws Exception {
100 log.info("Closing provider for " + APP_NAME);
101 if(this.executor != null){
104 if(this.rpcRegistration != null){
105 rpcRegistration.close();
107 log.info("Successfully closed provider for " + APP_NAME);
111 public Future<RpcResult<GenerateSequenceOutput>> generateSequence(GenerateSequenceInput input) {
112 RpcResult<GenerateSequenceOutput> rpcResult=null;
113 log.debug("Received input = " + input );
115 if(input.getRequestInfo()==null){
116 throw new APPCException("Request info is missing in the input");
118 SequenceGenerator seqGenerator = SequenceGeneratorFactory.getInstance()
119 .createSequenceGenerator(VNFOperation.findByString(input.getRequestInfo().getAction().name()));
120 SequenceGeneratorInput seqGenInput = buildSeqGenInput(input);
121 List<Transaction> transactions = seqGenerator.generateSequence(seqGenInput);
122 rpcResult = buildSuccessResponse(transactions);
123 } catch (APPCException e) {
124 log.error("Error Generating Sequence",e);
125 rpcResult = buildFailureResponse(e.getMessage());
127 return Futures.immediateFuture(rpcResult);
130 private RpcResult<GenerateSequenceOutput> buildSuccessResponse(List<Transaction> transactions) {
131 log.info("Building response from the list of transactions");
132 List<Transactions> transactionList = new LinkedList<>();
133 for(Transaction transaction:transactions){
134 ActionIdentifier actionIdentifier = buildActionIdentifierForResponse(transaction);
135 List<PrecheckOptions> precheckOptions = buildPrecheckOptionsForResponse(transaction);
136 List<Responses> responseList = getResponses(transaction);
137 Transactions transactionObj
138 = new TransactionsBuilder()
139 .setActionIdentifier(actionIdentifier)
140 .setAction(transaction.getAction())
141 .setActionLevel(transaction.getActionLevel())
142 .setPrecheckOperator(transaction.getPreCheckOperator())
143 .setPayload(transaction.getPayload())
144 .setTransactionId(transaction.getTransactionId())
145 .setPrecheckOptions(precheckOptions)
146 .setResponses(responseList)
148 transactionList.add(transactionObj);
151 GenerateSequenceOutputBuilder builder = new GenerateSequenceOutputBuilder()
152 .setTransactions(transactionList);
154 return RpcResultBuilder
155 .<GenerateSequenceOutput> status(true)
156 .withResult(builder.build()).build();
159 private ActionIdentifier buildActionIdentifierForResponse(Transaction transaction) {
160 log.info("Adding action identifiers to response.");
161 ActionIdentifier actionIdentifier = null;
162 if(transaction.getActionIdentifier() != null){
163 actionIdentifier = new ActionIdentifierBuilder()
164 .setVnfId(transaction.getActionIdentifier().getVnfId())
165 .setVnfcName(transaction.getActionIdentifier().getVnfcName())
166 .setVserverId(transaction.getActionIdentifier().getvServerId())
169 return actionIdentifier;
172 private List<PrecheckOptions> buildPrecheckOptionsForResponse(Transaction transaction) {
173 log.info("Adding Precheck options to response");
174 List<PrecheckOptions> precheckOptions = new LinkedList<>();
175 if(transaction.getPrecheckOptions()!=null){
176 for(PreCheckOption option:transaction.getPrecheckOptions()){
177 PrecheckOptions precheckOption = new PrecheckOptionsBuilder()
178 .setParamName(option.getParamName())
179 .setParamValue(option.getParamValue())
180 .setPreTransactionId(option.getPreTransactionId())
181 .setRule(option.getRule())
183 precheckOptions.add(precheckOption);
186 return precheckOptions;
188 private List<Responses> getResponses(Transaction transaction) {
189 List<Responses> responseList = new LinkedList<>();
190 for(Response resp : transaction.getResponses()){
191 Map<String,String> responseActions = resp.getResponseAction();
192 ResponseActionBuilder responseActionBuilder = new ResponseActionBuilder();
193 if(responseActions.get(Constants.ResponseAction.WAIT.getAction())!=null){
194 responseActionBuilder = responseActionBuilder.setWait(Integer.parseInt(responseActions.get(Constants.ResponseAction.WAIT.getAction())));
196 if(responseActions.get(Constants.ResponseAction.RETRY.getAction())!=null){
197 responseActionBuilder = responseActionBuilder.setRetry(Integer.parseInt(responseActions.get(Constants.ResponseAction.RETRY.getAction())));
199 if(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())!=null){
200 responseActionBuilder = responseActionBuilder
201 .setContinue(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())));
203 if(responseActions.get(Constants.ResponseAction.IGNORE.getAction()) !=null){
204 responseActionBuilder = responseActionBuilder.setIgnore(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.IGNORE.getAction())));
206 if(responseActions.get(Constants.ResponseAction.STOP.getAction()) !=null){
207 responseActionBuilder = responseActionBuilder.setStop(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.STOP.getAction())));
209 if(responseActions.get(Constants.ResponseAction.JUMP.getAction()) !=null){
210 responseActionBuilder = responseActionBuilder.setJump(Integer.parseInt(responseActions.get(Constants.ResponseAction.JUMP.getAction())));
212 Responses response = new ResponsesBuilder()
213 .setResponseMessage(resp.getResponseMessage())
214 .setResponseAction(responseActionBuilder.build())
216 responseList.add(response);
221 private SequenceGeneratorInput buildSeqGenInput(GenerateSequenceInput input) throws APPCException {
223 log.info("Building SequenceGeneratorInput from Yang object GenerateSequenceInput.");
224 validateMandatory(input);
226 RequestInfo requestInfo = buildRequestInfoForSeqGenInput(input);
227 InventoryModel inventoryModel = readInventoryModel(input);
229 VnfcDependencyModel dependencyModel = readDependencyModel(input);
230 if(dependencyModel!=null){
231 validateInventoryModelWithDependencyModel(dependencyModel,inventoryModel);
234 SequenceGeneratorInputBuilder builder = new SequenceGeneratorInputBuilder()
235 .requestInfo(requestInfo)
236 .inventoryModel(inventoryModel)
237 .dependendcyModel(dependencyModel);
239 builder = buildCapabilitiesForSeqGenInput(input, builder);
241 builder = buildTunableParamsForSeqGenInput(input, builder);
243 return builder.build();
246 private SequenceGeneratorInputBuilder buildTunableParamsForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
247 log.info("Initializing Tunable Parameters based on YANG object.");
248 if(input.getTunableParameters() != null){
249 builder = builder.tunableParameter(Constants.RETRY_COUNT,String.valueOf(input.getTunableParameters().getRetryCount()))
250 .tunableParameter(Constants.WAIT_TIME,String.valueOf(input.getTunableParameters().getWaitTime()));
251 if(input.getTunableParameters().getStrategy() !=null){
252 builder = builder.tunableParameter(Constants.STRATEGY,input.getTunableParameters().getStrategy().name());
258 private SequenceGeneratorInputBuilder buildCapabilitiesForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
259 log.info("Initializing capabilities based on YANG object.");
260 if(input.getCapabilities() !=null){
261 if(input.getCapabilities().getVnf()!=null){
262 builder = builder.capability("vnf",input.getCapabilities().getVnf());
264 if(input.getCapabilities().getVnfc()!=null){
265 builder = builder.capability("vnfc",input.getCapabilities().getVnfc());
267 if(input.getCapabilities().getVm()!=null){
268 builder = builder.capability("vm",input.getCapabilities().getVm());
270 if(input.getCapabilities().getVfModule()!=null){
271 builder = builder.capability("vf-module",input.getCapabilities().getVfModule());
278 private void validateInventoryModelWithDependencyModel(VnfcDependencyModel dependencyModel, InventoryModel inventoryModel) throws APPCException {
279 Set<String> dependencyModelVnfcSet = new HashSet<>();
280 Set<String> dependencyModelMandatoryVnfcSet = new HashSet<>();
281 Set<String> inventoryModelVnfcsSet = new HashSet<>();
283 for (Node<Vnfc> node : dependencyModel.getDependencies()) {
284 dependencyModelVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
285 if (node.getChild().isMandatory()) {
286 dependencyModelMandatoryVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
290 for (Vnfc vnfc : inventoryModel.getVnf().getVnfcs()) {
291 inventoryModelVnfcsSet.add(vnfc.getVnfcType().toLowerCase());
294 // if dependency model and inventory model contains same set of VNFCs, validation succeed and hence return
295 if (dependencyModelVnfcSet.equals(inventoryModelVnfcsSet)) {
299 if (inventoryModelVnfcsSet.size() >= dependencyModelVnfcSet.size()) {
300 Set<String> difference = new HashSet<>(inventoryModelVnfcsSet);
301 difference.removeAll(dependencyModelVnfcSet);
302 log.error("Dependency model is missing following vnfc type(s): " + difference);
303 throw new APPCException("Dependency model is missing following vnfc type(s): " + difference);
305 Set<String> difference = new HashSet<>(dependencyModelMandatoryVnfcSet);
306 difference.removeAll(inventoryModelVnfcsSet);
307 if (difference.size() > 0) {
308 log.error("Inventory model is missing following mandatory vnfc type(s): " + difference);
309 throw new APPCException("VMs missing for the mandatory VNFC : " + difference);
314 private RequestInfo buildRequestInfoForSeqGenInput(GenerateSequenceInput input) {
315 log.info("Building RequestInfo from Yang object");
316 RequestInfoBuilder requestInfobuilder = buildRequestInformation(input);
318 if(input.getRequestInfo().getActionIdentifier() !=null){
319 requestInfobuilder = buildActionIdentifiers(input, requestInfobuilder);
322 return requestInfobuilder.build();
325 private RequestInfoBuilder buildActionIdentifiers(GenerateSequenceInput input, RequestInfoBuilder requestInfobuilder) {
326 log.info("Initializing actionIdentifier for RequestInfo");
327 requestInfobuilder = requestInfobuilder
329 .vnfId(input.getRequestInfo().getActionIdentifier().getVnfId())
330 .vnfcName(input.getRequestInfo().getActionIdentifier().getVnfcName())
331 .vServerId(input.getRequestInfo().getActionIdentifier().getVserverId());
332 return requestInfobuilder;
335 private RequestInfoBuilder buildRequestInformation(GenerateSequenceInput input) {
336 log.info("Initializing action, actionLevel and payload for RequestInfo");
337 return new RequestInfoBuilder()
338 .action(input.getRequestInfo().getAction().name())
339 .actionLevel(input.getRequestInfo().getActionLevel().getName().toLowerCase())
340 .payload(input.getRequestInfo().getPayload());
343 private void validateMandatory(GenerateSequenceInput input) throws APPCException {
344 if(input.getRequestInfo() ==null){
345 throw new APPCException("Request Info is not present in the request");
347 if(input.getRequestInfo().getAction() ==null){
348 throw new APPCException("Action is not present in the request");
350 if(input.getInventoryInfo() ==null){
351 throw new APPCException("inventoryInfo is not provided in the input");
353 if (input.getInventoryInfo().getVnfInfo()== null) {
354 log.error("vnfInfo is null in the input");
355 throw new APPCException("vnfInfo is missing in the input");
357 if(input.getInventoryInfo().getVnfInfo().getVm().isEmpty()){
358 log.error("Null vm information in input.");
359 throw new APPCException("VnfInfo is missing in the input");
361 log.info("Mandatory information present in the request.");
364 private VnfcDependencyModel readDependencyModel(GenerateSequenceInput input) throws APPCException{
365 log.info("Initializing DependencyModel from YANG model.");
366 if(input.getDependencyInfo() == null || input.getDependencyInfo().getVnfcs() ==null || input.getDependencyInfo().getVnfcs().isEmpty()){
367 log.info("No dependency model information is present for the request.");
370 List<Vnfcs> vnfcs = input.getDependencyInfo().getVnfcs();
371 Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies = new HashSet<>();
372 Set<String> parentVnfcs=new HashSet<>();
373 Set<String> allVnfcTypes=new HashSet<>();
374 for(Vnfcs vnfcObj:vnfcs){
375 org.onap.appc.domainmodel.Vnfc vnfc = new org.onap.appc.domainmodel.Vnfc();
376 vnfc.setVnfcType(vnfcObj.getVnfcType());
377 allVnfcTypes.add(vnfcObj.getVnfcType());
378 vnfc.setResilienceType(vnfcObj.getResilience());
379 Node<Vnfc> currentNode = buildVnfcNodeForDependenyInfo(dependencies, vnfcObj, vnfc);
380 for(String parentVnfcType:vnfcObj.getParents()){
381 parentVnfcs.add(parentVnfcType);
382 Node<Vnfc> parentNode = readNode(parentVnfcType,dependencies);
383 if(parentNode == null){
384 Vnfc parentVnfc = new Vnfc();
385 parentVnfc.setVnfcType(parentVnfcType);
386 parentNode = new Node<>(parentVnfc);
387 currentNode.addParent(parentVnfc);
388 dependencies.add(parentNode);
391 currentNode.addParent(parentNode.getChild());
395 for(String parent:parentVnfcs){
396 if(!allVnfcTypes.contains(parent)){
397 throw new APPCException("Dependency model missing vnfc type "+parent);
400 return new VnfcDependencyModel(dependencies);
403 private Node<Vnfc> buildVnfcNodeForDependenyInfo(Set<Node<Vnfc>> dependencies, Vnfcs vnfcObj, Vnfc vnfc) {
404 Node<Vnfc> currentNode = readNode(vnfcObj.getVnfcType(),dependencies);
405 if(currentNode == null){
406 currentNode = new Node<>(vnfc);
407 dependencies.add(currentNode);
410 currentNode.getChild().setResilienceType(vnfcObj.getResilience());
411 currentNode.getChild().setMandatory(vnfcObj.isMandatory());
416 private Node<org.onap.appc.domainmodel.Vnfc> readNode(String vnfcType, Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies) {
417 for(Node<org.onap.appc.domainmodel.Vnfc> node : dependencies){
418 if(node.getChild().getVnfcType().equalsIgnoreCase(vnfcType)){
425 private InventoryModel readInventoryModel(GenerateSequenceInput input) throws APPCException {
427 log.info("Initializing InventoryModel from Yang input model");
428 Vnf vnf = createVnfForInventoryModel(input);
429 Map<org.onap.appc.domainmodel.Vnfc,List<Vserver>> map = new HashMap<>();
430 buildVserverDetailsForInventoryModel(input, vnf, map);
431 for(Map.Entry<org.onap.appc.domainmodel.Vnfc,List<Vserver>> entry:map.entrySet()){
432 org.onap.appc.domainmodel.Vnfc vnfc = entry.getKey();
433 List<Vserver> vmList = entry.getValue();
434 vnfc.addVservers(vmList);
436 return new InventoryModel(vnf);
439 private void buildVserverDetailsForInventoryModel(GenerateSequenceInput input, Vnf vnf, Map<Vnfc, List<Vserver>> map) throws APPCException {
440 if(input.getInventoryInfo().getVnfInfo().getVm().size()<1){
441 throw new APPCException("vnfInfo is missing in the input");
443 for(Vm vm:input.getInventoryInfo().getVnfInfo().getVm()){
444 if(StringUtils.isBlank(vm.getVserverId())){
445 throw new APPCException("vserver-id not found ");
447 Vserver vserver=new Vserver();
448 vserver.setId(vm.getVserverId());
449 if(!StringUtils.isBlank(vm.getVnfc().getVnfcName()) &&
450 !StringUtils.isBlank(vm.getVnfc().getVnfcType())){
451 Vnfc vfc = new Vnfc();
452 vfc.setVnfcName(vm.getVnfc().getVnfcName());
453 vfc.setVnfcType(vm.getVnfc().getVnfcType());
454 vserver.setVnfc(vfc);
455 List<Vserver> vms = map.get(vfc);
457 vms = new LinkedList<>();
462 vnf.addVserver(vserver);
466 private Vnf createVnfForInventoryModel(GenerateSequenceInput input) {
467 log.info("Setting VnfId and VnfType values for Vnf Inventory Model ");
469 vnf.setVnfId(input.getInventoryInfo().getVnfInfo().getVnfId());
470 vnf.setVnfType(input.getInventoryInfo().getVnfInfo().getVnfType());
474 private RpcResult<GenerateSequenceOutput> buildFailureResponse(String errorMessage){
475 GenerateSequenceOutputBuilder sequenceGeneratorOutputBuilder=new GenerateSequenceOutputBuilder();
476 StatusBuilder statusBuilder =new StatusBuilder();
477 statusBuilder.setCode(401);
478 statusBuilder.setMessage(errorMessage);
479 sequenceGeneratorOutputBuilder.setStatus(statusBuilder.build());
480 return RpcResultBuilder
481 .<GenerateSequenceOutput> status(true)
482 .withResult(sequenceGeneratorOutputBuilder.build())