L3: Add eth to br-ex
[ovsdb.git] / utils / southbound-utils / src / main / java / org / opendaylight / ovsdb / utils / southbound / utils / SouthboundUtils.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
9 package org.opendaylight.ovsdb.utils.southbound.utils;
10
11 import com.google.common.collect.ImmutableBiMap;
12 import java.net.InetAddress;
13 import java.net.NetworkInterface;
14 import java.net.UnknownHostException;
15 import java.util.ArrayList;
16 import java.util.Enumeration;
17
18 import java.util.List;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
21 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
22 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
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.ConnectionInfoBuilder;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class SouthboundUtils {
55     private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
56     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
57     private static final String DEFAULT_OPENFLOW_PORT = "6653";
58     private static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
59     private MdsalUtils mdsalUtils;
60
61     public SouthboundUtils(MdsalUtils mdsalUtils) {
62         this.mdsalUtils = mdsalUtils;
63     }
64
65     public NodeId createNodeId(IpAddress ip, PortNumber port) {
66         String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
67                 + new String(ip.getValue()) + ":" + port.getValue();
68         Uri uri = new Uri(uriString);
69         return new NodeId(uri);
70     }
71
72     public Node createNode(ConnectionInfo key) {
73         NodeBuilder nodeBuilder = new NodeBuilder();
74         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
75         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
76         return nodeBuilder.build();
77     }
78
79     public OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
80         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
81         ovsdbNodeBuilder.setConnectionInfo(key);
82         return ovsdbNodeBuilder.build();
83     }
84
85     public InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
86         return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
87     }
88
89     public InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
90         InstanceIdentifier<Node> path = InstanceIdentifier
91                 .create(NetworkTopology.class)
92                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
93                 .child(Node.class,createNodeKey(ip,port));
94         LOG.debug("Created ovsdb path: {}",path);
95         return path;
96     }
97
98     public InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
99         return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
100     }
101
102     public NodeKey createNodeKey(IpAddress ip, PortNumber port) {
103         return new NodeKey(createNodeId(ip, port));
104     }
105
106     public NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
107         return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
108     }
109
110     public NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
111         return new NodeId(createNodeId(ip,port).getValue()
112                 + "/" + SouthboundConstants.BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
113     }
114
115     public ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
116         InetAddress inetAddress = null;
117         try {
118             inetAddress = InetAddress.getByName(addressStr);
119         } catch (UnknownHostException e) {
120             LOG.warn("Could not allocate InetAddress");
121         }
122
123         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
124         PortNumber port = new PortNumber(Integer.parseInt(portStr));
125
126         LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
127                 .setRemoteIp(address)
128                 .setRemotePort(port)
129                 .build());
130         return new ConnectionInfoBuilder()
131                 .setRemoteIp(address)
132                 .setRemotePort(port)
133                 .build();
134     }
135
136     public String connectionInfoToString(final ConnectionInfo connectionInfo) {
137         return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
138     }
139
140     public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
141         boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
142                 createInstanceIdentifier(connectionInfo),
143                 createNode(connectionInfo));
144         try {
145             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
146         } catch (InterruptedException e) {
147             e.printStackTrace();
148         }
149         return result;
150     }
151
152     public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
153         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
154                 createInstanceIdentifier(connectionInfo));
155         return node;
156     }
157
158     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
159         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
160                 createInstanceIdentifier(connectionInfo));
161         try {
162             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
163         } catch (InterruptedException e) {
164             e.printStackTrace();
165         }
166         return result;
167     }
168
169     public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
170         addOvsdbNode(connectionInfo);
171         Node node = getOvsdbNode(connectionInfo);
172         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
173         return node;
174     }
175
176     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
177         deleteOvsdbNode(connectionInfo);
178         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
179         return true;
180     }
181
182     public List<ControllerEntry> createControllerEntry(String controllerTarget) {
183         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
184         controllerEntriesList.add(new ControllerEntryBuilder()
185                 .setTarget(new Uri(controllerTarget))
186                 .build());
187         return controllerEntriesList;
188     }
189
190     /**
191      * Extract the <code>store</code> type data store contents for the particular bridge identified by
192      * <code>bridgeName</code>.
193      *
194      * @param connectionInfo address for the node
195      * @param bridgeName name of the bridge
196      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
197      * @return <code>store</code> type data store contents
198      */
199     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
200                                               LogicalDatastoreType store) {
201         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
202         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
203         if (bridgeNode != null) {
204             ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
205         }
206         return ovsdbBridgeAugmentation;
207     }
208
209     /**
210      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
211      * identified by <code>bridgeName</code>
212      *
213      * @param connectionInfo address for the node
214      * @param bridgeName name of the bridge
215      * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
216      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
217      */
218     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
219         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
220     }
221
222     /**
223      * Extract the node contents from <code>store</code> type data store for the
224      * bridge identified by <code>bridgeName</code>.
225      *
226      * @param connectionInfo address for the node
227      * @param bridgeName name of the bridge
228      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
229      * @return <code>store</code> type data store contents
230      */
231     public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
232         InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
233         return mdsalUtils.read(store, bridgeIid);
234     }
235
236     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
237
238         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
239                 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
240         try {
241             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
242         } catch (InterruptedException e) {
243             e.printStackTrace();
244         }
245         return result;
246     }
247
248     public List<ProtocolEntry> createMdsalProtocols() {
249         List<ProtocolEntry> protocolList = new ArrayList<>();
250         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
251                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
252         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
253         return protocolList;
254     }
255
256     /*
257      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
258      *
259      * @param connectionInfo
260      * @param bridgeIid if passed null, one is created
261      * @param bridgeName cannot be null
262      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
263      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
264      * @param failMode toggles whether default fail mode is set for the bridge
265      * @param setManagedBy toggles whether to setManagedBy for the bridge
266      * @param dpType if passed null, this parameter is ignored
267      * @param externalIds if passed null, this parameter is ignored
268      * @param otherConfig if passed null, this parameter is ignored
269      * @return success of bridge addition
270      * @throws InterruptedException
271      */
272     public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
273                               final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
274                               final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
275                               final Class<? extends DatapathTypeBase> dpType,
276                               final List<BridgeExternalIds> externalIds,
277                               final List<ControllerEntry> controllerEntries,
278                               final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
279
280         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
281         if (bridgeIid == null) {
282             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
283         }
284         if (bridgeNodeId == null) {
285             bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
286         }
287         bridgeNodeBuilder.setNodeId(bridgeNodeId);
288         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
289         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
290         if (setProtocolEntries) {
291             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
292         }
293         if (failMode != null) {
294             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
295         }
296         if (setManagedBy) {
297             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
298         }
299         if (dpType != null) {
300             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
301         }
302         if (externalIds != null) {
303             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
304         }
305         if (controllerEntries != null) {
306             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
307         }
308         if (otherConfigs != null) {
309             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
310         }
311         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
312         LOG.debug("Built with the intent to store bridge data {}",
313                 ovsdbBridgeAugmentationBuilder.toString());
314         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
315                 bridgeIid, bridgeNodeBuilder.build());
316         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
317         return result;
318     }
319
320     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
321                               final ConnectionInfo connectionInfo) {
322         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
323         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
324     }
325 }