865ef9860039c942c10c7c4e9c628ed5909f66b5
[unimgr.git] / impl / src / main / java / org / opendaylight / unimgr / impl / UnimgrUtils.java
1 /*
2  * Copyright (c) 2015 CableLabs 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.unimgr.impl;
9
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;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19 import java.util.Map.Entry;
20 import java.util.concurrent.ExecutionException;
21
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;
26
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;
71
72 public class UnimgrUtils {
73
74     private static final Logger LOG = LoggerFactory.getLogger(UnimgrUtils.class);
75
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;
82         try {
83             nodeOptional = nodeFuture.get();
84             return nodeOptional;
85         } catch (InterruptedException e) {
86             return Optional.absent();
87         } catch (ExecutionException e) {
88             return Optional.absent();
89         }
90     }
91
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;
98         try {
99             nodeOptional = nodeFuture.get();
100             return nodeOptional;
101         } catch (InterruptedException e) {
102             return Optional.absent();
103         } catch (ExecutionException e) {
104             return Optional.absent();
105         }
106     }
107
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;
113         try {
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.");
118         }
119         if ((dataObject != null) && (dataObject.get() != null)) {
120             read.close();
121             return dataObject.get();
122         } else {
123             read.close();
124             return null;
125         }
126     }
127
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);
132         write.submit();
133     }
134
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());
140         } else {
141             ovsdbNodeIid = UnimgrMapper.getOvsdbNodeIID(ovsdbNodeId);
142         }
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()))
149                     .build();
150         return ovsdbBridge;
151     }
152
153     public static OvsdbNodeAugmentation createOvsdbNodeAugmentation(Uni uni) {
154         ConnectionInfo connectionInfos = new ConnectionInfoBuilder()
155                 .setRemoteIp(uni.getIpAddress())
156                 .setRemotePort(new PortNumber(UnimgrConstants.OVSDB_PORT))
157                 .build();
158         OvsdbNodeAugmentation ovsdbNode = new OvsdbNodeAugmentationBuilder()
159                 .setConnectionInfo(connectionInfos).build();
160         return ovsdbNode;
161     }
162
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)
168                                                                      .setVlanTag(vlanID)
169                                                                      .setVlanMode(VlanMode.Access)
170                                                                      .build();
171         return terminationPoint;
172     }
173
174     public static IpAddress getLocalIp() {
175         String ip;
176         try {
177             ip = InetAddress.getLocalHost().getHostAddress();
178             Ipv4Address ipv4 = new Ipv4Address(ip);
179             IpAddress ipAddress = new IpAddress(ipv4);
180             return ipAddress;
181         } catch (UnknownHostException e) {
182             LOG.info("Unable to retrieve controller's ip address, using loopback.");
183         }
184         return new IpAddress(UnimgrConstants.LOCAL_IP);
185     }
186
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;
195         } else {
196             return null;
197         }
198     }
199
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;
206     }
207
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());
214         return protocolList;
215     }
216
217     public static void createOvsdbNode(DataBroker dataBroker, NodeId ovsdbNodeId, Uni uni) {
218         InstanceIdentifier<Node> ovsdbNodeIid = UnimgrMapper
219                 .getOvsdbNodeIID(uni.getIpAddress());
220         try {
221             NodeKey ovsdbNodeKey = new NodeKey(ovsdbNodeId);
222             Node nodeData = new NodeBuilder().setNodeId(ovsdbNodeId)
223                     .setKey(ovsdbNodeKey)
224                     .addAugmentation(OvsdbNodeAugmentation.class, UnimgrUtils.createOvsdbNodeAugmentation(uni))
225                     .build();
226             // Submit the node to the datastore
227             WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
228             transaction.put(LogicalDatastoreType.CONFIGURATION, ovsdbNodeIid,
229                     nodeData);
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);
236         }
237     }
238
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(
255                     bridgeName));
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();
266         } else {
267             LOG.error("The OVSDB node is not connected {}", ovsdbNodeId);
268         }
269     }
270
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);
278         if (type != null) {
279             tpAugmentationBuilder.setInterfaceType(UnimgrConstants.OVSDB_INTERFACE_TYPE_MAP.get(type));
280         }
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();
287     }
288
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())
300                                         .setKey(optionKey)
301                                         .setValue(destination.getIpAddress().getIpv4Address().getValue())
302                                         .build();
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();
312     }
313
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;
322                     result.add(iidn);
323                 }
324             }
325         }
326         return result;
327     }
328
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);
332     }
333
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);
347                     }
348                 }
349             }
350         }
351         return result;
352     }
353 }