OPNFLWPLUG-986: Administrative Reconciliation for multiple/all Nodes
[openflowplugin.git] / applications / southbound-cli / src / main / java / org / opendaylight / openflowplugin / applications / southboundcli / AdminReconciliationServiceImpl.java
1 /*
2  * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowplugin.applications.southboundcli;
10
11 import com.google.common.util.concurrent.SettableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import java.util.stream.Collectors;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.openflowplugin.applications.southboundcli.util.OFNode;
21 import org.opendaylight.openflowplugin.applications.southboundcli.util.ShellUtil;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.AdminReconciliationService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.ExecReconciliationInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.ExecReconciliationOutput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.InitReconciliationInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.InitReconciliationInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.InitReconciliationOutput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.ReconciliationService;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.opendaylight.yangtools.yang.common.RpcError;
36 import org.opendaylight.yangtools.yang.common.RpcResult;
37 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class AdminReconciliationServiceImpl implements AdminReconciliationService {
42
43     private static final Logger LOG = LoggerFactory.getLogger(AdminReconciliationServiceImpl.class);
44     private final DataBroker broker;
45     private final ReconciliationService reconciliationService;
46
47     public AdminReconciliationServiceImpl(DataBroker broker, ReconciliationService reconciliationService) {
48         this.broker = broker;
49         this.reconciliationService = reconciliationService;
50     }
51
52
53     @Override
54     public Future<RpcResult<ExecReconciliationOutput>> execReconciliation(ExecReconciliationInput input) {
55         boolean reconcileAllNodes = input.isReconcileAllNodes();
56         List<BigInteger> inputNodes = input.getNodes();
57         if (inputNodes == null) {
58             inputNodes = new ArrayList<>();
59         }
60         if (reconcileAllNodes && inputNodes.size() > 0) {
61             return buildErrorResponse("Error executing command execReconciliation."
62                     + "If 'all' option is enabled, no Node must be specified as input parameter.");
63         }
64         if (!reconcileAllNodes && inputNodes.size() == 0) {
65             return buildErrorResponse("Error executing command execReconciliation. No Node information was specified.");
66         }
67         SettableFuture<RpcResult<ExecReconciliationOutput>> result = SettableFuture.create();
68         List<Long> nodeList = getAllNodes();
69         List<Long> nodesToReconcile = reconcileAllNodes ? nodeList :
70                 inputNodes.stream().distinct().map(node -> node.longValue()).collect(Collectors.toList());
71         if (nodesToReconcile.size() > 0) {
72             List<Long> unresolvedNodes =
73                     nodesToReconcile.stream().filter(node -> !nodeList.contains(node)).collect(Collectors.toList());
74             if (!unresolvedNodes.isEmpty()) {
75                 return buildErrorResponse("Node(s) not found: " + String.join(", ", unresolvedNodes.toString()));
76             }
77             for (Long nodeId : nodesToReconcile) {
78                 LOG.info("Executing admin reconciliation for node {}", nodeId);
79                 BigInteger node = new BigInteger(String.valueOf(nodeId));
80                 NodeKey nodeKey = new NodeKey(new NodeId("openflow:" + nodeId));
81                 InitReconciliationInput initReconInput = new InitReconciliationInputBuilder()
82                         .setNodeId(node).setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class)
83                                 .child(Node.class, nodeKey).build())).build();
84                 Future<RpcResult<InitReconciliationOutput>> initReconOutput = reconciliationService
85                         .initReconciliation(initReconInput);
86                 try {
87                     RpcResult<InitReconciliationOutput> rpcResult = initReconOutput.get();
88                     if (rpcResult.isSuccessful()) {
89                         LOG.info("Reconciliation successfully completed for node {}", nodeId);
90                     } else {
91                         LOG.error("Reconciliation failed for node {} with error {}", nodeId, rpcResult.getErrors());
92                     }
93                 } catch (ExecutionException | InterruptedException e) {
94                     LOG.error("Error occurred while invoking execReconciliation RPC for node {}", nodeId, e);
95                 }
96             }
97         } else {
98             return buildErrorResponse("No node found");
99         }
100         result.set(RpcResultBuilder.<ExecReconciliationOutput>success().build());
101         return result;
102     }
103
104     private Future<RpcResult<ExecReconciliationOutput>> buildErrorResponse(String msg) {
105         SettableFuture<RpcResult<ExecReconciliationOutput>> result = SettableFuture.create();
106         LOG.error(msg);
107         RpcError error = RpcResultBuilder.newError(RpcError.ErrorType.PROTOCOL, "execReconciliation", msg);
108         List<RpcError> errors = Collections.singletonList(error);
109         result.set(RpcResultBuilder.<ExecReconciliationOutput>failed().withRpcErrors(errors).build());
110         return result;
111     }
112
113     public List<Long> getAllNodes() {
114         List<OFNode> nodeList = ShellUtil.getAllNodes(broker);
115         List<Long> nodes = nodeList.stream().distinct().map(node -> node.getNodeId()).collect(Collectors.toList());
116         return nodes;
117     }
118 }
119