2 * ============LICENSE_START=======================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * ============LICENSE_END=========================================================
24 package org.onap.appc.seqgen.provider;
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFManager;
28 import com.google.common.util.concurrent.Futures;
29 import org.apache.commons.lang.StringUtils;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
32 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
33 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
34 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceInput;
35 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutput;
36 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutputBuilder;
37 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.SequenceGeneratorService;
38 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.dependency.info.dependency.info.Vnfcs;
39 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.inventory.info.inventory.info.vnf.info.Vm;
40 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.StatusBuilder;
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.TransactionsBuilder;
43 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.ActionIdentifier;
44 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.*;
45 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.responses.ResponseActionBuilder;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
48 import org.onap.appc.dg.objects.InventoryModel;
49 import org.onap.appc.dg.objects.Node;
50 import org.onap.appc.dg.objects.VnfcDependencyModel;
51 import org.onap.appc.domainmodel.Vnf;
52 import org.onap.appc.domainmodel.Vnfc;
53 import org.onap.appc.domainmodel.Vserver;
54 import org.onap.appc.domainmodel.lcm.VNFOperation;
55 import org.onap.appc.exceptions.APPCException;
56 import org.onap.appc.seqgen.SequenceGenerator;
57 import org.onap.appc.seqgen.impl.SequenceGeneratorFactory;
58 import org.onap.appc.seqgen.objects.Constants;
59 import org.onap.appc.seqgen.objects.PreCheckOption;
60 import org.onap.appc.seqgen.objects.RequestInfo;
61 import org.onap.appc.seqgen.objects.RequestInfoBuilder;
62 import org.onap.appc.seqgen.objects.Response;
63 import org.onap.appc.seqgen.objects.SequenceGeneratorInput;
64 import org.onap.appc.seqgen.objects.SequenceGeneratorInputBuilder;
65 import org.onap.appc.seqgen.objects.Transaction;
66 import java.util.HashMap;
67 import java.util.HashSet;
68 import java.util.LinkedList;
69 import java.util.List;
72 import java.util.concurrent.ExecutorService;
73 import java.util.concurrent.Executors;
74 import java.util.concurrent.Future;
77 public class SequenceGeneratorProvider implements AutoCloseable,SequenceGeneratorService{
78 protected DataBroker dataBroker;
79 protected RpcProviderRegistry rpcRegistry;
80 protected NotificationProviderService notificationService;
81 protected BindingAwareBroker.RpcRegistration<SequenceGeneratorService> rpcRegistration;
82 private final EELFLogger log = EELFManager.getInstance().getLogger(SequenceGeneratorProvider.class);
83 private final ExecutorService executor;
84 private final static String APP_NAME = "SequenceGeneratorProvider";
86 public SequenceGeneratorProvider(DataBroker dataBroker2, NotificationProviderService notificationProviderService
87 , RpcProviderRegistry rpcRegistry2) {
88 log.info("Creating provider for " + APP_NAME);
89 executor = Executors.newFixedThreadPool(1);
90 this.dataBroker = dataBroker2;
91 this.notificationService = notificationProviderService;
93 this.rpcRegistry = rpcRegistry2;
95 if (this.rpcRegistry != null) {
96 rpcRegistration = rpcRegistry.addRpcImplementation(SequenceGeneratorService.class, this);
98 log.info("Initialization complete for " + APP_NAME);
102 public void close() throws Exception {
103 log.info("Closing provider for " + APP_NAME);
104 if(this.executor != null){
107 if(this.rpcRegistration != null){
108 rpcRegistration.close();
110 log.info("Successfully closed provider for " + APP_NAME);
114 public Future<RpcResult<GenerateSequenceOutput>> generateSequence(GenerateSequenceInput input) {
115 RpcResult<GenerateSequenceOutput> rpcResult=null;
116 log.debug("Received input = " + input );
118 if(input.getRequestInfo()==null){
119 throw new APPCException("Request info is missing in the input");
121 SequenceGenerator seqGenerator = SequenceGeneratorFactory.getInstance()
122 .createSequenceGenerator(VNFOperation.findByString(input.getRequestInfo().getAction().name()));
123 SequenceGeneratorInput seqGenInput = buildSeqGenInput(input);
124 List<Transaction> transactions = seqGenerator.generateSequence(seqGenInput);
125 rpcResult = buildSuccessResponse(transactions);
126 } catch (Exception e) {
127 log.error("Error Generating Sequence",e);
128 rpcResult = buildFailureResponse(e.getMessage());
130 return Futures.immediateFuture(rpcResult);
133 private RpcResult<GenerateSequenceOutput> buildSuccessResponse(List<Transaction> transactions) {
134 log.info("Building response from the list of transactions");
135 List<Transactions> transactionList = new LinkedList<>();
136 for(Transaction transaction:transactions){
137 ActionIdentifier actionIdentifier = buildActionIdentifierForResponse(transaction);
138 List<PrecheckOptions> precheckOptions = buildPrecheckOptionsForResponse(transaction);
139 List<Responses> responseList = getResponses(transaction);
140 Transactions transactionObj
141 = new TransactionsBuilder()
142 .setActionIdentifier(actionIdentifier)
143 .setAction(transaction.getAction())
144 .setActionLevel(transaction.getActionLevel())
145 .setPrecheckOperator(transaction.getPreCheckOperator())
146 .setPayload(transaction.getPayload())
147 .setTransactionId(transaction.getTransactionId())
148 .setPrecheckOptions(precheckOptions)
149 .setResponses(responseList)
151 transactionList.add(transactionObj);
154 GenerateSequenceOutputBuilder builder = new GenerateSequenceOutputBuilder()
155 .setTransactions(transactionList);
157 return RpcResultBuilder
158 .<GenerateSequenceOutput> status(true)
159 .withResult(builder.build()).build();
162 private ActionIdentifier buildActionIdentifierForResponse(Transaction transaction) {
163 log.info("Adding action identifiers to response.");
164 ActionIdentifier actionIdentifier = null;
165 if(transaction.getActionIdentifier() != null){
166 actionIdentifier = new ActionIdentifierBuilder()
167 .setVnfId(transaction.getActionIdentifier().getVnfId())
168 .setVnfcName(transaction.getActionIdentifier().getVnfcName())
169 .setVserverId(transaction.getActionIdentifier().getvServerId())
172 return actionIdentifier;
175 private List<PrecheckOptions> buildPrecheckOptionsForResponse(Transaction transaction) {
176 log.info("Adding Precheck options to response");
177 List<PrecheckOptions> precheckOptions = new LinkedList<>();
178 if(transaction.getPrecheckOptions()!=null){
179 for(PreCheckOption option:transaction.getPrecheckOptions()){
180 PrecheckOptions precheckOption = new PrecheckOptionsBuilder()
181 .setParamName(option.getParamName())
182 .setParamValue(option.getParamValue())
183 .setPreTransactionId(option.getPreTransactionId())
184 .setRule(option.getRule())
186 precheckOptions.add(precheckOption);
189 return precheckOptions;
191 private List<Responses> getResponses(Transaction transaction) {
192 List<Responses> responseList = new LinkedList<>();
193 for(Response resp : transaction.getResponses()){
194 Map<String,String> responseActions = resp.getResponseAction();
195 ResponseActionBuilder responseActionBuilder = new ResponseActionBuilder();
196 if(responseActions.get(Constants.ResponseAction.WAIT.getAction())!=null){
197 responseActionBuilder = responseActionBuilder.setWait(Integer.parseInt(responseActions.get(Constants.ResponseAction.WAIT.getAction())));
199 if(responseActions.get(Constants.ResponseAction.RETRY.getAction())!=null){
200 responseActionBuilder = responseActionBuilder.setRetry(Integer.parseInt(responseActions.get(Constants.ResponseAction.RETRY.getAction())));
202 if(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())!=null){
203 responseActionBuilder = responseActionBuilder
204 .setContinue(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())));
206 if(responseActions.get(Constants.ResponseAction.IGNORE.getAction()) !=null){
207 responseActionBuilder = responseActionBuilder.setIgnore(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.IGNORE.getAction())));
209 if(responseActions.get(Constants.ResponseAction.STOP.getAction()) !=null){
210 responseActionBuilder = responseActionBuilder.setStop(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.STOP.getAction())));
212 if(responseActions.get(Constants.ResponseAction.JUMP.getAction()) !=null){
213 responseActionBuilder = responseActionBuilder.setJump(Integer.parseInt(responseActions.get(Constants.ResponseAction.JUMP.getAction())));
215 Responses response = new ResponsesBuilder()
216 .setResponseMessage(resp.getResponseMessage())
217 .setResponseAction(responseActionBuilder.build())
219 responseList.add(response);
224 private SequenceGeneratorInput buildSeqGenInput(GenerateSequenceInput input) throws APPCException {
226 log.info("Building SequenceGeneratorInput from Yang object GenerateSequenceInput.");
227 validateMandatory(input);
229 RequestInfo requestInfo = buildRequestInfoForSeqGenInput(input);
230 InventoryModel inventoryModel = readInventoryModel(input);
232 VnfcDependencyModel dependencyModel = readDependencyModel(input);
233 if(dependencyModel!=null){
234 validateInventoryModelWithDependencyModel(dependencyModel,inventoryModel);
237 SequenceGeneratorInputBuilder builder = new SequenceGeneratorInputBuilder()
238 .requestInfo(requestInfo)
239 .inventoryModel(inventoryModel)
240 .dependendcyModel(dependencyModel);
242 builder = buildCapabilitiesForSeqGenInput(input, builder);
244 builder = buildTunableParamsForSeqGenInput(input, builder);
246 return builder.build();
249 private SequenceGeneratorInputBuilder buildTunableParamsForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
250 log.info("Initializing Tunable Parameters based on YANG object.");
251 if(input.getTunableParameters() != null){
252 builder = builder.tunableParameter(Constants.RETRY_COUNT,String.valueOf(input.getTunableParameters().getRetryCount()))
253 .tunableParameter(Constants.WAIT_TIME,String.valueOf(input.getTunableParameters().getWaitTime()));
254 if(input.getTunableParameters().getStrategy() !=null){
255 builder = builder.tunableParameter(Constants.STRATEGY,input.getTunableParameters().getStrategy().name());
261 private SequenceGeneratorInputBuilder buildCapabilitiesForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
262 log.info("Initializing capabilities based on YANG object.");
263 if(input.getCapabilities() !=null){
264 if(input.getCapabilities().getVnf()!=null){
265 builder = builder.capability("vnf",input.getCapabilities().getVnf());
267 if(input.getCapabilities().getVnfc()!=null){
268 builder = builder.capability("vnfc",input.getCapabilities().getVnfc());
270 if(input.getCapabilities().getVm()!=null){
271 builder = builder.capability("vm",input.getCapabilities().getVm());
273 if(input.getCapabilities().getVfModule()!=null){
274 builder = builder.capability("vf-module",input.getCapabilities().getVfModule());
281 private void validateInventoryModelWithDependencyModel(VnfcDependencyModel dependencyModel, InventoryModel inventoryModel) throws APPCException {
282 Set<String> dependencyModelVnfcSet = new HashSet<>();
283 Set<String> dependencyModelMandatoryVnfcSet = new HashSet<>();
284 Set<String> inventoryModelVnfcsSet = new HashSet<>();
286 for (Node<Vnfc> node : dependencyModel.getDependencies()) {
287 dependencyModelVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
288 if (node.getChild().isMandatory()) {
289 dependencyModelMandatoryVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
293 for (Vnfc vnfc : inventoryModel.getVnf().getVnfcs()) {
294 inventoryModelVnfcsSet.add(vnfc.getVnfcType().toLowerCase());
297 // if dependency model and inventory model contains same set of VNFCs, validation succeed and hence return
298 if (dependencyModelVnfcSet.equals(inventoryModelVnfcsSet)) {
302 if (inventoryModelVnfcsSet.size() >= dependencyModelVnfcSet.size()) {
303 Set<String> difference = new HashSet<>(inventoryModelVnfcsSet);
304 difference.removeAll(dependencyModelVnfcSet);
305 log.error("Dependency model is missing following vnfc type(s): " + difference);
306 throw new APPCException("Dependency model is missing following vnfc type(s): " + difference);
308 Set<String> difference = new HashSet<>(dependencyModelMandatoryVnfcSet);
309 difference.removeAll(inventoryModelVnfcsSet);
310 if (difference.size() > 0) {
311 log.error("Inventory model is missing following mandatory vnfc type(s): " + difference);
312 throw new APPCException("VMs missing for the mandatory VNFC : " + difference);
317 private RequestInfo buildRequestInfoForSeqGenInput(GenerateSequenceInput input) {
318 log.info("Building RequestInfo from Yang object");
319 RequestInfoBuilder requestInfobuilder = buildRequestInformation(input);
321 if(input.getRequestInfo().getActionIdentifier() !=null){
322 requestInfobuilder = buildActionIdentifiers(input, requestInfobuilder);
325 return requestInfobuilder.build();
328 private RequestInfoBuilder buildActionIdentifiers(GenerateSequenceInput input, RequestInfoBuilder requestInfobuilder) {
329 log.info("Initializing actionIdentifier for RequestInfo");
330 requestInfobuilder = requestInfobuilder
332 .vnfId(input.getRequestInfo().getActionIdentifier().getVnfId())
333 .vnfcName(input.getRequestInfo().getActionIdentifier().getVnfcName())
334 .vServerId(input.getRequestInfo().getActionIdentifier().getVserverId());
335 return requestInfobuilder;
338 private RequestInfoBuilder buildRequestInformation(GenerateSequenceInput input) {
339 log.info("Initializing action, actionLevel and payload for RequestInfo");
340 return new RequestInfoBuilder()
341 .action(input.getRequestInfo().getAction().name())
342 .actionLevel(input.getRequestInfo().getActionLevel().getName().toLowerCase())
343 .payload(input.getRequestInfo().getPayload());
346 private void validateMandatory(GenerateSequenceInput input) throws APPCException {
347 if(input.getRequestInfo() ==null){
348 throw new APPCException("Request Info is not present in the request");
350 if(input.getRequestInfo().getAction() ==null){
351 throw new APPCException("Action is not present in the request");
353 if(input.getInventoryInfo() ==null){
354 throw new APPCException("inventoryInfo is not provided in the input");
356 if (input.getInventoryInfo().getVnfInfo()== null) {
357 log.error("vnfInfo is null in the input");
358 throw new APPCException("vnfInfo is missing in the input");
360 if(input.getInventoryInfo().getVnfInfo().getVm().isEmpty()){
361 log.error("Null vm information in input.");
362 throw new APPCException("VnfInfo is missing in the input");
364 log.info("Mandatory information present in the request.");
367 private VnfcDependencyModel readDependencyModel(GenerateSequenceInput input) throws APPCException{
368 log.info("Initializing DependencyModel from YANG model.");
369 if(input.getDependencyInfo() == null || input.getDependencyInfo().getVnfcs() ==null || input.getDependencyInfo().getVnfcs().isEmpty()){
370 log.info("No dependency model information is present for the request.");
373 List<Vnfcs> vnfcs = input.getDependencyInfo().getVnfcs();
374 Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies = new HashSet<>();
375 Set<String> parentVnfcs=new HashSet<>();
376 Set<String> allVnfcTypes=new HashSet<>();
377 for(Vnfcs vnfcObj:vnfcs){
378 org.onap.appc.domainmodel.Vnfc vnfc = new org.onap.appc.domainmodel.Vnfc();
379 vnfc.setVnfcType(vnfcObj.getVnfcType());
380 allVnfcTypes.add(vnfcObj.getVnfcType());
381 vnfc.setResilienceType(vnfcObj.getResilience());
382 Node<Vnfc> currentNode = buildVnfcNodeForDependenyInfo(dependencies, vnfcObj, vnfc);
383 for(String parentVnfcType:vnfcObj.getParents()){
384 parentVnfcs.add(parentVnfcType);
385 Node<Vnfc> parentNode = readNode(parentVnfcType,dependencies);
386 if(parentNode == null){
387 Vnfc parentVnfc = new Vnfc();
388 parentVnfc.setVnfcType(parentVnfcType);
389 parentNode = new Node<>(parentVnfc);
390 currentNode.addParent(parentVnfc);
391 dependencies.add(parentNode);
394 currentNode.addParent(parentNode.getChild());
398 for(String parent:parentVnfcs){
399 if(!allVnfcTypes.contains(parent)){
400 throw new APPCException("Dependency model missing vnfc type "+parent);
403 return new VnfcDependencyModel(dependencies);
406 private Node<Vnfc> buildVnfcNodeForDependenyInfo(Set<Node<Vnfc>> dependencies, Vnfcs vnfcObj, Vnfc vnfc) {
407 Node<Vnfc> currentNode = readNode(vnfcObj.getVnfcType(),dependencies);
408 if(currentNode == null){
409 currentNode = new Node<>(vnfc);
410 dependencies.add(currentNode);
413 currentNode.getChild().setResilienceType(vnfcObj.getResilience());
414 currentNode.getChild().setMandatory(vnfcObj.isMandatory());
419 private Node<org.onap.appc.domainmodel.Vnfc> readNode(String vnfcType, Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies) {
420 for(Node<org.onap.appc.domainmodel.Vnfc> node : dependencies){
421 if(node.getChild().getVnfcType().equalsIgnoreCase(vnfcType)){
428 private InventoryModel readInventoryModel(GenerateSequenceInput input) throws APPCException {
430 log.info("Initializing InventoryModel from Yang input model");
431 Vnf vnf = createVnfForInventoryModel(input);
432 Map<org.onap.appc.domainmodel.Vnfc,List<Vserver>> map = new HashMap<>();
433 buildVserverDetailsForInventoryModel(input, vnf, map);
434 for(Map.Entry<org.onap.appc.domainmodel.Vnfc,List<Vserver>> entry:map.entrySet()){
435 org.onap.appc.domainmodel.Vnfc vnfc = entry.getKey();
436 List<Vserver> vmList = entry.getValue();
437 vnfc.addVservers(vmList);
439 return new InventoryModel(vnf);
442 private void buildVserverDetailsForInventoryModel(GenerateSequenceInput input, Vnf vnf, Map<Vnfc, List<Vserver>> map) throws APPCException {
443 if(input.getInventoryInfo().getVnfInfo().getVm().size()<1){
444 throw new APPCException("vnfInfo is missing in the input");
446 for(Vm vm:input.getInventoryInfo().getVnfInfo().getVm()){
447 if(StringUtils.isBlank(vm.getVserverId())){
448 throw new APPCException("vserver-id not found ");
450 Vserver vserver=new Vserver();
451 vserver.setId(vm.getVserverId());
452 if(!StringUtils.isBlank(vm.getVnfc().getVnfcName()) &&
453 !StringUtils.isBlank(vm.getVnfc().getVnfcType())){
454 Vnfc vfc = new Vnfc();
455 vfc.setVnfcName(vm.getVnfc().getVnfcName());
456 vfc.setVnfcType(vm.getVnfc().getVnfcType());
457 vserver.setVnfc(vfc);
458 List<Vserver> vms = map.get(vfc);
460 vms = new LinkedList<>();
465 vnf.addVserver(vserver);
469 private Vnf createVnfForInventoryModel(GenerateSequenceInput input) {
470 log.info("Setting VnfId and VnfType values for Vnf Inventory Model ");
472 vnf.setVnfId(input.getInventoryInfo().getVnfInfo().getVnfId());
473 vnf.setVnfType(input.getInventoryInfo().getVnfInfo().getVnfType());
474 vnf.setIdentityUrl(input.getInventoryInfo().getVnfInfo().getIdentityUrl());
478 private RpcResult<GenerateSequenceOutput> buildFailureResponse(String errorMessage){
479 GenerateSequenceOutputBuilder sequenceGeneratorOutputBuilder=new GenerateSequenceOutputBuilder();
480 StatusBuilder statusBuilder =new StatusBuilder();
481 statusBuilder.setCode(401);
482 statusBuilder.setMessage(errorMessage);
483 sequenceGeneratorOutputBuilder.setStatus(statusBuilder.build());
484 return RpcResultBuilder
485 .<GenerateSequenceOutput> status(true)
486 .withResult(sequenceGeneratorOutputBuilder.build())