More southbound migration for netvirt
[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.security.InvalidParameterException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
21 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
23 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
24 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * Utility class to wrap mdsal transactions.
48  *
49  * @author Sam Hague (shague@redhat.com)
50  */
51 public class MdsalUtils {
52     private static final Logger LOG = LoggerFactory.getLogger(MdsalUtils.class);
53     private static DataBroker databroker = null;
54     private static final int OVSDB_UPDATE_TIMEOUT = 500;
55
56     /**
57      * Class constructor setting the data broker.
58      *
59      * @param dataBroker the {@link org.opendaylight.controller.md.sal.binding.api.DataBroker}
60      */
61     public MdsalUtils(DataBroker dataBroker) {
62         this.databroker = dataBroker;
63     }
64 /*
65     public static Node createNode(String nodeId) {
66             String[] pair = identifier.split("\\|");
67             if ((pair.length > 1) && (pair[0].equals("OVS"))) {
68                 id = pair[1];
69             }
70             return id;
71         }
72         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
73         SouthboundMapper.createNode(connectionInfo);
74     }
75 */
76     /**
77      * Executes delete as a blocking transaction.
78      *
79      * @param store {@link LogicalDatastoreType} which should be modified
80      * @param path {@link InstanceIdentifier} to read from
81      * @param <D> the data object type
82      * @return the result of the request
83      */
84     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean delete(
85             final LogicalDatastoreType store, final InstanceIdentifier<D> path)  {
86         boolean result = false;
87         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
88         transaction.delete(store, path);
89         CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
90         try {
91             future.checkedGet();
92             result = true;
93         } catch (TransactionCommitFailedException e) {
94             LOG.warn("Failed to delete {} ", path, e);
95         }
96         return result;
97     }
98
99     /**
100      * Executes merge as a blocking transaction.
101      *
102      * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
103      * @param path {@link InstanceIdentifier} for path to read
104      * @param <D> the data object type
105      * @return the result of the request
106      */
107     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean merge(
108             final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
109         boolean result = false;
110         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
111         transaction.merge(logicalDatastoreType, path, data, true);
112         CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
113         try {
114             future.checkedGet();
115             result = true;
116         } catch (TransactionCommitFailedException e) {
117             LOG.warn("Failed to merge {} ", path, e);
118         }
119         return result;
120     }
121
122     /**
123      * Executes put as a blocking transaction.
124      *
125      * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
126      * @param path {@link InstanceIdentifier} for path to read
127      * @param <D> the data object type
128      * @return the result of the request
129      */
130     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean put(
131             final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
132         boolean result = false;
133         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
134         transaction.put(logicalDatastoreType, path, data, true);
135         CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
136         try {
137             future.checkedGet();
138             result = true;
139         } catch (TransactionCommitFailedException e) {
140             LOG.warn("Failed to put {} ", path, e);
141         }
142         return result;
143     }
144
145     /**
146      * Executes read as a blocking transaction.
147      *
148      * @param store {@link LogicalDatastoreType} to read
149      * @param path {@link InstanceIdentifier} for path to read
150      * @param <D> the data object type
151      * @return the result as the data object requested
152      */
153     public static <D extends org.opendaylight.yangtools.yang.binding.DataObject> D read(
154             final LogicalDatastoreType store, final InstanceIdentifier<D> path)  {
155         D result = null;
156         final ReadOnlyTransaction transaction = databroker.newReadOnlyTransaction();
157         Optional<D> optionalDataObject;
158         CheckedFuture<Optional<D>, ReadFailedException> future = transaction.read(store, path);
159         try {
160             optionalDataObject = future.checkedGet();
161             if (optionalDataObject.isPresent()) {
162                 result = optionalDataObject.get();
163             } else {
164                 LOG.debug("{}: Failed to read {}",
165                         Thread.currentThread().getStackTrace()[1], path);
166             }
167         } catch (ReadFailedException e) {
168             LOG.warn("Failed to read {} ", path, e);
169         }
170         transaction.close();
171         return result;
172     }
173
174     public static String getOptionsValue(List<Options> options, String key) {
175         String value = null;
176         for (Options option : options) {
177             if (option.getKey().equals(key)) {
178                 value = option.getValue();
179             }
180         }
181         return value;
182     }
183
184     public static String getInterfaceExternalIdsValue(OvsdbTerminationPointAugmentation terminationPointAugmentation,
185                                                       String key) {
186         String value = null;
187         List<InterfaceExternalIds> pairs = terminationPointAugmentation.getInterfaceExternalIds();
188         for (InterfaceExternalIds pair : pairs) {
189             if (pair.getKey().equals(key)) {
190                 value = pair.getExternalIdValue();
191             }
192         }
193         return value;
194     }
195
196     public static ConnectionInfo getConnectionInfo(Node node) {
197         ConnectionInfo connectionInfo = null;
198         OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
199         if (ovsdbNodeAugmentation != null) {
200             connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
201         }
202         return connectionInfo;
203     }
204
205     public static OvsdbBridgeAugmentation getBridge(Node node, String name) {
206         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
207         ConnectionInfo connectionInfo = MdsalUtils.getConnectionInfo(node);
208         if (connectionInfo != null) {
209             InstanceIdentifier<Node> bridgeIid =
210                     SouthboundMapper.createInstanceIdentifier(connectionInfo,
211                             new OvsdbBridgeName(name));
212             Node bridgeNode = MdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
213             if (bridgeNode != null) {
214                 ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
215             }
216         }
217         return ovsdbBridgeAugmentation;
218     }
219
220     public static Uuid getBridgeUuid(Node node, String name) {
221         Uuid uuid = null;
222         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getBridge(node, name);
223         if (ovsdbBridgeAugmentation != null) {
224             uuid = ovsdbBridgeAugmentation.getBridgeUuid();
225         }
226         return uuid;
227     }
228
229     public static boolean addBridge(Node ovsdbNode, String bridgeName)
230             throws InterruptedException, InvalidParameterException {
231         boolean result = false;
232
233         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
234         if (connectionInfo != null) {
235             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
236             InstanceIdentifier<Node> bridgeIid =
237                     SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
238             NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
239             bridgeNodeBuilder.setNodeId(bridgeNodeId);
240             OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
241             ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
242             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
243             ovsdbBridgeAugmentationBuilder.setFailMode(
244                     SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
245             //setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
246             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
247
248             result = merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build());
249             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
250         } else {
251             throw new InvalidParameterException("Could not find ConnectionInfo");
252         }
253
254         return result;
255     }
256
257     private static void setManagedBy(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
258                               ConnectionInfo connectionInfo) {
259         InstanceIdentifier<Node> connectionNodePath = SouthboundMapper.createInstanceIdentifier(connectionInfo);
260         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
261     }
262
263     private static List<ProtocolEntry> createMdsalProtocols() {
264         List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
265         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
266                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
267         protocolList.add(new ProtocolEntryBuilder().
268                 setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
269         return protocolList;
270     }
271
272     public static OvsdbTerminationPointAugmentation getTerminationPointAugmentation(Node bridgeNode, String portName) {
273         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
274         if (ovsdbBridgeAugmentation != null) {
275             List<TerminationPoint> terminationPoints = bridgeNode.getTerminationPoint();
276             for(TerminationPoint terminationPoint : terminationPoints) {
277                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
278                         terminationPoint.getAugmentation( OvsdbTerminationPointAugmentation.class);
279                 if (ovsdbTerminationPointAugmentation != null
280                         && ovsdbTerminationPointAugmentation.getName().equals(portName)) {
281                     return ovsdbTerminationPointAugmentation;
282                 }
283             }
284         }
285         return null;
286     }
287 }