Upgrade ietf-{inet,yang}-types to 2013-07-15
[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 java.math.BigInteger;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.NetworkInterface;
16 import java.net.UnknownHostException;
17 import java.util.ArrayList;
18 import java.util.Enumeration;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
24 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkr;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhost;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuser;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGeneve;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre64;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre64;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeLisp;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypePatch;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeSystem;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeTap;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlanGpe;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow11;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow12;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow14;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow15;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
87 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
88 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
92 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
93 import org.slf4j.Logger;
94 import org.slf4j.LoggerFactory;
95
96 import com.google.common.collect.ImmutableBiMap;
97
98 public class SouthboundUtils {
99     private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
100     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
101     public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
102     private final MdsalUtils mdsalUtils;
103     public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
104     public static short OPENFLOW_PORT = 6653;
105     public static final String OVSDB_URI_PREFIX = "ovsdb";
106     public static final String BRIDGE_URI_PREFIX = "bridge";
107
108     public SouthboundUtils(MdsalUtils mdsalUtils) {
109         this.mdsalUtils = mdsalUtils;
110     }
111
112     public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
113             = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
114             .put("internal", InterfaceTypeInternal.class)
115             .put("vxlan", InterfaceTypeVxlan.class)
116             .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
117             .put("patch", InterfaceTypePatch.class)
118             .put("system", InterfaceTypeSystem.class)
119             .put("tap", InterfaceTypeTap.class)
120             .put("geneve", InterfaceTypeGeneve.class)
121             .put("gre", InterfaceTypeGre.class)
122             .put("ipsec_gre", InterfaceTypeIpsecGre.class)
123             .put("gre64", InterfaceTypeGre64.class)
124             .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
125             .put("lisp", InterfaceTypeLisp.class)
126             .put("dpdk", InterfaceTypeDpdk.class)
127             .put("dpdkr", InterfaceTypeDpdkr.class)
128             .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
129             .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
130             .build();
131
132     public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
133             = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
134             .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
135             .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
136             .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
137             .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
138             .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
139             .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
140             .build();
141
142     public static NodeId createNodeId(IpAddress ip, PortNumber port) {
143         String uriString = OVSDB_URI_PREFIX + "://"
144                 + String.valueOf(ip.getValue()) + ":" + port.getValue();
145         Uri uri = new Uri(uriString);
146         return new NodeId(uri);
147     }
148
149     public static Node createNode(ConnectionInfo key) {
150         NodeBuilder nodeBuilder = new NodeBuilder();
151         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
152         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
153         return nodeBuilder.build();
154     }
155
156     public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
157         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
158         ovsdbNodeBuilder.setConnectionInfo(key);
159         return ovsdbNodeBuilder.build();
160     }
161
162     public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
163         return InstanceIdentifier
164                 .create(NetworkTopology.class)
165                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
166                 .child(Node.class,new NodeKey(nodeId));
167     }
168
169     public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
170         return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
171     }
172
173     public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
174         return new NodeId(ovsdbNodeId.getValue()
175                 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
176     }
177
178     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
179         return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
180     }
181
182     public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
183         InstanceIdentifier<Node> path = InstanceIdentifier
184                 .create(NetworkTopology.class)
185                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
186                 .child(Node.class,createNodeKey(ip,port));
187         LOG.debug("Created ovsdb path: {}",path);
188         return path;
189     }
190
191     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
192         return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
193     }
194
195     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
196         return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
197     }
198
199     public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName){
200
201         InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
202                 .create(NetworkTopology.class)
203                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
204                 .child(Node.class,node.getKey())
205                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
206
207         LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
208         return terminationPointPath;
209     }
210
211     public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
212         return new NodeKey(createNodeId(ip, port));
213     }
214
215     public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
216         return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
217     }
218
219     public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
220         return new NodeId(createNodeId(ip,port).getValue()
221                 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
222     }
223
224     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
225         NodeKey nodeKey = iid.firstKeyOf(Node.class);
226         return nodeKey.getNodeId();
227     }
228
229     public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
230         ConnectionInfo connectionInfo = null;
231         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
232         if (ovsdbNodeAugmentation != null) {
233             connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
234         }
235         return connectionInfo;
236     }
237
238     public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
239         return node.getAugmentation(OvsdbNodeAugmentation.class);
240     }
241
242     public static IpAddress createIpAddress(InetAddress address) {
243         IpAddress ip = null;
244         if (address instanceof Inet4Address) {
245             ip = createIpAddress((Inet4Address)address);
246         } else if (address instanceof Inet6Address) {
247             ip = createIpAddress((Inet6Address)address);
248         }
249         return ip;
250     }
251
252     public static IpAddress createIpAddress(Inet4Address address) {
253         return IetfInetUtil.INSTANCE.ipAddressFor(address);
254     }
255
256     public static IpAddress createIpAddress(Inet6Address address) {
257         Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
258         return new IpAddress(ipv6);
259     }
260
261     public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
262         InetAddress inetAddress = null;
263         try {
264             inetAddress = InetAddress.getByName(addressStr);
265         } catch (UnknownHostException e) {
266             LOG.warn("Could not allocate InetAddress", e);
267         }
268
269         IpAddress address = createIpAddress(inetAddress);
270         PortNumber port = new PortNumber(Integer.parseInt(portStr));
271
272         LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
273                 .setRemoteIp(address)
274                 .setRemotePort(port)
275                 .build());
276         return new ConnectionInfoBuilder()
277                 .setRemoteIp(address)
278                 .setRemotePort(port)
279                 .build();
280     }
281
282     public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
283         return String.valueOf(
284                 connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
285     }
286
287     public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
288         return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
289     }
290
291     public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
292         boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
293                 createInstanceIdentifier(connectionInfo),
294                 createNode(connectionInfo));
295         if (timeout != 0) {
296             try {
297                 Thread.sleep(timeout);
298             } catch (InterruptedException e) {
299                 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
300                         connectionInfoToString(connectionInfo), e);
301             }
302         }
303         return result;
304     }
305
306     public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
307         return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
308                 createInstanceIdentifier(connectionInfo));
309     }
310
311     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
312         return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
313     }
314
315     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
316         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
317                 createInstanceIdentifier(connectionInfo));
318         if (timeout != 0) {
319             try {
320                 Thread.sleep(timeout);
321             } catch (InterruptedException e) {
322                 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
323                         connectionInfoToString(connectionInfo), e);
324             }
325         }
326         return result;
327     }
328
329     public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
330         return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
331     }
332
333     public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
334         addOvsdbNode(connectionInfo, timeout);
335         Node node = getOvsdbNode(connectionInfo);
336         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
337         return node;
338     }
339
340     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
341         return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
342     }
343
344     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
345         deleteOvsdbNode(connectionInfo, timeout);
346         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
347         return true;
348     }
349
350     public List<ControllerEntry> createControllerEntry(String controllerTarget) {
351         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
352         controllerEntriesList.add(new ControllerEntryBuilder()
353                 .setTarget(new Uri(controllerTarget))
354                 .build());
355         return controllerEntriesList;
356     }
357
358     /**
359      * Extract the <code>store</code> type data store contents for the particular bridge identified by
360      * <code>bridgeName</code>.
361      *
362      * @param connectionInfo address for the node
363      * @param bridgeName name of the bridge
364      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
365      * @return <code>store</code> type data store contents
366      */
367     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
368                                               LogicalDatastoreType store) {
369         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
370         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
371         if (bridgeNode != null) {
372             ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
373         }
374         return ovsdbBridgeAugmentation;
375     }
376
377     /**
378      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
379      * identified by <code>bridgeName</code>
380      *
381      * @param connectionInfo address for the node
382      * @param bridgeName name of the bridge
383      * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
384      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
385      */
386     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
387         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
388     }
389
390     /**
391      * Extract the node contents from <code>store</code> type data store for the
392      * bridge identified by <code>bridgeName</code>.
393      *
394      * @param connectionInfo address for the node
395      * @param bridgeName name of the bridge
396      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
397      * @return <code>store</code> type data store contents
398      */
399     public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
400         InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
401         return mdsalUtils.read(store, bridgeIid);
402     }
403
404     public Node getBridgeNode(Node node, String bridgeName) {
405         OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
406         if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
407             return node;
408         } else {
409             return readBridgeNode(node, bridgeName);
410         }
411     }
412
413     public Node readBridgeNode(Node node, String name) {
414         Node ovsdbNode = node;
415         if (extractNodeAugmentation(ovsdbNode) == null) {
416             ovsdbNode = readOvsdbNode(node);
417             if (ovsdbNode == null) {
418                 return null;
419             }
420         }
421         Node bridgeNode = null;
422         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
423         if (connectionInfo != null) {
424             InstanceIdentifier<Node> bridgeIid =
425                     createInstanceIdentifier(node.getKey(), name);
426             bridgeNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
427         }
428         return bridgeNode;
429     }
430
431     public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
432         return node.getAugmentation(OvsdbNodeAugmentation.class);
433     }
434
435     public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
436         if (node == null) {
437             return null;
438         }
439         return node.getAugmentation(OvsdbBridgeAugmentation.class);
440     }
441
442     public Node readOvsdbNode(Node bridgeNode) {
443         Node ovsdbNode = null;
444         OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
445         if (bridgeAugmentation != null) {
446             InstanceIdentifier<Node> ovsdbNodeIid =
447                     (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
448             ovsdbNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
449         }else{
450             LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
451         }
452         return ovsdbNode;
453     }
454
455     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
456         return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
457     }
458
459     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
460         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
461                 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
462         if (timeout != 0) {
463             try {
464                 Thread.sleep(timeout);
465             } catch (InterruptedException e) {
466                 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
467             }
468         }
469         return result;
470     }
471
472     public List<ProtocolEntry> createMdsalProtocols() {
473         List<ProtocolEntry> protocolList = new ArrayList<>();
474         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
475                 OVSDB_PROTOCOL_MAP.inverse();
476         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
477         return protocolList;
478     }
479
480     public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
481                              final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
482                              final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
483                              final Class<? extends DatapathTypeBase> dpType,
484                              final List<BridgeExternalIds> externalIds,
485                              final List<ControllerEntry> controllerEntries,
486                              final List<BridgeOtherConfigs> otherConfigs,
487                              final String dpid) throws InterruptedException {
488         return addBridge(connectionInfo, bridgeIid, bridgeName, bridgeNodeId, setProtocolEntries, failMode,
489                 setManagedBy, dpType, externalIds, controllerEntries, otherConfigs, dpid);
490     }
491
492     /*
493      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
494      *
495      * @param connectionInfo
496      * @param bridgeIid if passed null, one is created
497      * @param bridgeName cannot be null
498      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
499      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
500      * @param failMode toggles whether default fail mode is set for the bridge
501      * @param setManagedBy toggles whether to setManagedBy for the bridge
502      * @param dpType if passed null, this parameter is ignored
503      * @param externalIds if passed null, this parameter is ignored
504      * @param otherConfig if passed null, this parameter is ignored
505      * @return success of bridge addition
506      * @throws InterruptedException
507      */
508     public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
509                              final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
510                              final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
511                              final Class<? extends DatapathTypeBase> dpType,
512                              final List<BridgeExternalIds> externalIds,
513                              final List<ControllerEntry> controllerEntries,
514                              final List<BridgeOtherConfigs> otherConfigs,
515                              final String dpid, long timeout) throws InterruptedException {
516
517         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
518         if (bridgeIid == null) {
519             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
520         }
521         if (bridgeNodeId == null) {
522             bridgeNodeId = createManagedNodeId(bridgeIid);
523         }
524         bridgeNodeBuilder.setNodeId(bridgeNodeId);
525         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
526         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
527         if (setProtocolEntries) {
528             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
529         }
530         if (failMode != null) {
531             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
532         }
533         if (setManagedBy) {
534             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
535         }
536         if (dpType != null) {
537             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
538         }
539         if (externalIds != null) {
540             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
541         }
542         if (controllerEntries != null) {
543             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
544         }
545         if (otherConfigs != null) {
546             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
547         }
548         if (dpid != null && !dpid.isEmpty()) {
549             DatapathId datapathId = new DatapathId(dpid);
550             ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
551         }
552         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
553         LOG.debug("Built with the intent to store bridge data {}",
554                 ovsdbBridgeAugmentationBuilder.toString());
555         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
556                 bridgeIid, bridgeNodeBuilder.build());
557         if (timeout != 0) {
558             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
559         }
560         return result;
561     }
562
563     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
564                               final ConnectionInfo connectionInfo) {
565         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
566         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
567     }
568
569     public boolean addTerminationPoint(
570             Node bridgeNode, String portName, String type, Map<String, String> options,
571             Map<String, String> externalIds) {
572         return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
573     }
574
575     public boolean addTerminationPoint(
576             Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
577             Long ofPort) {
578         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
579         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
580
581         tpAugmentationBuilder.setName(portName);
582         tpAugmentationBuilder.setOfport(ofPort);
583         if (type != null) {
584             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
585         }
586
587         if (options != null && options.size() > 0) {
588             List<Options> optionsList = new ArrayList<>();
589             for (Map.Entry<String, String> entry : options.entrySet()) {
590                 OptionsBuilder optionsBuilder = new OptionsBuilder();
591                 optionsBuilder.setKey(new OptionsKey(entry.getKey()));
592                 optionsBuilder.setOption(entry.getKey());
593                 optionsBuilder.setValue(entry.getValue());
594                 optionsList.add(optionsBuilder.build());
595             }
596             tpAugmentationBuilder.setOptions(optionsList);
597         }
598
599         if (externalIds != null && externalIds.size() > 0) {
600             List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
601             for (Map.Entry<String, String> entry : externalIds.entrySet()) {
602                 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
603                 interfaceExternalIdsBuilder.setKey(new InterfaceExternalIdsKey(entry.getKey()));
604                 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
605                 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
606                 externalIdsList.add(interfaceExternalIdsBuilder.build());
607             }
608             tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
609         }
610
611         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
612         tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
613         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
614         /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
615         return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
616     }
617
618     public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
619         return addTerminationPoint(bridgeNode, portName, type, null, null);
620     }
621
622     private String getControllerIPAddress() {
623         String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
624         if (addressString != null) {
625             try {
626                 if (InetAddress.getByName(addressString) != null) {
627                     return addressString;
628                 }
629             } catch (UnknownHostException e) {
630                 LOG.error("Host {} is invalid", addressString, e);
631             }
632         }
633
634         addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
635         if (addressString != null) {
636             try {
637                 if (InetAddress.getByName(addressString) != null) {
638                     return addressString;
639                 }
640             } catch (UnknownHostException e) {
641                 LOG.error("Host {} is invalid", addressString, e);
642             }
643         }
644
645         return null;
646     }
647
648     private short getControllerOFPort() {
649         short openFlowPort = OPENFLOW_PORT;
650         String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
651         if (portString != null) {
652             try {
653                 openFlowPort = Short.parseShort(portString);
654             } catch (NumberFormatException e) {
655                 LOG.warn("Invalid port:{}, use default({})", portString,
656                         openFlowPort, e);
657             }
658         }
659         return openFlowPort;
660     }
661
662     public List<String> getControllersFromOvsdbNode(Node node) {
663         List<String> controllersStr = new ArrayList<>();
664
665         String controllerIpStr = getControllerIPAddress();
666         if (controllerIpStr != null) {
667             // If codepath makes it here, the ip address to be used was explicitly provided.
668             // Being so, also fetch openflowPort provided via ConfigProperties.
669             controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
670                     + ":" + controllerIpStr + ":" + getControllerOFPort());
671         } else {
672             // Check if ovsdb node has manager entries
673             OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
674             if (ovsdbNodeAugmentation != null) {
675                 List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
676                 if (managerEntries != null && !managerEntries.isEmpty()) {
677                     for (ManagerEntry managerEntry : managerEntries) {
678                         if (managerEntry == null || managerEntry.getTarget() == null) {
679                             continue;
680                         }
681                         String[] tokens = managerEntry.getTarget().getValue().split(":");
682                         if (tokens.length == 3 && tokens[0].equalsIgnoreCase("tcp")) {
683                             controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
684                                     + ":" + tokens[1] + ":" + getControllerOFPort());
685                         } else if (tokens[0].equalsIgnoreCase("ptcp")) {
686                             ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
687                             if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
688                                 controllerIpStr = String.valueOf(connectionInfo.getLocalIp().getValue());
689                                 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
690                                         + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
691                             } else {
692                                 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
693                             }
694                         } else {
695                             LOG.trace("Skipping manager entry {} for node {}",
696                                     managerEntry.getTarget(), node.getNodeId().getValue());
697                         }
698                     }
699                 } else {
700                     LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
701                 }
702             }
703         }
704
705         if (controllersStr.isEmpty()) {
706             // Neither user provided ip nor ovsdb node has manager entries. Lets use local machine ip address.
707             LOG.debug("Use local machine ip address as a OpenFlow Controller ip address");
708             controllerIpStr = getLocalControllerHostIpAddress();
709             if (controllerIpStr != null) {
710                 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
711                         + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
712             }
713         }
714
715         if (controllersStr.isEmpty()) {
716             LOG.warn("Failed to determine OpenFlow controller ip address");
717         } else if (LOG.isDebugEnabled()) {
718             controllerIpStr = "";
719             for (String currControllerIpStr : controllersStr) {
720                 controllerIpStr += " " + currControllerIpStr;
721             }
722             LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(), controllerIpStr);
723         }
724
725         return controllersStr;
726     }
727
728     private String getLocalControllerHostIpAddress() {
729         String ipaddress = null;
730         try{
731             for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();){
732                 NetworkInterface iface = ifaces.nextElement();
733
734                 for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
735                     InetAddress inetAddr = inetAddrs.nextElement();
736                     if (!inetAddr.isLoopbackAddress() && inetAddr.isSiteLocalAddress()) {
737                         ipaddress = inetAddr.getHostAddress();
738                         break;
739                     }
740                 }
741             }
742         }catch (Exception e){
743             LOG.warn("Exception while fetching local host ip address ", e);
744         }
745         return ipaddress;
746     }
747
748     public long getDataPathId(Node node) {
749         long dpid = 0L;
750         String datapathId = getDatapathId(node);
751         if (datapathId != null) {
752             dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
753         }
754         return dpid;
755     }
756
757     public String getDatapathId(Node node) {
758         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
759         return getDatapathId(ovsdbBridgeAugmentation);
760     }
761
762     public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
763         String datapathId = null;
764         if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
765             datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
766         }
767         return datapathId;
768     }
769 }