Create the tunnel port in OVSDB, and connect.
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / ovsdb / OfOverlayOvsdbBridgeDataChangeListener.java
1 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.ovsdb;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Map.Entry;
6 import java.util.concurrent.ExecutionException;
7
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;
42
43 import com.google.common.base.Optional;
44 import com.google.common.util.concurrent.CheckedFuture;
45
46 public class OfOverlayOvsdbBridgeDataChangeListener implements DataChangeListener, AutoCloseable {
47
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);
58
59     public OfOverlayOvsdbBridgeDataChangeListener(DataBroker db) {
60         this.db = db;
61         InstanceIdentifier<Node> iid = InstanceIdentifier
62                 .create(NetworkTopology.class)
63                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
64                 .child(Node.class);
65         registration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, this, DataChangeScope.BASE);
66     }
67
68     @Override
69     public void close() throws Exception {
70         registration.close();
71
72     }
73
74     @Override
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);
83                 if(bridge!= null) {
84                     Optional<OvsdbNodeAugmentation> connectionOptional = getConnection(transaction, bridge);
85                     if(connectionOptional.isPresent()) {
86
87                         List<Options> options = getOptions();
88
89                         OvsdbTerminationPointAugmentation ovsdbTp = getOvsdbTerminationPointAugmentation(bridge,options);
90
91                         List<TerminationPoint> tps = getTerminationPoints(bridge,ovsdbTp);
92
93                         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getOvsdbBridgeAugmentation(bridge,connectionOptional.get());
94
95                         Node configNode = getNode(node, tps,ovsdbBridgeAugmentation);
96                         LOG.info("About to write nodeId {} node {}",nodeIid,configNode);
97                         transaction.merge(LogicalDatastoreType.CONFIGURATION, nodeIid, configNode);
98                     }
99                 }
100             }
101         }
102         transaction.submit();
103     }
104
105     private Node getNode(Node node, List<TerminationPoint> tps,
106             OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
107         NodeBuilder nodeBuilder = new NodeBuilder();
108         nodeBuilder.setKey(node.getKey());
109
110         nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
111                 ovsdbBridgeAugmentation);
112
113         nodeBuilder.setTerminationPoint(tps);
114         return nodeBuilder.build();
115     }
116
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();
125     }
126
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);
132
133         List<TerminationPoint> tps = new ArrayList<TerminationPoint>();
134         tps.add(tpBuilder.build());
135         return tps;
136     }
137
138     private String generateTpName(OvsdbBridgeAugmentation bridge) {
139         return OFOVERLAY_TUNNEL;
140     }
141
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();
149     }
150
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());
156     }
157
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);
162         return options;
163     }
164
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());
173         }
174
175         return result;
176     }
177
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);
185                 try {
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));
189                      } else {
190                          LOG.warn("Could not find ovsdb-node for connection for {}",bridge);
191                      }
192                 } catch (InterruptedException | ExecutionException e) {
193                     LOG.warn("Could not find ovsdb-node for connection for {}",bridge,e);
194                 }
195             } else {
196                 LOG.warn("Bridge 'managedBy' non-ovsdb-node.  bridge {} getManagedBy() {}",bridge,bareIId.getValue());
197             }
198         } else {
199             LOG.warn("Bridge 'managedBy' is null.  bridge {}",bridge);
200         }
201         return Optional.absent();
202     }
203 }
204