2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * ================================================================================
9 * Modifications Copyright (C) 2019 Ericsson
10 * =============================================================================
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
23 * ============LICENSE_END=========================================================
26 package org.onap.appc.seqgen.provider;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedList;
31 import java.util.List;
34 import java.util.concurrent.ExecutorService;
35 import java.util.concurrent.Executors;
36 import java.util.concurrent.Future;
37 import org.apache.commons.lang.StringUtils;
38 import org.onap.appc.dg.objects.InventoryModel;
39 import org.onap.appc.dg.objects.Node;
40 import org.onap.appc.dg.objects.VnfcDependencyModel;
41 import org.onap.appc.domainmodel.Vnf;
42 import org.onap.appc.domainmodel.Vnfc;
43 import org.onap.appc.domainmodel.Vserver;
44 import org.onap.appc.domainmodel.lcm.VNFOperation;
45 import org.onap.appc.exceptions.APPCException;
46 import org.onap.appc.seqgen.SequenceGenerator;
47 import org.onap.appc.seqgen.impl.SequenceGeneratorFactory;
48 import org.onap.appc.seqgen.objects.Constants;
49 import org.onap.appc.seqgen.objects.PreCheckOption;
50 import org.onap.appc.seqgen.objects.RequestInfo;
51 import org.onap.appc.seqgen.objects.RequestInfoBuilder;
52 import org.onap.appc.seqgen.objects.Response;
53 import org.onap.appc.seqgen.objects.SequenceGeneratorInput;
54 import org.onap.appc.seqgen.objects.SequenceGeneratorInputBuilder;
55 import org.onap.appc.seqgen.objects.Transaction;
56 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
57 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
58 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
59 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
60 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceInput;
61 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutput;
62 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.GenerateSequenceOutputBuilder;
63 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.SequenceGeneratorService;
64 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.dependency.info.dependency.info.Vnfcs;
65 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.inventory.info.inventory.info.vnf.info.Vm;
66 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.StatusBuilder;
67 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.Transactions;
68 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.TransactionsBuilder;
69 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.ActionIdentifier;
70 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.ActionIdentifierBuilder;
71 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.PrecheckOptions;
72 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.PrecheckOptionsBuilder;
73 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.Responses;
74 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.ResponsesBuilder;
75 import org.opendaylight.yang.gen.v1.org.onap.appc.sequencegenerator.rev170706.response.transactions.responses.ResponseActionBuilder;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
78 import com.att.eelf.configuration.EELFLogger;
79 import com.att.eelf.configuration.EELFManager;
80 import com.google.common.util.concurrent.Futures;
83 public class SequenceGeneratorProvider implements AutoCloseable,SequenceGeneratorService {
84 protected DataBroker dataBroker;
85 protected RpcProviderRegistry rpcRegistry;
86 protected NotificationProviderService notificationService;
87 protected BindingAwareBroker.RpcRegistration<SequenceGeneratorService> rpcRegistration;
88 private final EELFLogger log = EELFManager.getInstance().getLogger(SequenceGeneratorProvider.class);
89 private final ExecutorService executor;
90 private final static String APP_NAME = "SequenceGeneratorProvider";
92 public SequenceGeneratorProvider(DataBroker dataBroker2, NotificationProviderService notificationProviderService,
93 RpcProviderRegistry rpcRegistry2) {
94 log.info("Creating provider for " + APP_NAME);
95 executor = Executors.newFixedThreadPool(1);
96 this.dataBroker = dataBroker2;
97 this.notificationService = notificationProviderService;
99 this.rpcRegistry = rpcRegistry2;
101 if (this.rpcRegistry != null) {
102 rpcRegistration = rpcRegistry.addRpcImplementation(SequenceGeneratorService.class, this);
104 log.info("Initialization complete for " + APP_NAME);
108 public void close() throws Exception {
109 log.info("Closing provider for " + APP_NAME);
110 if(this.executor != null){
113 if(this.rpcRegistration != null) {
114 rpcRegistration.close();
116 log.info("Successfully closed provider for " + APP_NAME);
120 public Future<RpcResult<GenerateSequenceOutput>> generateSequence(GenerateSequenceInput input) {
121 RpcResult<GenerateSequenceOutput> rpcResult=null;
122 log.debug("Received input = " + input );
124 if(input.getRequestInfo()==null){
125 throw new APPCException("Request info is missing in the input");
127 SequenceGenerator seqGenerator = SequenceGeneratorFactory.getInstance()
128 .createSequenceGenerator(VNFOperation.findByString(input.getRequestInfo().getAction().name()));
129 SequenceGeneratorInput seqGenInput = buildSeqGenInput(input);
130 List<Transaction> transactions = seqGenerator.generateSequence(seqGenInput);
131 rpcResult = buildSuccessResponse(transactions);
132 } catch (Exception e) {
133 log.error("Error Generating Sequence",e);
134 rpcResult = buildFailureResponse(e.getMessage());
136 return Futures.immediateFuture(rpcResult);
139 private RpcResult<GenerateSequenceOutput> buildSuccessResponse(List<Transaction> transactions) {
140 log.info("Building response from the list of transactions");
141 List<Transactions> transactionList = new LinkedList<>();
142 for(Transaction transaction: transactions) {
143 ActionIdentifier actionIdentifier = buildActionIdentifierForResponse(transaction);
144 List<PrecheckOptions> precheckOptions = buildPrecheckOptionsForResponse(transaction);
145 List<Responses> responseList = getResponses(transaction);
146 Transactions transactionObj
147 = new TransactionsBuilder()
148 .setActionIdentifier(actionIdentifier)
149 .setAction(transaction.getAction())
150 .setActionLevel(transaction.getActionLevel())
151 .setPrecheckOperator(transaction.getPreCheckOperator())
152 .setPayload(transaction.getPayload())
153 .setTransactionId(transaction.getTransactionId())
154 .setPrecheckOptions(precheckOptions)
155 .setResponses(responseList)
157 transactionList.add(transactionObj);
160 GenerateSequenceOutputBuilder builder = new GenerateSequenceOutputBuilder()
161 .setTransactions(transactionList);
163 return RpcResultBuilder
164 .<GenerateSequenceOutput> status(true)
165 .withResult(builder.build()).build();
168 private ActionIdentifier buildActionIdentifierForResponse(Transaction transaction) {
169 log.info("Adding action identifiers to response.");
170 ActionIdentifier actionIdentifier = null;
171 if(transaction.getActionIdentifier() != null){
172 actionIdentifier = new ActionIdentifierBuilder()
173 .setVnfId(transaction.getActionIdentifier().getVnfId())
174 .setVnfcName(transaction.getActionIdentifier().getVnfcName())
175 .setVserverId(transaction.getActionIdentifier().getvServerId())
178 return actionIdentifier;
181 private List<PrecheckOptions> buildPrecheckOptionsForResponse(Transaction transaction) {
182 log.info("Adding Precheck options to response");
183 List<PrecheckOptions> precheckOptions = new LinkedList<>();
184 if(transaction.getPrecheckOptions() != null){
185 for(PreCheckOption option:transaction.getPrecheckOptions()){
186 PrecheckOptions precheckOption = new PrecheckOptionsBuilder()
187 .setParamName(option.getParamName())
188 .setParamValue(option.getParamValue())
189 .setPreTransactionId(option.getPreTransactionId())
190 .setRule(option.getRule())
192 precheckOptions.add(precheckOption);
195 return precheckOptions;
197 private List<Responses> getResponses(Transaction transaction) {
198 List<Responses> responseList = new LinkedList<>();
199 for(Response resp : transaction.getResponses()){
200 Map<String,String> responseActions = resp.getResponseAction();
201 ResponseActionBuilder responseActionBuilder = new ResponseActionBuilder();
202 if(responseActions.get(Constants.ResponseAction.WAIT.getAction()) != null){
203 responseActionBuilder = responseActionBuilder.setWait(Integer.parseInt(responseActions.get(Constants.ResponseAction.WAIT.getAction())));
205 if(responseActions.get(Constants.ResponseAction.RETRY.getAction()) != null){
206 responseActionBuilder = responseActionBuilder.setRetry(Integer.parseInt(responseActions.get(Constants.ResponseAction.RETRY.getAction())));
208 if(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())!=null){
209 responseActionBuilder = responseActionBuilder
210 .setContinue(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.CONTINUE.getAction().toLowerCase())));
212 if(responseActions.get(Constants.ResponseAction.IGNORE.getAction()) != null){
213 responseActionBuilder = responseActionBuilder.setIgnore(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.IGNORE.getAction())));
215 if(responseActions.get(Constants.ResponseAction.STOP.getAction()) != null){
216 responseActionBuilder = responseActionBuilder.setStop(Boolean.parseBoolean(responseActions.get(Constants.ResponseAction.STOP.getAction())));
218 if(responseActions.get(Constants.ResponseAction.JUMP.getAction()) != null){
219 responseActionBuilder = responseActionBuilder.setJump(Integer.parseInt(responseActions.get(Constants.ResponseAction.JUMP.getAction())));
221 Responses response = new ResponsesBuilder()
222 .setResponseMessage(resp.getResponseMessage())
223 .setResponseAction(responseActionBuilder.build())
225 responseList.add(response);
230 private SequenceGeneratorInput buildSeqGenInput(GenerateSequenceInput input) throws APPCException {
232 log.info("Building SequenceGeneratorInput from Yang object GenerateSequenceInput.");
233 validateMandatory(input);
235 RequestInfo requestInfo = buildRequestInfoForSeqGenInput(input);
236 InventoryModel inventoryModel = readInventoryModel(input);
238 VnfcDependencyModel dependencyModel = readDependencyModel(input);
239 if(dependencyModel != null){
240 validateInventoryModelWithDependencyModel(dependencyModel, inventoryModel);
243 SequenceGeneratorInputBuilder builder = new SequenceGeneratorInputBuilder()
244 .requestInfo(requestInfo)
245 .inventoryModel(inventoryModel)
246 .dependendcyModel(dependencyModel);
248 builder = buildCapabilitiesForSeqGenInput(input, builder);
250 builder = buildTunableParamsForSeqGenInput(input, builder);
252 return builder.build();
255 private SequenceGeneratorInputBuilder buildTunableParamsForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
256 log.info("Initializing Tunable Parameters based on YANG object.");
257 if(input.getTunableParameters() != null){
258 builder = builder.tunableParameter(Constants.RETRY_COUNT,String.valueOf(input.getTunableParameters().getRetryCount()))
259 .tunableParameter(Constants.WAIT_TIME,String.valueOf(input.getTunableParameters().getWaitTime()));
260 if(input.getTunableParameters().getStrategy() != null){
261 builder = builder.tunableParameter(Constants.STRATEGY,input.getTunableParameters().getStrategy().name());
267 private SequenceGeneratorInputBuilder buildCapabilitiesForSeqGenInput(GenerateSequenceInput input, SequenceGeneratorInputBuilder builder) {
268 log.info("Initializing capabilities based on YANG object.");
269 if(input.getCapabilities() != null){
270 if(input.getCapabilities().getVnf() != null){
271 builder = builder.capability("vnf", input.getCapabilities().getVnf());
273 if(input.getCapabilities().getVnfc() != null){
274 builder = builder.capability("vnfc", input.getCapabilities().getVnfc());
276 if(input.getCapabilities().getVm() != null){
277 builder = builder.capability("vm", input.getCapabilities().getVm());
279 if(input.getCapabilities().getVfModule() != null){
280 builder = builder.capability("vf-module", input.getCapabilities().getVfModule());
287 private void validateInventoryModelWithDependencyModel(VnfcDependencyModel dependencyModel, InventoryModel inventoryModel) throws APPCException {
288 Set<String> dependencyModelVnfcSet = new HashSet<>();
289 Set<String> dependencyModelMandatoryVnfcSet = new HashSet<>();
290 Set<String> inventoryModelVnfcsSet = new HashSet<>();
292 for (Node<Vnfc> node : dependencyModel.getDependencies()) {
293 dependencyModelVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
294 if (node.getChild().isMandatory()) {
295 dependencyModelMandatoryVnfcSet.add(node.getChild().getVnfcType().toLowerCase());
299 for (Vnfc vnfc : inventoryModel.getVnf().getVnfcs()) {
300 inventoryModelVnfcsSet.add(vnfc.getVnfcType().toLowerCase());
303 // if dependency model and inventory model contains same set of VNFCs, validation succeed and hence return
304 if (dependencyModelVnfcSet.equals(inventoryModelVnfcsSet)) {
308 if (inventoryModelVnfcsSet.size() >= dependencyModelVnfcSet.size()) {
309 Set<String> difference = new HashSet<>(inventoryModelVnfcsSet);
310 difference.removeAll(dependencyModelVnfcSet);
311 log.error("Dependency model is missing following vnfc type(s): " + difference);
312 throw new APPCException("Dependency model is missing following vnfc type(s): " + difference);
314 Set<String> difference = new HashSet<>(dependencyModelMandatoryVnfcSet);
315 difference.removeAll(inventoryModelVnfcsSet);
316 if (difference.size() > 0) {
317 log.error("Inventory model is missing following mandatory vnfc type(s): " + difference);
318 throw new APPCException("VMs missing for the mandatory VNFC : " + difference);
323 private RequestInfo buildRequestInfoForSeqGenInput(GenerateSequenceInput input) {
324 log.info("Building RequestInfo from Yang object");
325 RequestInfoBuilder requestInfobuilder = buildRequestInformation(input);
327 if(input.getRequestInfo().getActionIdentifier() != null){
328 requestInfobuilder = buildActionIdentifiers(input, requestInfobuilder);
331 return requestInfobuilder.build();
334 private RequestInfoBuilder buildActionIdentifiers(GenerateSequenceInput input, RequestInfoBuilder requestInfobuilder) {
335 log.info("Initializing actionIdentifier for RequestInfo");
336 requestInfobuilder = requestInfobuilder
338 .vnfId(input.getRequestInfo().getActionIdentifier().getVnfId())
339 .vnfcName(input.getRequestInfo().getActionIdentifier().getVnfcName())
340 .vServerId(input.getRequestInfo().getActionIdentifier().getVserverId());
341 return requestInfobuilder;
344 private RequestInfoBuilder buildRequestInformation(GenerateSequenceInput input) {
345 log.info("Initializing action, actionLevel and payload for RequestInfo");
346 return new RequestInfoBuilder()
347 .action(input.getRequestInfo().getAction().name())
348 .actionLevel(input.getRequestInfo().getActionLevel().getName().toLowerCase())
349 .payload(input.getRequestInfo().getPayload());
352 private void validateMandatory(GenerateSequenceInput input) throws APPCException {
353 if(input.getRequestInfo() == null){
354 throw new APPCException("Request Info is not present in the request");
356 if(input.getRequestInfo().getAction() == null){
357 throw new APPCException("Action is not present in the request");
359 if(input.getInventoryInfo() == null){
360 throw new APPCException("inventoryInfo is not provided in the input");
362 if (input.getInventoryInfo().getVnfInfo() == null) {
363 log.error("vnfInfo is null in the input");
364 throw new APPCException("vnfInfo is missing in the input");
366 if(input.getInventoryInfo().getVnfInfo().getVm().isEmpty()){
367 log.error("Null vm information in input.");
368 throw new APPCException("VnfInfo is missing in the input");
370 log.info("Mandatory information present in the request.");
373 private VnfcDependencyModel readDependencyModel(GenerateSequenceInput input) throws APPCException{
374 log.info("Initializing DependencyModel from YANG model.");
375 if(input.getDependencyInfo() == null || input.getDependencyInfo().getVnfcs() == null || input.getDependencyInfo().getVnfcs().isEmpty()){
376 log.info("No dependency model information is present for the request.");
379 List<Vnfcs> vnfcs = input.getDependencyInfo().getVnfcs();
380 Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies = new HashSet<>();
381 Set<String> parentVnfcs = new HashSet<>();
382 Set<String> allVnfcTypes = new HashSet<>();
383 for(Vnfcs vnfcObj:vnfcs) {
384 org.onap.appc.domainmodel.Vnfc vnfc = new org.onap.appc.domainmodel.Vnfc();
385 vnfc.setVnfcType(vnfcObj.getVnfcType());
386 allVnfcTypes.add(vnfcObj.getVnfcType());
387 vnfc.setResilienceType(vnfcObj.getResilience());
388 Node<Vnfc> currentNode = buildVnfcNodeForDependenyInfo(dependencies, vnfcObj, vnfc);
389 for(String parentVnfcType:vnfcObj.getParents()) {
390 parentVnfcs.add(parentVnfcType);
391 Node<Vnfc> parentNode = readNode(parentVnfcType, dependencies);
392 if(parentNode == null){
393 Vnfc parentVnfc = new Vnfc();
394 parentVnfc.setVnfcType(parentVnfcType);
395 parentNode = new Node<>(parentVnfc);
396 currentNode.addParent(parentVnfc);
397 dependencies.add(parentNode);
400 currentNode.addParent(parentNode.getChild());
404 for(String parent:parentVnfcs){
405 if(!allVnfcTypes.contains(parent)){
406 throw new APPCException("Dependency model missing vnfc type " + parent);
409 return new VnfcDependencyModel(dependencies);
412 private Node<Vnfc> buildVnfcNodeForDependenyInfo(Set<Node<Vnfc>> dependencies, Vnfcs vnfcObj, Vnfc vnfc) {
413 Node<Vnfc> currentNode = readNode(vnfcObj.getVnfcType(), dependencies);
414 if(currentNode == null){
415 currentNode = new Node<>(vnfc);
416 dependencies.add(currentNode);
419 currentNode.getChild().setResilienceType(vnfcObj.getResilience());
420 currentNode.getChild().setMandatory(vnfcObj.isMandatory());
425 private Node<org.onap.appc.domainmodel.Vnfc> readNode(String vnfcType, Set<Node<org.onap.appc.domainmodel.Vnfc>> dependencies) {
426 for(Node<org.onap.appc.domainmodel.Vnfc> node : dependencies){
427 if(node.getChild().getVnfcType().equalsIgnoreCase(vnfcType)){
434 private InventoryModel readInventoryModel(GenerateSequenceInput input) throws APPCException {
436 log.info("Initializing InventoryModel from Yang input model");
437 Vnf vnf = createVnfForInventoryModel(input);
438 Map<org.onap.appc.domainmodel.Vnfc, List<Vserver>> map = new HashMap<>();
439 buildVserverDetailsForInventoryModel(input, vnf, map);
440 for(Map.Entry<org.onap.appc.domainmodel.Vnfc, List<Vserver>> entry:map.entrySet()){
441 org.onap.appc.domainmodel.Vnfc vnfc = entry.getKey();
442 List<Vserver> vmList = entry.getValue();
443 vnfc.addVservers(vmList);
445 return new InventoryModel(vnf);
448 private void buildVserverDetailsForInventoryModel(GenerateSequenceInput input, Vnf vnf, Map<Vnfc, List<Vserver>> map) throws APPCException {
449 if(input.getInventoryInfo().getVnfInfo().getVm().size() < 1) {
450 throw new APPCException("vnfInfo is missing in the input");
452 for(Vm vm:input.getInventoryInfo().getVnfInfo().getVm()) {
453 if(StringUtils.isBlank(vm.getVserverId())){
454 throw new APPCException("vserver-id not found ");
456 Vserver vserver=new Vserver();
457 vserver.setId(vm.getVserverId());
458 if(!StringUtils.isBlank(vm.getVnfc().getVnfcName()) &&
459 !StringUtils.isBlank(vm.getVnfc().getVnfcType())) {
460 Vnfc vfc = new Vnfc();
461 vfc.setVnfcName(vm.getVnfc().getVnfcName());
462 vfc.setVnfcType(vm.getVnfc().getVnfcType());
463 vserver.setVnfc(vfc);
464 List<Vserver> vms = map.get(vfc);
466 vms = new LinkedList<>();
471 vnf.addVserver(vserver);
475 private Vnf createVnfForInventoryModel(GenerateSequenceInput input) {
476 log.info("Setting VnfId and VnfType values for Vnf Inventory Model ");
478 vnf.setVnfId(input.getInventoryInfo().getVnfInfo().getVnfId());
479 vnf.setVnfType(input.getInventoryInfo().getVnfInfo().getVnfType());
480 vnf.setIdentityUrl(input.getInventoryInfo().getVnfInfo().getIdentityUrl());
484 private RpcResult<GenerateSequenceOutput> buildFailureResponse(String errorMessage){
485 GenerateSequenceOutputBuilder sequenceGeneratorOutputBuilder=new GenerateSequenceOutputBuilder();
486 StatusBuilder statusBuilder = new StatusBuilder();
487 statusBuilder.setCode(401);
488 statusBuilder.setMessage(errorMessage);
489 sequenceGeneratorOutputBuilder.setStatus(statusBuilder.build());
490 return RpcResultBuilder
491 .<GenerateSequenceOutput> status(true)
492 .withResult(sequenceGeneratorOutputBuilder.build())