Fixup Augmentable and Identifiable methods changing
[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.base.Optional;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import com.google.common.util.concurrent.SettableFuture;
14 import java.math.BigInteger;
15 import java.time.LocalDateTime;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
21 import java.util.stream.Collectors;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.openflowplugin.applications.southboundcli.alarm.AlarmAgent;
26 import org.opendaylight.openflowplugin.applications.southboundcli.util.OFNode;
27 import org.opendaylight.openflowplugin.applications.southboundcli.util.ShellUtil;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.AdminReconciliationService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.ReconcileInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.ReconcileOutput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.ReconciliationCounter;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.reconciliation.counter.ReconcileCounter;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.reconciliation.counter.ReconcileCounterBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.admin.reconciliation.service.rev180227.reconciliation.counter.ReconcileCounterKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.ReconcileNodeInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.ReconcileNodeInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.ReconcileNodeOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.reconciliation.service.rev180227.ReconciliationService;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.RpcError;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 public class AdminReconciliationServiceImpl implements AdminReconciliationService {
52
53     private static final Logger LOG = LoggerFactory.getLogger(AdminReconciliationServiceImpl.class);
54     private final DataBroker broker;
55     private final ReconciliationService reconciliationService;
56     private final Long startCount = 1L;
57     private final AlarmAgent alarmAgent;
58
59     public AdminReconciliationServiceImpl(final DataBroker broker, final ReconciliationService reconciliationService,
60                                           final AlarmAgent alarmAgent) {
61         this.broker = broker;
62         this.reconciliationService = reconciliationService;
63         this.alarmAgent = alarmAgent;
64     }
65
66
67     @Override
68     public ListenableFuture<RpcResult<ReconcileOutput>> reconcile(ReconcileInput input) {
69         boolean reconcileAllNodes = input.isReconcileAllNodes();
70         List<BigInteger> inputNodes = input.getNodes();
71         if (inputNodes == null) {
72             inputNodes = new ArrayList<>();
73         }
74         if (reconcileAllNodes && inputNodes.size() > 0) {
75             return buildErrorResponse("Error executing command reconcile."
76                     + "If 'all' option is enabled, no Node must be specified as input parameter.");
77         }
78         if (!reconcileAllNodes && inputNodes.size() == 0) {
79             return buildErrorResponse("Error executing command reconcile. No Node information was specified.");
80         }
81         SettableFuture<RpcResult<ReconcileOutput>> result = SettableFuture.create();
82         List<Long> nodeList = getAllNodes();
83         List<Long> nodesToReconcile = reconcileAllNodes ? nodeList :
84                 inputNodes.stream().distinct().map(node -> node.longValue()).collect(Collectors.toList());
85         if (nodesToReconcile.size() > 0) {
86             List<Long> unresolvedNodes =
87                     nodesToReconcile.stream().filter(node -> !nodeList.contains(node)).collect(Collectors.toList());
88             if (!unresolvedNodes.isEmpty()) {
89                 return buildErrorResponse("Node(s) not found: " + String.join(", ", unresolvedNodes.toString()));
90             }
91             for (Long nodeId : nodesToReconcile) {
92                 alarmAgent.raiseAdminReconciliationAlarm(nodeId);
93                 LOG.info("Executing admin reconciliation for node {}", nodeId);
94                 BigInteger node = new BigInteger(String.valueOf(nodeId));
95                 NodeKey nodeKey = new NodeKey(new NodeId("openflow:" + nodeId));
96                 ReconcileNodeInput reconInput = new ReconcileNodeInputBuilder()
97                         .setNodeId(node).setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class)
98                                 .child(Node.class, nodeKey).build())).build();
99                 Future<RpcResult<ReconcileNodeOutput>> reconOutput = reconciliationService
100                         .reconcileNode(reconInput);
101                 try {
102                     RpcResult<ReconcileNodeOutput> rpcResult = reconOutput.get();
103                     if (rpcResult.isSuccessful()) {
104                         increaseReconcileCount(node, true);
105                         LOG.info("Reconciliation successfully completed for node {}", nodeId);
106                     } else {
107                         increaseReconcileCount(node, false);
108                         LOG.error("Reconciliation failed for node {} with error {}", nodeId, rpcResult.getErrors());
109                     }
110                 } catch (ExecutionException | InterruptedException e) {
111                     LOG.error("Error occurred while invoking reconcile RPC for node {}", nodeId, e);
112                 }
113                 alarmAgent.clearAdminReconciliationAlarm(nodeId);
114             }
115         } else {
116             return buildErrorResponse("No node found");
117         }
118         result.set(RpcResultBuilder.<ReconcileOutput>success().build());
119         return result;
120     }
121
122     private ListenableFuture<RpcResult<ReconcileOutput>> buildErrorResponse(String msg) {
123         SettableFuture<RpcResult<ReconcileOutput>> result = SettableFuture.create();
124         LOG.error(msg);
125         RpcError error = RpcResultBuilder.newError(RpcError.ErrorType.PROTOCOL, "reconcile", msg);
126         List<RpcError> errors = Collections.singletonList(error);
127         result.set(RpcResultBuilder.<ReconcileOutput>failed().withRpcErrors(errors).build());
128         return result;
129     }
130
131     public List<Long> getAllNodes() {
132         List<OFNode> nodeList = ShellUtil.getAllNodes(broker);
133         List<Long> nodes = nodeList.stream().distinct().map(node -> node.getNodeId()).collect(Collectors.toList());
134         return nodes;
135     }
136
137     private void increaseReconcileCount(BigInteger nodeId, Boolean reconcileState) {
138         InstanceIdentifier<ReconcileCounter> instanceIdentifier = InstanceIdentifier
139                 .builder(ReconciliationCounter.class).child(ReconcileCounter.class,
140                         new ReconcileCounterKey(nodeId)).build();
141         ReadWriteTransaction tx = broker.newReadWriteTransaction();
142         Optional<ReconcileCounter> optional = readReconcileCounterFromDS(tx, instanceIdentifier, nodeId);
143         ReconcileCounterBuilder counterBuilder = new ReconcileCounterBuilder()
144                 .withKey(new ReconcileCounterKey(nodeId)).setNodeId(nodeId)
145                 .setLastRequestTime(LocalDateTime.now().toString());
146         if (reconcileState) {
147             counterBuilder.setSuccessCount(startCount);
148             if (optional.isPresent()) {
149                 ReconcileCounter counter = optional.get();
150                 Long successCount = counter.getSuccessCount();
151                 counterBuilder.setSuccessCount(++successCount);
152                 LOG.debug("Reconcile Success count {} for the node: {} ", successCount, nodeId);
153             }
154         } else {
155             counterBuilder.setFailureCount(startCount);
156             if (optional.isPresent()) {
157                 ReconcileCounter counter = optional.get();
158                 Long failureCount = counter.getFailureCount();
159                 counterBuilder.setFailureCount(++failureCount);
160                 LOG.debug("Reconcile Failure count {} for the node: {} ", failureCount, nodeId);
161             }
162         }
163         try {
164             tx.merge(LogicalDatastoreType.OPERATIONAL, instanceIdentifier, counterBuilder.build(), true);
165             tx.submit().get();
166         } catch (InterruptedException | ExecutionException e) {
167             LOG.error("Exception while submitting counter {}", nodeId, e);
168         }
169     }
170
171     private Optional<ReconcileCounter> readReconcileCounterFromDS(ReadWriteTransaction tx,
172                 InstanceIdentifier<ReconcileCounter> instanceIdentifier, BigInteger nodeId) {
173         try {
174             return tx.read(LogicalDatastoreType.OPERATIONAL, instanceIdentifier).get();
175         } catch (InterruptedException | ExecutionException e) {
176             LOG.error("Exception while reading counter for node: {}", nodeId, e);
177         }
178         return Optional.absent();
179     }
180 }
181