2 * Copyright (c) 2015 CableLabs and others. All rights reserved.
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
8 package org.opendaylight.unimgr.impl;
10 import java.net.InetAddress;
11 import java.net.UnknownHostException;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
18 import java.util.UUID;
19 import java.util.Map.Entry;
20 import java.util.concurrent.ExecutionException;
22 import com.google.common.base.Optional;
23 import com.google.common.collect.ImmutableBiMap;
24 import com.google.common.collect.Lists;
25 import com.google.common.util.concurrent.CheckedFuture;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
29 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
30 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unimgr.rev150622.Unis;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unimgr.rev150622.unis.Uni;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
67 import org.opendaylight.yangtools.yang.binding.DataObject;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
72 public class UnimgrUtils {
74 private static final Logger LOG = LoggerFactory.getLogger(UnimgrUtils.class);
76 public static final Optional<Node> readNode(DataBroker dataBroker,
77 InstanceIdentifier<Node> nodeIid) {
78 ReadTransaction read = dataBroker.newReadOnlyTransaction();
79 CheckedFuture<Optional<Node>, ReadFailedException> nodeFuture = read
80 .read(LogicalDatastoreType.OPERATIONAL, nodeIid);
81 Optional<Node> nodeOptional;
83 nodeOptional = nodeFuture.get();
85 } catch (InterruptedException e) {
86 return Optional.absent();
87 } catch (ExecutionException e) {
88 return Optional.absent();
92 public static final Optional<Uni> readUniNode(DataBroker dataBroker,
93 InstanceIdentifier<Uni> nodeIid) {
94 ReadTransaction read = dataBroker.newReadOnlyTransaction();
95 CheckedFuture<Optional<Uni>, ReadFailedException> nodeFuture = read
96 .read(LogicalDatastoreType.OPERATIONAL, nodeIid);
97 Optional<Uni> nodeOptional;
99 nodeOptional = nodeFuture.get();
101 } catch (InterruptedException e) {
102 return Optional.absent();
103 } catch (ExecutionException e) {
104 return Optional.absent();
108 // This might not scale up.
109 public static final Unis readUnisFromStore(DataBroker dataBroker,
110 LogicalDatastoreType storetype) {
111 ReadOnlyTransaction read = dataBroker.newReadOnlyTransaction();
112 Optional<Unis> dataObject = null;
114 dataObject = read.read(storetype,
115 UnimgrMapper.getUnisIid()).get();
116 } catch (InterruptedException | ExecutionException e) {
117 LOG.error("Error retrieving the UNIs from the Configuration tree.");
119 if ((dataObject != null) && (dataObject.get() != null)) {
121 return dataObject.get();
128 public static void copyUniToDataStore(DataBroker dataBroker, Uni uni,
129 LogicalDatastoreType dataStoreType) {
130 WriteTransaction write = dataBroker.newWriteOnlyTransaction();
131 write.put(dataStoreType, UnimgrMapper.getUniIid(uni), uni);
135 public static OvsdbBridgeAugmentation createOvsdbBridgeAugmentation(Uni uni) {
136 NodeId ovsdbNodeId = uni.getOvsdbNodeId();
137 InstanceIdentifier<Node> ovsdbNodeIid;
138 if (ovsdbNodeId == null || ovsdbNodeId.getValue().isEmpty()) {
139 ovsdbNodeIid = UnimgrMapper.getOvsdbNodeIID(uni.getIpAddress());
141 ovsdbNodeIid = UnimgrMapper.getOvsdbNodeIID(ovsdbNodeId);
143 OvsdbNodeRef ovsdbNodeRef = new OvsdbNodeRef(ovsdbNodeIid);
144 UUID bridgeUuid = UUID.randomUUID();
145 OvsdbBridgeAugmentation ovsdbBridge = new OvsdbBridgeAugmentationBuilder()
146 .setBridgeName(new OvsdbBridgeName(UnimgrConstants.DEFAULT_BRIDGE_NAME))
147 .setManagedBy(ovsdbNodeRef)
148 .setBridgeUuid(new Uuid(bridgeUuid.toString()))
153 public static OvsdbNodeAugmentation createOvsdbNodeAugmentation(Uni uni) {
154 ConnectionInfo connectionInfos = new ConnectionInfoBuilder()
155 .setRemoteIp(uni.getIpAddress())
156 .setRemotePort(new PortNumber(UnimgrConstants.OVSDB_PORT))
158 OvsdbNodeAugmentation ovsdbNode = new OvsdbNodeAugmentationBuilder()
159 .setConnectionInfo(connectionInfos).build();
163 public static OvsdbTerminationPointAugmentation createOvsdbTerminationPointAugmentation(Uni uni) {
164 // we will use nodeId to set interface port id
165 VlanId vlanID = new VlanId(1);
166 OvsdbTerminationPointAugmentation terminationPoint = new OvsdbTerminationPointAugmentationBuilder()
167 .setName(UnimgrConstants.DEFAULT_INTERNAL_IFACE)
169 .setVlanMode(VlanMode.Access)
171 return terminationPoint;
174 public static IpAddress getLocalIp() {
177 ip = InetAddress.getLocalHost().getHostAddress();
178 Ipv4Address ipv4 = new Ipv4Address(ip);
179 IpAddress ipAddress = new IpAddress(ipv4);
181 } catch (UnknownHostException e) {
182 LOG.info("Unable to retrieve controller's ip address, using loopback.");
184 return new IpAddress(UnimgrConstants.LOCAL_IP);
187 public static ConnectionInfo getConnectionInfo(DataBroker dataBroker, NodeId ovsdbNodeId) {
188 InstanceIdentifier<Node> nodeIid = UnimgrMapper.getOvsdbNodeIID(ovsdbNodeId);
189 Optional<Node> node = readNode(dataBroker, nodeIid);
190 if (node.isPresent()) {
191 Node ovsdbNode = node.get();
192 OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
193 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
194 return connectionInfo;
200 public static List<ControllerEntry> createControllerEntries(String targetString) {
201 List<ControllerEntry> controllerEntries = new ArrayList<ControllerEntry>();
202 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
203 controllerEntryBuilder.setTarget(new Uri(targetString));
204 controllerEntries.add(controllerEntryBuilder.build());
205 return controllerEntries;
208 public static List<ProtocolEntry> createMdsalProtocols() {
209 List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
210 ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
211 UnimgrConstants.OVSDB_PROTOCOL_MAP.inverse();
212 protocolList.add(new ProtocolEntryBuilder().
213 setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
217 public static void createOvsdbNode(DataBroker dataBroker, NodeId ovsdbNodeId, Uni uni) {
218 InstanceIdentifier<Node> ovsdbNodeIid = UnimgrMapper
219 .getOvsdbNodeIID(uni.getIpAddress());
221 NodeKey ovsdbNodeKey = new NodeKey(ovsdbNodeId);
222 Node nodeData = new NodeBuilder().setNodeId(ovsdbNodeId)
223 .setKey(ovsdbNodeKey)
224 .addAugmentation(OvsdbNodeAugmentation.class, UnimgrUtils.createOvsdbNodeAugmentation(uni))
226 // Submit the node to the datastore
227 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
228 transaction.put(LogicalDatastoreType.CONFIGURATION, ovsdbNodeIid,
230 transaction.submit();
231 LOG.info("Created and submitted a new OVSDB node {}",
232 nodeData.getNodeId());
233 } catch (Exception e) {
234 LOG.error("Exception while creating OvsdbNodeAugmentation, "
235 + "Uni is null. Node Id: {}", ovsdbNodeId);
239 public static void createBridgeNode(DataBroker dataBroker, NodeId ovsdbNodeId, Uni uni, String bridgeName) {
240 LOG.info("Creating a bridge on node {}", ovsdbNodeId);
241 InstanceIdentifier<Node> ovsdbNodeIid = UnimgrMapper
242 .getOvsdbNodeIID(uni.getIpAddress());
243 ConnectionInfo connectionInfo = UnimgrUtils.getConnectionInfo(dataBroker, ovsdbNodeId);
244 if (connectionInfo != null) {
245 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
246 InstanceIdentifier<Node> bridgeIid = UnimgrMapper
247 .getOvsdbBridgeNodeIID(ovsdbNodeId, bridgeName);
248 NodeId bridgeNodeId = new NodeId(ovsdbNodeId
249 + UnimgrConstants.DEFAULT_BRIDGE_NODE_ID_SUFFIX + bridgeName);
250 bridgeNodeBuilder.setNodeId(bridgeNodeId);
251 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
252 // String target = VcpeUtils.getLocalIp().toString();
253 // ovsdbBridgeAugmentationBuilder.setControllerEntry(VcpeUtils.createControllerEntries(target));
254 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(
256 ovsdbBridgeAugmentationBuilder.setProtocolEntry(UnimgrUtils
257 .createMdsalProtocols());
258 OvsdbNodeRef ovsdbNodeRef = new OvsdbNodeRef(ovsdbNodeIid);
259 ovsdbBridgeAugmentationBuilder.setManagedBy(ovsdbNodeRef);
260 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
261 ovsdbBridgeAugmentationBuilder.build());
262 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
263 transaction.put(LogicalDatastoreType.CONFIGURATION, bridgeIid,
264 bridgeNodeBuilder.build());
265 transaction.submit();
267 LOG.error("The OVSDB node is not connected {}", ovsdbNodeId);
271 public static void createTerminationPointNode(DataBroker dataBroker, Uni uni,
272 Node bridgeNode, String bridgeName, String portName, String type) {
273 InstanceIdentifier<TerminationPoint> tpIid = UnimgrMapper
274 .createTerminationPointInstanceIdentifier(bridgeNode, portName);
275 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
276 new OvsdbTerminationPointAugmentationBuilder();
277 tpAugmentationBuilder.setName(portName);
279 tpAugmentationBuilder.setInterfaceType(UnimgrConstants.OVSDB_INTERFACE_TYPE_MAP.get(type));
281 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
282 tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
283 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
284 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
285 transaction.put(LogicalDatastoreType.CONFIGURATION,tpIid,tpBuilder.build());
286 transaction.submit();
289 public static void createGreTunnel(DataBroker dataBroker, Uni source, Uni destination,
290 Node bridgeNode, String bridgeName, String portName) {
291 InstanceIdentifier<TerminationPoint> tpIid = UnimgrMapper
292 .createTerminationPointInstanceIdentifier(bridgeNode, portName);
293 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
294 new OvsdbTerminationPointAugmentationBuilder();
295 tpAugmentationBuilder.setName(portName);
296 ArrayList<Options> options = Lists.newArrayList();
297 OptionsKey optionKey = new OptionsKey("remote_ip");
298 Options destinationIp = new OptionsBuilder()
299 .setOption(destination.getIpAddress().getIpv4Address().getValue())
301 .setValue(destination.getIpAddress().getIpv4Address().getValue())
303 options.add(destinationIp);
304 tpAugmentationBuilder.setOptions(options);
305 tpAugmentationBuilder.setInterfaceType(UnimgrConstants.OVSDB_INTERFACE_TYPE_MAP.get("gre"));
306 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
307 tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
308 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
309 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
310 transaction.put(LogicalDatastoreType.CONFIGURATION,tpIid,tpBuilder.build());
311 transaction.submit();
314 public static <T extends DataObject> Set<InstanceIdentifier<T>> extractRemoved(
315 AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
316 Set<InstanceIdentifier<T>> result = new HashSet<InstanceIdentifier<T>>();
317 if (changes != null && changes.getRemovedPaths() != null) {
318 for (InstanceIdentifier<?> iid : changes.getRemovedPaths()) {
319 if (iid.getTargetType().equals(klazz)) {
320 @SuppressWarnings("unchecked") // Actually checked above
321 InstanceIdentifier<T> iidn = (InstanceIdentifier<T>)iid;
329 public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extractOriginal(
330 AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
331 return extract(changes.getOriginalData(),klazz);
334 public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extract(
335 Map<InstanceIdentifier<?>, DataObject> changes, Class<T> klazz) {
336 Map<InstanceIdentifier<T>,T> result = new HashMap<InstanceIdentifier<T>,T>();
337 if (changes != null && changes.entrySet() != null) {
338 for (Entry<InstanceIdentifier<?>, DataObject> created : changes.entrySet()) {
339 if (klazz.isInstance(created.getValue())) {
340 @SuppressWarnings("unchecked")
341 T value = (T) created.getValue();
342 Class<?> type = created.getKey().getTargetType();
343 if (type.equals(klazz)) {
344 @SuppressWarnings("unchecked") // Actually checked above
345 InstanceIdentifier<T> iid = (InstanceIdentifier<T>) created.getKey();
346 result.put(iid, value);