ovsdb enable checkstyle on error
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / reconciliation / configuration / BridgeConfigReconciliationTask.java
1 /*
2  * Copyright (c) 2016 , NEC Corporation 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 package org.opendaylight.ovsdb.southbound.reconciliation.configuration;
9
10
11 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
12
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.CheckedFuture;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Set;
21 import javax.annotation.Nullable;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
24 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
25 import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
26 import org.opendaylight.ovsdb.southbound.OvsdbConnectionManager;
27 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
28 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
29 import org.opendaylight.ovsdb.southbound.ovsdb.transact.BridgeOperationalState;
30 import org.opendaylight.ovsdb.southbound.ovsdb.transact.DataChangesManagedByOvsdbNodeEvent;
31 import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactCommandAggregator;
32 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
33 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationTask;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryKey;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
41 import org.opendaylight.yangtools.yang.binding.DataObject;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * Configuration Reconciliation task to reconcile existing bridge configurations in the config datastore and the
49  * switch when the latter is up and connected to the controller.
50  * Created by Vinh Nguyen (vinh.nguyen@hcl.com) on 3/21/16.
51  */
52 public class BridgeConfigReconciliationTask extends ReconciliationTask {
53
54     private static final Logger LOG = LoggerFactory.getLogger(BridgeConfigReconciliationTask.class);
55     private final OvsdbConnectionInstance connectionInstance;
56
57     public BridgeConfigReconciliationTask(ReconciliationManager reconciliationManager, OvsdbConnectionManager
58             connectionManager, InstanceIdentifier<?> nodeIid, OvsdbConnectionInstance connectionInstance) {
59         super(reconciliationManager, connectionManager, nodeIid, null);
60         this.connectionInstance = connectionInstance;
61
62     }
63
64     @Override
65     public boolean reconcileConfiguration(OvsdbConnectionManager connectionManager) {
66         InstanceIdentifier<Topology> topologyInstanceIdentifier = SouthboundMapper.createTopologyInstanceIdentifier();
67         ReadOnlyTransaction tx = reconciliationManager.getDb().newReadOnlyTransaction();
68
69         // find all bridges of the specific device in the config data store
70         // TODO: this query is not efficient. It retrieves all the Nodes in the datastore, loop over them and look for
71         // the bridges of specific device. It is mre efficient if MDSAL allows query nodes using wildcard on node id
72         // (ie: ovsdb://uuid/<device uuid>/bridge/*) r attributes
73         CheckedFuture<Optional<Topology>, ReadFailedException> readTopologyFuture =
74                 tx.read(CONFIGURATION, topologyInstanceIdentifier);
75         Futures.addCallback(readTopologyFuture, new FutureCallback<Optional<Topology>>() {
76             @Override
77             public void onSuccess(@Nullable Optional<Topology> optionalTopology) {
78                 if (optionalTopology != null && optionalTopology.isPresent()) {
79                     @SuppressWarnings("unchecked")
80                     InstanceIdentifier<Node> ndIid = (InstanceIdentifier<Node>) nodeIid;
81                     Topology topology = optionalTopology.get();
82                     if (topology.getNode() != null) {
83                         final Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
84                         for (Node node : topology.getNode()) {
85                             OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
86                             if (bridge != null && bridge.getManagedBy() != null
87                                     && bridge.getManagedBy().getValue().equals(ndIid)) {
88                                 changes.putAll(extractBridgeConfigurationChanges(node, bridge));
89                             }
90                         }
91                         if (!changes.isEmpty()) {
92                             reconcileBridgeConfigurations(changes);
93                         }
94                     }
95                 }
96             }
97
98             @Override
99             public void onFailure(Throwable throwable) {
100                 LOG.warn("Read Config/DS for Topology failed! {}", nodeIid, throwable);
101             }
102
103         });
104
105         return true;
106     }
107
108     private Map<InstanceIdentifier<?>, DataObject> extractBridgeConfigurationChanges(
109             final Node bridgeNode, final OvsdbBridgeAugmentation ovsdbBridge) {
110         Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
111         final InstanceIdentifier<Node> bridgeNodeIid =
112                 SouthboundMapper.createInstanceIdentifier(connectionInstance, ovsdbBridge.getBridgeName().getValue());
113         final InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbBridgeIid =
114                 bridgeNodeIid.builder().augmentation(OvsdbBridgeAugmentation.class).build();
115         changes.put(bridgeNodeIid, bridgeNode);
116         changes.put(ovsdbBridgeIid, ovsdbBridge);
117
118         if (ovsdbBridge.getProtocolEntry() != null) {
119             for (ProtocolEntry protocol : ovsdbBridge.getProtocolEntry()) {
120                 if (SouthboundConstants.OVSDB_PROTOCOL_MAP.get(protocol.getProtocol()) != null) {
121                     KeyedInstanceIdentifier<ProtocolEntry, ProtocolEntryKey> protocolIid =
122                             ovsdbBridgeIid.child(ProtocolEntry.class, protocol.getKey());
123                     changes.put(protocolIid, protocol);
124                 } else {
125                     throw new IllegalArgumentException("Unknown protocol " + protocol.getProtocol());
126                 }
127             }
128         }
129
130         if (ovsdbBridge.getControllerEntry() != null) {
131             for (ControllerEntry controller : ovsdbBridge.getControllerEntry()) {
132                 KeyedInstanceIdentifier<ControllerEntry, ControllerEntryKey> controllerIid =
133                         ovsdbBridgeIid.child(ControllerEntry.class, controller.getKey());
134                 changes.put(controllerIid, controller);
135             }
136         }
137
138         return changes;
139     }
140
141     private void reconcileBridgeConfigurations(final Map<InstanceIdentifier<?>, DataObject> changes) {
142         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvents = new AsyncDataChangeEvent() {
143             @Override
144             public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
145                 return changes;
146             }
147
148             @Override
149             public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
150                 return Collections.emptyMap();
151             }
152
153             @Override
154             public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
155                 return Collections.emptyMap();
156             }
157
158             @Override
159             public Set<InstanceIdentifier<?>> getRemovedPaths() {
160                 return Collections.emptySet();
161             }
162
163             @Override
164             public DataObject getOriginalSubtree() {
165                 return null;
166             }
167
168             @Override
169             public DataObject getUpdatedSubtree() {
170                 return null;
171             }
172         };
173
174         connectionInstance.transact(new TransactCommandAggregator(),
175                 new BridgeOperationalState(reconciliationManager.getDb(), changeEvents),
176                 new DataChangesManagedByOvsdbNodeEvent(
177                         reconciliationManager.getDb(),
178                         connectionInstance.getInstanceIdentifier(),
179                         changeEvents));
180     }
181
182     @Override
183     public void doRetry(boolean wasPreviousAttemptSuccessful) {
184     }
185
186     @Override
187     public void checkReadinessAndProcess() {
188     }
189
190     @Override
191     public long retryDelayInMills() {
192         return 0;
193     }
194 }