1 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.ovsdb;
3 import java.util.ArrayList;
5 import java.util.Map.Entry;
6 import java.util.concurrent.ExecutionException;
8 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
9 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
10 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
11 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
12 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
15 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
37 import org.opendaylight.yangtools.concepts.ListenerRegistration;
38 import org.opendaylight.yangtools.yang.binding.DataObject;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import com.google.common.base.Optional;
44 import com.google.common.util.concurrent.CheckedFuture;
46 public class OfOverlayOvsdbBridgeDataChangeListener implements DataChangeListener, AutoCloseable {
48 private static final String REMOTE_IP_VALUE = "flow";
49 private static final String REMOTE_IP_KEY = "remote_ip";
50 private static final String VNID_KEY = "key";
51 private static final String VNID_VALUE = "flow";
52 private static final String OFOVERLAY_TUNNEL = "ofoverlay-tun";
53 private static final String OF_PORT = "6653";
54 private static boolean connectController = false;
55 private ListenerRegistration<DataChangeListener> registration;
56 private DataBroker db;
57 private static final Logger LOG = LoggerFactory.getLogger(OfOverlayOvsdbBridgeDataChangeListener.class);
59 public OfOverlayOvsdbBridgeDataChangeListener(DataBroker db) {
61 InstanceIdentifier<Node> iid = InstanceIdentifier
62 .create(NetworkTopology.class)
63 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
65 registration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, this, DataChangeScope.BASE);
69 public void close() throws Exception {
75 public void onDataChanged(
76 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
77 ReadWriteTransaction transaction = db.newReadWriteTransaction();
78 for (Entry<InstanceIdentifier<?>, DataObject> entry :change.getCreatedData().entrySet()) {
79 if(entry.getValue() instanceof Node) {
80 Node node = (Node)entry.getValue();
81 InstanceIdentifier<Node> nodeIid = (InstanceIdentifier<Node>) entry.getKey();
82 OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
84 Optional<OvsdbNodeAugmentation> connectionOptional = getConnection(transaction, bridge);
85 if(connectionOptional.isPresent()) {
87 List<Options> options = getOptions();
89 OvsdbTerminationPointAugmentation ovsdbTp = getOvsdbTerminationPointAugmentation(bridge,options);
91 List<TerminationPoint> tps = getTerminationPoints(bridge,ovsdbTp);
93 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getOvsdbBridgeAugmentation(bridge,connectionOptional.get());
95 Node configNode = getNode(node, tps,ovsdbBridgeAugmentation);
96 LOG.info("About to write nodeId {} node {}",nodeIid,configNode);
97 transaction.merge(LogicalDatastoreType.CONFIGURATION, nodeIid, configNode);
102 transaction.submit();
105 private Node getNode(Node node, List<TerminationPoint> tps,
106 OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
107 NodeBuilder nodeBuilder = new NodeBuilder();
108 nodeBuilder.setKey(node.getKey());
110 nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
111 ovsdbBridgeAugmentation);
113 nodeBuilder.setTerminationPoint(tps);
114 return nodeBuilder.build();
117 private OvsdbBridgeAugmentation getOvsdbBridgeAugmentation(OvsdbBridgeAugmentation bridge,
118 OvsdbNodeAugmentation connection) {
119 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentation = new OvsdbBridgeAugmentationBuilder();
120 List<ControllerEntry> controllerEntries = getControllerEntries(connection);
121 ovsdbBridgeAugmentation.setControllerEntry(controllerEntries);
122 ovsdbBridgeAugmentation.setBridgeName(bridge.getBridgeName());
123 ovsdbBridgeAugmentation.setManagedBy(bridge.getManagedBy());
124 return ovsdbBridgeAugmentation.build();
127 private List<TerminationPoint> getTerminationPoints(OvsdbBridgeAugmentation bridge,
128 OvsdbTerminationPointAugmentation ovsdbTp) {
129 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
130 tpBuilder.setTpId(new TpId(new Uri(generateTpName(bridge))));
131 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, ovsdbTp);
133 List<TerminationPoint> tps = new ArrayList<TerminationPoint>();
134 tps.add(tpBuilder.build());
138 private String generateTpName(OvsdbBridgeAugmentation bridge) {
139 return OFOVERLAY_TUNNEL;
142 private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(OvsdbBridgeAugmentation bridge,
143 List<Options> options) {
144 OvsdbTerminationPointAugmentationBuilder ovsdbTpBuilder = new OvsdbTerminationPointAugmentationBuilder();
145 ovsdbTpBuilder.setName(generateTpName(bridge));
146 ovsdbTpBuilder.setOptions(options);
147 ovsdbTpBuilder.setInterfaceType(InterfaceTypeVxlan.class);
148 return ovsdbTpBuilder.build();
151 private void setOption(List<Options> options, String key, String value) {
152 OptionsBuilder option = new OptionsBuilder();
153 option.setOption(key);
154 option.setValue(value);
155 options.add(option.build());
158 private List<Options> getOptions() {
159 List<Options> options = new ArrayList<Options>();
160 setOption(options, REMOTE_IP_KEY, REMOTE_IP_VALUE);
161 setOption(options, VNID_KEY, VNID_VALUE);
165 private List<ControllerEntry> getControllerEntries(OvsdbNodeAugmentation connection) {
166 ControllerEntryBuilder controllerBuilder = new ControllerEntryBuilder();
167 List<ControllerEntry> result = new ArrayList<ControllerEntry>();
168 if (connectController == true && connection.getConnectionInfo().getLocalIp() != null) {
169 String localIp = String.valueOf(connection.getConnectionInfo().getLocalIp().getValue());
170 String targetString = "tcp:" + localIp + ":" + OF_PORT;
171 controllerBuilder.setTarget(new Uri(targetString));
172 result.add(controllerBuilder.build());
178 private Optional<OvsdbNodeAugmentation> getConnection(ReadWriteTransaction transaction,OvsdbBridgeAugmentation bridge) {
179 OvsdbNodeRef bareIId = bridge.getManagedBy();
180 if(bareIId != null) {
181 if(bareIId.getValue().getTargetType().equals(Node.class)) {
182 InstanceIdentifier<Node> iid = (InstanceIdentifier<Node>) bareIId.getValue();
183 CheckedFuture<Optional<Node>, ReadFailedException> connectionFuture =
184 transaction.read(LogicalDatastoreType.OPERATIONAL, iid);
186 Optional<Node> nodeOptional = connectionFuture.get();
187 if(nodeOptional.isPresent() && nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
188 return Optional.of(nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class));
190 LOG.warn("Could not find ovsdb-node for connection for {}",bridge);
192 } catch (InterruptedException | ExecutionException e) {
193 LOG.warn("Could not find ovsdb-node for connection for {}",bridge,e);
196 LOG.warn("Bridge 'managedBy' non-ovsdb-node. bridge {} getManagedBy() {}",bridge,bareIId.getValue());
199 LOG.warn("Bridge 'managedBy' is null. bridge {}",bridge);
201 return Optional.absent();