2 * ============LICENSE_START=======================================================
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
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 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.onap.appc.seqgen.provider;
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.google.common.util.concurrent.Futures;
30 import org.apache.commons.lang.StringUtils;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
33 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
34 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
35 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceInput;
36 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutput;
37 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutputBuilder;
38 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.SequenceGeneratorService;
39 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.dependency.info.dependency.info.Vnfcs;
40 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.inventory.info.inventory.info.vnf.info.Vm;
41 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.StatusBuilder;
42 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.Transactions;
43 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.TransactionsBuilder;
44 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.ActionIdentifier;
45 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.*;
46 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.responses.ResponseActionBuilder;
47 import org.opendaylight.yangtools.yang.common.RpcResult;
48 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
49 import org.onap.appc.dg.objects.InventoryModel;
50 import org.onap.appc.dg.objects.Node;
51 import org.onap.appc.dg.objects.VnfcDependencyModel;
52 import org.onap.appc.domainmodel.Vnf;
53 import org.onap.appc.domainmodel.Vnfc;
54 import org.onap.appc.domainmodel.Vserver;
55 import org.onap.appc.domainmodel.lcm.VNFOperation;
56 import org.onap.appc.exceptions.APPCException;
57 import org.onap.appc.seqgen.SequenceGenerator;
58 import org.onap.appc.seqgen.impl.SequenceGeneratorFactory;
59 import org.onap.appc.seqgen.objects.Constants;
60 import org.onap.appc.seqgen.objects.PreCheckOption;
61 import org.onap.appc.seqgen.objects.RequestInfo;
62 import org.onap.appc.seqgen.objects.RequestInfoBuilder;
63 import org.onap.appc.seqgen.objects.Response;
64 import org.onap.appc.seqgen.objects.SequenceGeneratorInput;
65 import org.onap.appc.seqgen.objects.SequenceGeneratorInputBuilder;
66 import org.onap.appc.seqgen.objects.Transaction;
67 import java.util.HashMap;
68 import java.util.HashSet;
69 import java.util.LinkedList;
70 import java.util.List;
73 import java.util.concurrent.ExecutorService;
74 import java.util.concurrent.Executors;
75 import java.util.concurrent.Future;
78 public class SequenceGeneratorProvider implements AutoCloseable,SequenceGeneratorService{
79 protected DataBroker dataBroker;
80 protected RpcProviderRegistry rpcRegistry;
81 protected NotificationProviderService notificationService;
82 protected BindingAwareBroker.RpcRegistration<SequenceGeneratorService> rpcRegistration;
83 private final EELFLogger log = EELFManager.getInstance().getLogger(SequenceGeneratorProvider.class);
84 private final ExecutorService executor;
85 private final static String APP_NAME = "SequenceGeneratorProvider";
87 public SequenceGeneratorProvider(DataBroker dataBroker2, NotificationProviderService notificationProviderService
88 , RpcProviderRegistry rpcRegistry2) {
89 log.info("Creating provider for " + APP_NAME);
90 executor = Executors.newFixedThreadPool(1);
91 this.dataBroker = dataBroker2;
92 this.notificationService = notificationProviderService;
94 this.rpcRegistry = rpcRegistry2;
96 if (this.rpcRegistry != null) {
97 rpcRegistration = rpcRegistry.addRpcImplementation(SequenceGeneratorService.class, this);
99 log.info("Initialization complete for " + APP_NAME);
103 public void close() throws Exception {
104 log.info("Closing provider for " + APP_NAME);
105 if(this.executor != null){
108 if(this.rpcRegistration != null){
109 rpcRegistration.close();
111 log.info("Successfully closed provider for " + APP_NAME);
115 public Future<RpcResult<GenerateSequenceOutput>> generateSequence(GenerateSequenceInput input) {
116 RpcResult<GenerateSequenceOutput> rpcResult=null;
117 log.debug("Received input = " + input );
119 if(input.getRequestInfo()==null){
120 throw new APPCException("Request info is missing in the input");
122 SequenceGenerator seqGenerator = SequenceGeneratorFactory.getInstance()
123 .createSequenceGenerator(VNFOperation.findByString(input.getRequestInfo().getAction().name()));
124 SequenceGeneratorInput seqGenInput = buildSeqGenInput(input);
125 List<Transaction> transactions = seqGenerator.generateSequence(seqGenInput);
126 rpcResult = buildSuccessResponse(transactions);
127 } catch (APPCException e) {
128 log.error("Error Generating Sequence",e);
129 rpcResult = buildFailureResponse(e.getMessage());
131 return Futures.immediateFuture(rpcResult);
134 private RpcResult<GenerateSequenceOutput> buildSuccessResponse(List<Transaction> transactions) {
135 log.info("Building response from the list of transactions");
136 List<Transactions> transactionList = new LinkedList<>();
137 for(Transaction transaction:transactions){
138 ActionIdentifier actionIdentifier = buildActionIdentifierForResponse(transaction);
139 List<PrecheckOptions> precheckOptions = buildPrecheckOptionsForResponse(transaction);
140 List<Responses> responseList = getResponses(transaction);
141 Transactions transactionObj
142 = new TransactionsBuilder()
143 .setActionIdentifier(actionIdentifier)
144 .setAction(transaction.getAction())
145 .setActionLevel(transaction.getActionLevel())
146 .setPrecheckOperator(transaction.getPreCheckOperator())
147 .setPayload(transaction.getPayload())
148 .setTransactionId(transaction.getTransactionId())
149 .setPrecheckOptions(precheckOptions)
150 .setResponses(responseList)
152 transactionList.add(transactionObj);
155 GenerateSequenceOutputBuilder builder = new GenerateSequenceOutputBuilder()
156 .setTransactions(transactionList);
158 return RpcResultBuilder
159 .<GenerateSequenceOutput> status(true)
160 .withResult(builder.build()).build();
163 private ActionIdentifier buildActionIdentifierForResponse(Transaction transaction) {
164 log.info("Adding action identifiers to response.");
165 ActionIdentifier actionIdentifier = null;
166 if(transaction.getActionIdentifier() != null){
167 actionIdentifier = new ActionIdentifierBuilder()
168 .setVnfId(transaction.getActionIdentifier().getVnfId())
169 .setVnfcName(transaction.getActionIdentifier().getVnfcName())
170 .setVserverId(transaction.getActionIdentifier().getvServerId())
173 return actionIdentifier;
176 private List<PrecheckOptions> buildPrecheckOptionsForResponse(Transaction transaction) {
177 log.info("Adding Precheck options to response");
178 List<PrecheckOptions> precheckOptions = new LinkedList<>();
179 if(transaction.getPrecheckOptions()!=null){
180 for(PreCheckOption option:transaction.getPrecheckOptions()){
181 PrecheckOptions precheckOption = new PrecheckOptionsBuilder()
182 .setParamName(option.getParamName())
183 .setParamValue(option.getParamValue())
184 .setPreTransactionId(option.getPreTransactionId())
185 .setRule(option.getRule())
187 precheckOptions.add(precheckOption);
190 return precheckOptions;
192 private List<Responses> getResponses(Transaction transaction) {
193 List<Responses> responseList = new LinkedList<>();
194 for(Response resp : transaction.getResponses()){
195 Map<String,String> responseActions = resp.getResponseAction();
196 ResponseActionBuilder responseActionBuilder = new ResponseActionBuilder();
197 if(responseActions.get(Constants.ResponseAction.WAIT.getAction())!=null){
198 responseActionBuilder = responseActionBuilder.setWait(Integer.parseInt(responseActions.get(Constants.ResponseAction.WAIT.getAction())));
200 if(responseActions.get(Constants.ResponseAction.RETRY.getAction())!=null){
201 responseActionBuilder = responseActionBuilder.setRetry(Integer.parseInt(responseActions.get(Constants.ResponseAction.RETRY.getAction())));
203 if(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())!=null){
204 responseActionBuilder = responseActionBuilder
205 .setContinue(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())));
207 if(responseActions.get(Constants.ResponseAction.IGNORE.getAction()) !=null){
208 responseActionBuilder = responseActionBuilder.setIgnore(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.IGNORE.getAction())));
210 if(responseActions.get(Constants.ResponseAction.STOP.getAction()) !=null){
211 responseActionBuilder = responseActionBuilder.setStop(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.STOP.getAction())));
213 if(responseActions.get(Constants.ResponseAction.JUMP.getAction()) !=null){
214 responseActionBuilder = responseActionBuilder.setJump(Integer.parseInt(responseActions.get(Constants.ResponseAction.JUMP.getAction())));
216 Responses response = new ResponsesBuilder()
217 .setResponseMessage(resp.getResponseMessage())
218 .setResponseAction(responseActionBuilder.build())
220 responseList.add(response);
225 private SequenceGeneratorInput buildSeqGenInput(GenerateSequenceInput input) throws APPCException {
227 log.info("Building SequenceGeneratorInput from Yang object GenerateSequenceInput.");
228 validateMandatory(input);
230 RequestInfo requestInfo = buildRequestInfoForSeqGenInput(input);
231 InventoryModel inventoryModel = readInventoryModel(input);
233 VnfcDependencyModel dependencyModel = readDependencyModel(input);
234 if(dependencyModel!=null){
235 validateInventoryModelWithDependencyModel(dependencyModel,inventoryModel);
238 SequenceGeneratorInputBuilder builder = new SequenceGeneratorInputBuilder()
239 .requestInfo(requestInfo)
240 .inventoryModel(inventoryModel)
241 .dependendcyModel(dependencyModel);
243 builder = buildCapabilitiesForSeqGenInput(input, builder);
245 builder = buildTunableParamsForSeqGenInput(input, builder);
247 return builder.build();
250 private SequenceGeneratorInputBuilder buildTunableParamsForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
251 log.info("Initializing Tunable Parameters based on YANG object.");
252 if(input.getTunableParameters() != null){
253 builder = builder.tunableParameter(Constants.RETRY_COUNT,String.valueOf(input.getTunableParameters().getRetryCount()))
254 .tunableParameter(Constants.WAIT_TIME,String.valueOf(input.getTunableParameters().getWaitTime()));
255 if(input.getTunableParameters().getStrategy() !=null){
256 builder = builder.tunableParameter(Constants.STRATEGY,input.getTunableParameters().getStrategy().name());
262 private SequenceGeneratorInputBuilder buildCapabilitiesForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
263 log.info("Initializing capabilities based on YANG object.");
264 if(input.getCapabilities() !=null){
265 if(input.getCapabilities().getVnf()!=null){
266 builder = builder.capability("vnf",input.getCapabilities().getVnf());
268 if(input.getCapabilities().getVnfc()!=null){
269 builder = builder.capability("vnfc",input.getCapabilities().getVnfc());
271 if(input.getCapabilities().getVm()!=null){
272 builder = builder.capability("vm",input.getCapabilities().getVm());
274 if(input.getCapabilities().getVfModule()!=null){
275 builder = builder.capability("vf-module",input.getCapabilities().getVfModule());
282 private void validateInventoryModelWithDependencyModel(VnfcDependencyModel dependencyModel, InventoryModel inventoryModel) throws APPCException {
283 Set<String> dependencyModelVnfcSet = new HashSet<>();
284 Set<String> dependencyModelMandatoryVnfcSet = new HashSet<>();
285 Set<String> inventoryModelVnfcsSet = new HashSet<>();
287 for (Node<Vnfc> node : dependencyModel.getDependencies()) {
288 dependencyModelVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
289 if (node.getChild().isMandatory()) {
290 dependencyModelMandatoryVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
294 for (Vnfc vnfc : inventoryModel.getVnf().getVnfcs()) {
295 inventoryModelVnfcsSet.add(vnfc.getVnfcType().toLowerCase());
298 // if dependency model and inventory model contains same set of VNFCs, validation succeed and hence return
299 if (dependencyModelVnfcSet.equals(inventoryModelVnfcsSet)) {
303 if (inventoryModelVnfcsSet.size() >= dependencyModelVnfcSet.size()) {
304 Set<String> difference = new HashSet<>(inventoryModelVnfcsSet);
305 difference.removeAll(dependencyModelVnfcSet);
306 log.error("Dependency model is missing following vnfc type(s): " + difference);
307 throw new APPCException("Dependency model is missing following vnfc type(s): " + difference);
309 Set<String> difference = new HashSet<>(dependencyModelMandatoryVnfcSet);
310 difference.removeAll(inventoryModelVnfcsSet);
311 if (difference.size() > 0) {
312 log.error("Inventory model is missing following mandatory vnfc type(s): " + difference);
313 throw new APPCException("VMs missing for the mandatory VNFC : " + difference);
318 private RequestInfo buildRequestInfoForSeqGenInput(GenerateSequenceInput input) {
319 log.info("Building RequestInfo from Yang object");
320 RequestInfoBuilder requestInfobuilder = buildRequestInformation(input);
322 if(input.getRequestInfo().getActionIdentifier() !=null){
323 requestInfobuilder = buildActionIdentifiers(input, requestInfobuilder);
326 return requestInfobuilder.build();
329 private RequestInfoBuilder buildActionIdentifiers(GenerateSequenceInput input, RequestInfoBuilder requestInfobuilder) {
330 log.info("Initializing actionIdentifier for RequestInfo");
331 requestInfobuilder = requestInfobuilder
333 .vnfId(input.getRequestInfo().getActionIdentifier().getVnfId())
334 .vnfcName(input.getRequestInfo().getActionIdentifier().getVnfcName())
335 .vServerId(input.getRequestInfo().getActionIdentifier().getVserverId());
336 return requestInfobuilder;
339 private RequestInfoBuilder buildRequestInformation(GenerateSequenceInput input) {
340 log.info("Initializing action, actionLevel and payload for RequestInfo");
341 return new RequestInfoBuilder()
342 .action(input.getRequestInfo().getAction().name())
343 .actionLevel(input.getRequestInfo().getActionLevel().getName().toLowerCase())
344 .payload(input.getRequestInfo().getPayload());
347 private void validateMandatory(GenerateSequenceInput input) throws APPCException {
348 if(input.getRequestInfo() ==null){
349 throw new APPCException("Request Info is not present in the request");
351 if(input.getRequestInfo().getAction() ==null){
352 throw new APPCException("Action is not present in the request");
354 if(input.getInventoryInfo() ==null){
355 throw new APPCException("inventoryInfo is not provided in the input");
357 if (input.getInventoryInfo().getVnfInfo()== null) {
358 log.error("vnfInfo is null in the input");
359 throw new APPCException("vnfInfo is missing in the input");
361 if(input.getInventoryInfo().getVnfInfo().getVm().isEmpty()){
362 log.error("Null vm information in input.");
363 throw new APPCException("VnfInfo is missing in the input");
365 log.info("Mandatory information present in the request.");
368 private VnfcDependencyModel readDependencyModel(GenerateSequenceInput input) throws APPCException{
369 log.info("Initializing DependencyModel from YANG model.");
370 if(input.getDependencyInfo() == null || input.getDependencyInfo().getVnfcs() ==null || input.getDependencyInfo().getVnfcs().isEmpty()){
371 log.info("No dependency model information is present for the request.");
374 List<Vnfcs> vnfcs = input.getDependencyInfo().getVnfcs();
375 Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies = new HashSet<>();
376 Set<String> parentVnfcs=new HashSet<>();
377 Set<String> allVnfcTypes=new HashSet<>();
378 for(Vnfcs vnfcObj:vnfcs){
379 org.onap.appc.domainmodel.Vnfc vnfc = new org.onap.appc.domainmodel.Vnfc();
380 vnfc.setVnfcType(vnfcObj.getVnfcType());
381 allVnfcTypes.add(vnfcObj.getVnfcType());
382 vnfc.setResilienceType(vnfcObj.getResilience());
383 Node<Vnfc> currentNode = buildVnfcNodeForDependenyInfo(dependencies, vnfcObj, vnfc);
384 for(String parentVnfcType:vnfcObj.getParents()){
385 parentVnfcs.add(parentVnfcType);
386 Node<Vnfc> parentNode = readNode(parentVnfcType,dependencies);
387 if(parentNode == null){
388 Vnfc parentVnfc = new Vnfc();
389 parentVnfc.setVnfcType(parentVnfcType);
390 parentNode = new Node<>(parentVnfc);
391 currentNode.addParent(parentVnfc);
392 dependencies.add(parentNode);
395 currentNode.addParent(parentNode.getChild());
399 for(String parent:parentVnfcs){
400 if(!allVnfcTypes.contains(parent)){
401 throw new APPCException("Dependency model missing vnfc type "+parent);
404 return new VnfcDependencyModel(dependencies);
407 private Node<Vnfc> buildVnfcNodeForDependenyInfo(Set<Node<Vnfc>> dependencies, Vnfcs vnfcObj, Vnfc vnfc) {
408 Node<Vnfc> currentNode = readNode(vnfcObj.getVnfcType(),dependencies);
409 if(currentNode == null){
410 currentNode = new Node<>(vnfc);
411 dependencies.add(currentNode);
414 currentNode.getChild().setResilienceType(vnfcObj.getResilience());
415 currentNode.getChild().setMandatory(vnfcObj.isMandatory());
420 private Node<org.onap.appc.domainmodel.Vnfc> readNode(String vnfcType, Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies) {
421 for(Node<org.onap.appc.domainmodel.Vnfc> node : dependencies){
422 if(node.getChild().getVnfcType().equalsIgnoreCase(vnfcType)){
429 private InventoryModel readInventoryModel(GenerateSequenceInput input) throws APPCException {
431 log.info("Initializing InventoryModel from Yang input model");
432 Vnf vnf = createVnfForInventoryModel(input);
433 Map<org.onap.appc.domainmodel.Vnfc,List<Vserver>> map = new HashMap<>();
434 buildVserverDetailsForInventoryModel(input, vnf, map);
435 for(Map.Entry<org.onap.appc.domainmodel.Vnfc,List<Vserver>> entry:map.entrySet()){
436 org.onap.appc.domainmodel.Vnfc vnfc = entry.getKey();
437 List<Vserver> vmList = entry.getValue();
438 vnfc.addVservers(vmList);
440 return new InventoryModel(vnf);
443 private void buildVserverDetailsForInventoryModel(GenerateSequenceInput input, Vnf vnf, Map<Vnfc, List<Vserver>> map) throws APPCException {
444 if(input.getInventoryInfo().getVnfInfo().getVm().size()<1){
445 throw new APPCException("vnfInfo is missing in the input");
447 for(Vm vm:input.getInventoryInfo().getVnfInfo().getVm()){
448 if(StringUtils.isBlank(vm.getVserverId())){
449 throw new APPCException("vserver-id not found ");
451 Vserver vserver=new Vserver();
452 vserver.setId(vm.getVserverId());
453 if(!StringUtils.isBlank(vm.getVnfc().getVnfcName()) &&
454 !StringUtils.isBlank(vm.getVnfc().getVnfcType())){
455 Vnfc vfc = new Vnfc();
456 vfc.setVnfcName(vm.getVnfc().getVnfcName());
457 vfc.setVnfcType(vm.getVnfc().getVnfcType());
458 vserver.setVnfc(vfc);
459 List<Vserver> vms = map.get(vfc);
461 vms = new LinkedList<>();
466 vnf.addVserver(vserver);
470 private Vnf createVnfForInventoryModel(GenerateSequenceInput input) {
471 log.info("Setting VnfId and VnfType values for Vnf Inventory Model ");
473 vnf.setVnfId(input.getInventoryInfo().getVnfInfo().getVnfId());
474 vnf.setVnfType(input.getInventoryInfo().getVnfInfo().getVnfType());
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())