Remove OvsdbConfigurationService
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / impl / MdsalUtils.java
1 /*
2  * Copyright (c) 2015 Red Hat, Inc. 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.openstack.netvirt.impl;
9
10 import com.google.common.base.Optional;
11 import com.google.common.collect.ImmutableBiMap;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import java.math.BigInteger;
14 import java.security.InvalidParameterException;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Map;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
25 import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables;
26 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
27 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIds;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 /**
57  * Utility class to wrap mdsal transactions.
58  *
59  * @author Sam Hague (shague@redhat.com)
60  */
61 public class MdsalUtils {
62     private static final Logger LOG = LoggerFactory.getLogger(MdsalUtils.class);
63     private static DataBroker databroker = null;
64     private static final int OVSDB_UPDATE_TIMEOUT = 500;
65
66     /**
67      * Class constructor setting the data broker.
68      *
69      * @param dataBroker the {@link org.opendaylight.controller.md.sal.binding.api.DataBroker}
70      */
71     public MdsalUtils(DataBroker dataBroker) {
72         this.databroker = dataBroker;
73     }
74
75     /**
76      * Executes delete as a blocking transaction.
77      *
78      * @param store {@link LogicalDatastoreType} which should be modified
79      * @param path {@link InstanceIdentifier} to read from
80      * @param <D> the data object type
81      * @return the result of the request
82      */
83     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean delete(
84             final LogicalDatastoreType store, final InstanceIdentifier<D> path)  {
85         boolean result = false;
86         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
87         transaction.delete(store, path);
88         CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
89         try {
90             future.checkedGet();
91             result = true;
92         } catch (TransactionCommitFailedException e) {
93             LOG.warn("Failed to delete {} ", path, e);
94         }
95         return result;
96     }
97
98     /**
99      * Executes merge as a blocking transaction.
100      *
101      * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
102      * @param path {@link InstanceIdentifier} for path to read
103      * @param <D> the data object type
104      * @return the result of the request
105      */
106     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean merge(
107             final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
108         boolean result = false;
109         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
110         transaction.merge(logicalDatastoreType, path, data, true);
111         CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
112         try {
113             future.checkedGet();
114             result = true;
115         } catch (TransactionCommitFailedException e) {
116             LOG.warn("Failed to merge {} ", path, e);
117         }
118         return result;
119     }
120
121     /**
122      * Executes put as a blocking transaction.
123      *
124      * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
125      * @param path {@link InstanceIdentifier} for path to read
126      * @param <D> the data object type
127      * @return the result of the request
128      */
129     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean put(
130             final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
131         boolean result = false;
132         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
133         transaction.put(logicalDatastoreType, path, data, true);
134         CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
135         try {
136             future.checkedGet();
137             result = true;
138         } catch (TransactionCommitFailedException e) {
139             LOG.warn("Failed to put {} ", path, e);
140         }
141         return result;
142     }
143
144     /**
145      * Executes read as a blocking transaction.
146      *
147      * @param store {@link LogicalDatastoreType} to read
148      * @param path {@link InstanceIdentifier} for path to read
149      * @param <D> the data object type
150      * @return the result as the data object requested
151      */
152     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> D read(
153             final LogicalDatastoreType store, final InstanceIdentifier<D> path)  {
154         D result = null;
155         final ReadOnlyTransaction transaction = databroker.newReadOnlyTransaction();
156         Optional<D> optionalDataObject;
157         CheckedFuture<Optional<D>, ReadFailedException> future = transaction.read(store, path);
158         try {
159             optionalDataObject = future.checkedGet();
160             if (optionalDataObject.isPresent()) {
161                 result = optionalDataObject.get();
162             } else {
163                 LOG.debug("{}: Failed to read {}",
164                         Thread.currentThread().getStackTrace()[1], path);
165             }
166         } catch (ReadFailedException e) {
167             LOG.warn("Failed to read {} ", path, e);
168         }
169         transaction.close();
170         return result;
171     }
172
173     public static String getOptionsValue(List<Options> options, String key) {
174         String value = null;
175         for (Options option : options) {
176             if (option.getKey().equals(key)) {
177                 value = option.getValue();
178             }
179         }
180         return value;
181     }
182
183     public static String getOpenVSwitchExternalIdsValue(OvsdbNodeAugmentation ovsdbNodeAugmentation, String key) {
184         String value = null;
185         List<OpenvswitchExternalIds> pairs = ovsdbNodeAugmentation.getOpenvswitchExternalIds();
186         for (OpenvswitchExternalIds pair : pairs) {
187             if (pair.getKey().equals(key)) {
188                 value = pair.getExternalIdValue();
189             }
190         }
191         return value;
192     }
193
194     public static String getInterfaceExternalIdsValue(OvsdbTerminationPointAugmentation terminationPointAugmentation,
195                                                       String key) {
196         String value = null;
197         List<InterfaceExternalIds> pairs = terminationPointAugmentation.getInterfaceExternalIds();
198         for (InterfaceExternalIds pair : pairs) {
199             if (pair.getKey().equals(key)) {
200                 value = pair.getExternalIdValue();
201             }
202         }
203         return value;
204     }
205
206     public static ConnectionInfo getConnectionInfo(Node node) {
207         ConnectionInfo connectionInfo = null;
208         OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
209         if (ovsdbNodeAugmentation != null) {
210             connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
211         }
212         return connectionInfo;
213     }
214
215     public static OvsdbBridgeAugmentation readBridge(Node node, String name) {
216         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
217         ConnectionInfo connectionInfo = getConnectionInfo(node);
218         if (connectionInfo != null) {
219             InstanceIdentifier<Node> bridgeIid =
220                     SouthboundMapper.createInstanceIdentifier(connectionInfo,
221                             new OvsdbBridgeName(name));
222             Node bridgeNode = read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
223             if (bridgeNode != null) {
224                 ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
225             }
226         }
227         return ovsdbBridgeAugmentation;
228     }
229
230     public static Uuid getBridgeUuid(Node node, String name) {
231         Uuid uuid = null;
232         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = readBridge(node, name);
233         if (ovsdbBridgeAugmentation != null) {
234             uuid = ovsdbBridgeAugmentation.getBridgeUuid();
235         }
236         return uuid;
237     }
238
239     public static boolean addBridge(Node ovsdbNode, String bridgeName, String target)
240             throws InterruptedException, InvalidParameterException {
241         boolean result = false;
242
243         LOG.info("addBridge: node: {}, bridgeName: {}, target: {}", ovsdbNode, bridgeName, target);
244         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
245         if (connectionInfo != null) {
246             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
247             InstanceIdentifier<Node> bridgeIid =
248                     SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
249             NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
250             bridgeNodeBuilder.setNodeId(bridgeNodeId);
251             OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
252             //ovsdbBridgeAugmentationBuilder.setControllerEntry(setControllerEntries(target));
253             ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
254             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
255             ovsdbBridgeAugmentationBuilder.setFailMode(
256                     SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
257             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
258             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
259
260             result = merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build());
261             LOG.info("addBridge: result: {}", result);
262             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
263             addController(ovsdbNode, bridgeName, target);
264             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
265         } else {
266             throw new InvalidParameterException("Could not find ConnectionInfo");
267         }
268
269         return result;
270     }
271
272     private static void setManagedBy(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
273                                      ConnectionInfo connectionInfo) {
274         InstanceIdentifier<Node> connectionNodePath = SouthboundMapper.createInstanceIdentifier(connectionInfo);
275         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
276     }
277
278     private static void addController(Node ovsdbNode, String bridgeName, String targetString) {
279         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
280         if (connectionInfo != null) {
281             for (ControllerEntry controllerEntry: setControllerEntries(targetString)) {
282                 InstanceIdentifier<ControllerEntry> iid =
283                         SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName))
284                                 .augmentation(OvsdbBridgeAugmentation.class)
285                                 .child(ControllerEntry.class, controllerEntry.getKey());
286
287                 boolean result = put(LogicalDatastoreType.CONFIGURATION, iid, controllerEntry);
288                 LOG.info("addController: result: {}", result);
289             }
290         }
291     }
292
293     private static List<ControllerEntry> setControllerEntries(String targetString) {
294         List<ControllerEntry> controllerEntries = new ArrayList<ControllerEntry>();
295         ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
296         controllerEntryBuilder.setTarget(new Uri(targetString));
297         controllerEntries.add(controllerEntryBuilder.build());
298         return controllerEntries;
299     }
300
301     private static List<ProtocolEntry> createMdsalProtocols() {
302         List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
303         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
304                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
305         protocolList.add(new ProtocolEntryBuilder().
306                 setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
307         return protocolList;
308     }
309
310     public static OvsdbTerminationPointAugmentation getTerminationPointAugmentation(Node bridgeNode, String portName) {
311         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
312         if (ovsdbBridgeAugmentation != null) {
313             List<TerminationPoint> terminationPoints = bridgeNode.getTerminationPoint();
314             for(TerminationPoint terminationPoint : terminationPoints) {
315                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
316                         terminationPoint.getAugmentation( OvsdbTerminationPointAugmentation.class);
317                 if (ovsdbTerminationPointAugmentation != null
318                         && ovsdbTerminationPointAugmentation.getName().equals(portName)) {
319                     return ovsdbTerminationPointAugmentation;
320                 }
321             }
322         }
323         return null;
324     }
325
326     public static List<TerminationPoint> getTerminationPoints(Node node) {
327         List<TerminationPoint> terminationPoints = null;
328         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
329         if (ovsdbBridgeAugmentation != null) {
330             terminationPoints = node.getTerminationPoint();
331         }
332         return terminationPoints;
333     }
334
335     private static Topology getOvsdbTopology() {
336         InstanceIdentifier<Topology> path = InstanceIdentifier
337                 .create(NetworkTopology.class)
338                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
339
340         Topology topology = read(LogicalDatastoreType.OPERATIONAL, path);
341         return topology;
342     }
343
344     public static String getDatapathId(Node node) {
345         String datapathId = null;
346         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
347         if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
348             datapathId = node.getAugmentation(OvsdbBridgeAugmentation.class).getDatapathId().getValue();
349         }
350         return datapathId;
351     }
352
353     public static long getDataPathId(Node node) {
354         long dpid = 0L;
355         String datapathId = getDatapathId(node);
356         if (datapathId != null) {
357             dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
358         }
359         return dpid;
360     }
361
362     public static String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
363         String datapathId = null;
364         if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
365             datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
366         }
367         return datapathId;
368     }
369
370     public static OvsdbBridgeAugmentation getBridge(Node node, String name) {
371         OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
372         if (bridge != null) {
373             if (!bridge.getBridgeName().equals(name)) {
374                 bridge = null;
375             }
376         }
377         return bridge;
378     }
379
380     public static String getBridgeName(Node node) {
381         return (node.getAugmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue());
382     }
383
384     public static OvsdbBridgeAugmentation readBridge(Node node) {
385         return (node.getAugmentation(OvsdbBridgeAugmentation.class));
386     }
387
388     public static List<Node> getBridges(Node node) {
389         return null;
390     }
391
392     public static List<OvsdbTerminationPointAugmentation> getPorts(Node node) {
393         return null;
394     }
395
396     public static Boolean deletePort(Node node, String portName) {
397         return false;
398     }
399
400     public static Boolean addPort(Node node, String bridgeName, String portName) {
401         return false;
402     }
403
404     public static Boolean addTunnelPort(Node node, String bridgeName, String portName, String type,
405                                         Map<String, String> options) {
406         return false;
407     }
408
409     public static Boolean addPatchPort(Node node, String bridgeName, String portName, String peerPortName) {
410         return false;
411     }
412
413     public static OvsdbTerminationPointAugmentation getPort(Node node, String portName) {
414         return null;
415     }
416
417     public static String getExternalId(Node node, OvsdbTables table, String key) {
418         return null;
419     }
420
421     public static String getOtherConfig(Node node, OvsdbTables table, String key) {
422         return null;
423     }
424
425     public static boolean addVlanToTp(long vlan) {
426         return false;
427     }
428
429     public static boolean isTunnel(OvsdbTerminationPointAugmentation port) {
430         return SouthboundMapper.createOvsdbInterfaceType(
431                 port.getInterfaceType()).equals(NetworkHandler.NETWORK_TYPE_VXLAN)
432                 || SouthboundMapper.createOvsdbInterfaceType(
433                 port.getInterfaceType()).equals(NetworkHandler.NETWORK_TYPE_GRE);
434     }
435
436     public static String getNodeUUID(Node node) {
437         String nodeUUID = null;
438         OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
439         if (ovsdbNodeAugmentation != null) {
440             // TODO replace with proper uuid and not the system-id
441             nodeUUID = getOpenVSwitchExternalIdsValue(ovsdbNodeAugmentation, "system-id");
442         }
443         return nodeUUID;
444     }
445 }