Fix NPE in SouthboundUtils
[ovsdb.git] / utils / southbound-utils / src / main / java / org / opendaylight / ovsdb / utils / southbound / utils / SouthboundUtils.java
1 /*
2  * Copyright (c) 2015, 2018 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 static java.util.Objects.requireNonNull;
12
13 import com.google.common.collect.ImmutableBiMap;
14 import java.math.BigInteger;
15 import java.net.Inet4Address;
16 import java.net.Inet6Address;
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.security.InvalidParameterException;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28 import java.util.stream.Collectors;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
31 import org.opendaylight.ovsdb.utils.mdsal.utils.ControllerMdsalUtils;
32 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkr;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhost;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuser;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuserclient;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGeneve;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre64;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre64;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeLisp;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypePatch;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeSystem;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeTap;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlanGpe;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow11;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow12;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow14;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow15;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeSecure;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeStandalone;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
107 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
108 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
109 import org.opendaylight.yangtools.yang.binding.DataObject;
110 import org.opendaylight.yangtools.yang.binding.Identifier;
111 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
112 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
113 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
114 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
115 import org.slf4j.Logger;
116 import org.slf4j.LoggerFactory;
117
118 public class SouthboundUtils {
119     private abstract static class UtilsProvider {
120
121         abstract <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path);
122
123         abstract boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
124
125         abstract <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path,
126                 T createNode);
127
128         abstract <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
129     }
130
131     @Deprecated
132     private static final class ControllerUtilsProvider extends UtilsProvider {
133         private final ControllerMdsalUtils mdsalUtils;
134
135         ControllerUtilsProvider(final ControllerMdsalUtils mdsalUtils) {
136             this.mdsalUtils = requireNonNull(mdsalUtils);
137         }
138
139         @Override
140         <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
141             return mdsalUtils.read(
142                 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path);
143         }
144
145         @Override
146         <T extends DataObject> boolean put(LogicalDatastoreType store,
147                 InstanceIdentifier<T> path, T data) {
148             return mdsalUtils.put(
149                 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path, data);
150         }
151
152         @Override
153         boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
154             return mdsalUtils.delete(
155                 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path);
156         }
157
158         @Override
159         <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
160             return mdsalUtils.merge(
161                 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path, data);
162         }
163     }
164
165     private static final class MdsalUtilsProvider extends UtilsProvider {
166         private final MdsalUtils mdsalUtils;
167
168         MdsalUtilsProvider(final MdsalUtils mdsalUtils) {
169             this.mdsalUtils = requireNonNull(mdsalUtils);
170         }
171
172         @Override
173         <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
174             return mdsalUtils.read(store, path);
175         }
176
177         @Override
178         <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
179             return mdsalUtils.put(store, path, data);
180         }
181
182         @Override
183         boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
184             return mdsalUtils.delete(store, path);
185         }
186
187         @Override
188         <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
189             return mdsalUtils.merge(store, path, data);
190         }
191     }
192
193     private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
194     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
195     public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
196     public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
197     public static final String OPENFLOW_SECURE_PROTOCOL = "ssl";
198     public static final short OPENFLOW_PORT = 6653;
199     public static final String OVSDB_URI_PREFIX = "ovsdb";
200     public static final String BRIDGE_URI_PREFIX = "bridge";
201     private static final String DISABLE_IN_BAND = "disable-in-band";
202     private static final String PATCH_PORT_TYPE = "patch";
203     // External ID key used for mapping between an OVSDB port and an interface name
204     private static final String EXTERNAL_INTERFACE_ID_KEY = "iface-id";
205     private static final String CREATED_BY = "created_by";
206     private static final String ODL = "odl";
207     private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
208     private static final Pattern PATTERN = Pattern.compile(FORMAT);
209
210     private final UtilsProvider provider;
211
212     @Deprecated
213     public SouthboundUtils(ControllerMdsalUtils mdsalUtils) {
214         provider = new ControllerUtilsProvider(mdsalUtils);
215     }
216
217     public SouthboundUtils(MdsalUtils mdsalUtils) {
218         provider = new MdsalUtilsProvider(mdsalUtils);
219     }
220
221     public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
222             = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
223             .put("internal", InterfaceTypeInternal.class)
224             .put("vxlan", InterfaceTypeVxlan.class)
225             .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
226             .put("patch", InterfaceTypePatch.class)
227             .put("system", InterfaceTypeSystem.class)
228             .put("tap", InterfaceTypeTap.class)
229             .put("geneve", InterfaceTypeGeneve.class)
230             .put("gre", InterfaceTypeGre.class)
231             .put("ipsec_gre", InterfaceTypeIpsecGre.class)
232             .put("gre64", InterfaceTypeGre64.class)
233             .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
234             .put("lisp", InterfaceTypeLisp.class)
235             .put("dpdk", InterfaceTypeDpdk.class)
236             .put("dpdkr", InterfaceTypeDpdkr.class)
237             .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
238             .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
239             .put("dpdkvhostuserclient", InterfaceTypeDpdkvhostuserclient.class)
240             .build();
241
242     public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
243             = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
244             .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
245             .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
246             .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
247             .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
248             .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
249             .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
250             .build();
251
252     private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
253             = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
254             .put(OvsdbFailModeStandalone.class,"standalone")
255             .put(OvsdbFailModeSecure.class,"secure")
256             .build();
257
258     public static NodeId createNodeId(IpAddress ip, PortNumber port) {
259         String uriString = OVSDB_URI_PREFIX + "://" + ip.stringValue() + ":" + port.getValue();
260         Uri uri = new Uri(uriString);
261         return new NodeId(uri);
262     }
263
264     public static Node createNode(ConnectionInfo key) {
265         NodeBuilder nodeBuilder = new NodeBuilder();
266         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
267         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
268         return nodeBuilder.build();
269     }
270
271     public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
272         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
273         ovsdbNodeBuilder.setConnectionInfo(key);
274         return ovsdbNodeBuilder.build();
275     }
276
277     public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
278         return InstanceIdentifier
279                 .create(NetworkTopology.class)
280                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
281                 .child(Node.class,new NodeKey(nodeId));
282     }
283
284     public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
285         return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
286     }
287
288     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
289         return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
290     }
291
292     public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
293         InstanceIdentifier<Node> path = InstanceIdentifier
294                 .create(NetworkTopology.class)
295                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
296                 .child(Node.class,createNodeKey(ip,port));
297         LOG.debug("Created ovsdb path: {}",path);
298         return path;
299     }
300
301     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, OvsdbBridgeName bridgeName) {
302         return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
303     }
304
305     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
306         return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
307     }
308
309     public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName) {
310
311         InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
312                 .create(NetworkTopology.class)
313                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
314                 .child(Node.class,node.key())
315                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
316
317         LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
318         return terminationPointPath;
319     }
320
321     public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
322         return new NodeKey(createNodeId(ip, port));
323     }
324
325     public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
326         return new NodeId(ovsdbNodeId.getValue()
327                 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
328     }
329
330     public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
331         return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
332     }
333
334     public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
335         return new NodeId(createNodeId(ip,port).getValue()
336                 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
337     }
338
339     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
340         NodeKey nodeKey = iid.firstKeyOf(Node.class);
341         return nodeKey.getNodeId();
342     }
343
344     public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
345         return node.augmentation(OvsdbNodeAugmentation.class);
346     }
347
348     public static IpAddress createIpAddress(InetAddress address) {
349         IpAddress ip = null;
350         if (address instanceof Inet4Address) {
351             ip = createIpAddress((Inet4Address)address);
352         } else if (address instanceof Inet6Address) {
353             ip = createIpAddress((Inet6Address)address);
354         }
355         return ip;
356     }
357
358     public static IpAddress createIpAddress(Inet4Address address) {
359         return IetfInetUtil.INSTANCE.ipAddressFor(address);
360     }
361
362     public static IpAddress createIpAddress(Inet6Address address) {
363         Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
364         return new IpAddress(ipv6);
365     }
366
367     public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
368         ConnectionInfo connectionInfo = null;
369         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
370         if (ovsdbNodeAugmentation != null) {
371             connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
372         }
373         return connectionInfo;
374     }
375
376     public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
377         InetAddress inetAddress = null;
378         try {
379             inetAddress = InetAddress.getByName(addressStr);
380         } catch (UnknownHostException e) {
381             LOG.warn("Could not allocate InetAddress", e);
382         }
383
384         IpAddress address = createIpAddress(inetAddress);
385         PortNumber port = new PortNumber(Integer.parseInt(portStr));
386
387         LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
388                 .setRemoteIp(address)
389                 .setRemotePort(port)
390                 .build());
391         return new ConnectionInfoBuilder()
392                 .setRemoteIp(address)
393                 .setRemotePort(port)
394                 .build();
395     }
396
397     public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
398         return connectionInfo.getRemoteIp().stringValue() + ":" + connectionInfo.getRemotePort().getValue();
399     }
400
401     public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
402         return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
403     }
404
405     public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
406         boolean result = provider.put(LogicalDatastoreType.CONFIGURATION,
407                 createInstanceIdentifier(connectionInfo),
408                 createNode(connectionInfo));
409         if (timeout != 0) {
410             try {
411                 Thread.sleep(timeout);
412             } catch (InterruptedException e) {
413                 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
414                         connectionInfoToString(connectionInfo), e);
415             }
416         }
417         return result;
418     }
419
420     public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
421         return provider.read(LogicalDatastoreType.OPERATIONAL,
422                 createInstanceIdentifier(connectionInfo));
423     }
424
425     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
426         return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
427     }
428
429     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
430         boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
431                 createInstanceIdentifier(connectionInfo));
432         if (timeout != 0) {
433             try {
434                 Thread.sleep(timeout);
435             } catch (InterruptedException e) {
436                 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
437                         connectionInfoToString(connectionInfo), e);
438             }
439         }
440         return result;
441     }
442
443     public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
444         return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
445     }
446
447     public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
448         addOvsdbNode(connectionInfo, timeout);
449         Node node = getOvsdbNode(connectionInfo);
450         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
451         return node;
452     }
453
454     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
455         return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
456     }
457
458     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
459         deleteOvsdbNode(connectionInfo, timeout);
460         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
461         return true;
462     }
463
464     public List<ControllerEntry> createControllerEntry(String controllerTarget) {
465         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
466         controllerEntriesList.add(new ControllerEntryBuilder()
467                 .setTarget(new Uri(controllerTarget))
468                 .build());
469         return controllerEntriesList;
470     }
471
472     /**
473      * Extract the <code>store</code> type data store contents for the particular bridge identified by
474      * <code>bridgeName</code>.
475      *
476      * @param connectionInfo address for the node
477      * @param bridgeName name of the bridge
478      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
479      * @return <code>store</code> type data store contents
480      */
481     @Deprecated
482     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
483             org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType store) {
484         return getBridge(connectionInfo, bridgeName, store.toMdsal());
485     }
486
487     /**
488      * Extract the <code>store</code> type data store contents for the particular bridge identified by
489      * <code>bridgeName</code>.
490      *
491      * @param connectionInfo address for the node
492      * @param bridgeName name of the bridge
493      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
494      * @return <code>store</code> type data store contents
495      */
496     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
497                                               LogicalDatastoreType store) {
498         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
499         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
500         if (bridgeNode != null) {
501             ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
502         }
503         return ovsdbBridgeAugmentation;
504     }
505
506     /**
507      * Extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
508      * identified by <code>bridgeName</code>.
509      *
510      * @param connectionInfo address for the node
511      * @param bridgeName name of the bridge
512      * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
513      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
514      */
515     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
516         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
517     }
518
519     /**
520      * Extract the node contents from <code>store</code> type data store for the
521      * bridge identified by <code>bridgeName</code>.
522      *
523      * @param connectionInfo address for the node
524      * @param bridgeName name of the bridge
525      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
526      * @return <code>store</code> type data store contents
527      */
528     @Deprecated
529     public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName,
530             org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType store) {
531         return getBridgeNode(connectionInfo, bridgeName, store.toMdsal());
532     }
533
534     /**
535      * Extract the node contents from <code>store</code> type data store for the
536      * bridge identified by <code>bridgeName</code>.
537      *
538      * @param connectionInfo address for the node
539      * @param bridgeName name of the bridge
540      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
541      * @return <code>store</code> type data store contents
542      */
543     public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
544         InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
545         return provider.read(store, bridgeIid);
546     }
547
548     public Node getBridgeNode(Node node, String bridgeName) {
549         OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
550         if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
551             return node;
552         } else {
553             return readBridgeNode(node, bridgeName);
554         }
555     }
556
557     public Node readBridgeNode(Node node, String name) {
558         Node ovsdbNode = node;
559         if (extractNodeAugmentation(ovsdbNode) == null) {
560             ovsdbNode = readOvsdbNode(node);
561             if (ovsdbNode == null) {
562                 return null;
563             }
564         }
565         Node bridgeNode = null;
566         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
567         if (connectionInfo != null) {
568             InstanceIdentifier<Node> bridgeIid =
569                     createInstanceIdentifier(node.key(), name);
570             bridgeNode = provider.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
571         }
572         return bridgeNode;
573     }
574
575     public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
576         return node.augmentation(OvsdbNodeAugmentation.class);
577     }
578
579     public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
580         if (node == null) {
581             return null;
582         }
583         return node.augmentation(OvsdbBridgeAugmentation.class);
584     }
585
586     public Node readOvsdbNode(Node bridgeNode) {
587         Node ovsdbNode = null;
588         OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
589         if (bridgeAugmentation != null) {
590             InstanceIdentifier<Node> ovsdbNodeIid =
591                     (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
592             ovsdbNode = provider.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
593         } else {
594             LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
595         }
596         return ovsdbNode;
597     }
598
599     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
600         return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
601     }
602
603     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
604         boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
605                 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
606         if (timeout != 0) {
607             try {
608                 Thread.sleep(timeout);
609             } catch (InterruptedException e) {
610                 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
611             }
612         }
613         return result;
614     }
615
616     public List<ProtocolEntry> createMdsalProtocols() {
617         List<ProtocolEntry> protocolList = new ArrayList<>();
618         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
619                 OVSDB_PROTOCOL_MAP.inverse();
620         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
621         return protocolList;
622     }
623
624     /*
625      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
626      *
627      * @param connectionInfo
628      * @param bridgeIid if passed null, one is created
629      * @param bridgeName cannot be null
630      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
631      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
632      * @param failMode toggles whether default fail mode is set for the bridge
633      * @param setManagedBy toggles whether to setManagedBy for the bridge
634      * @param dpType if passed null, this parameter is ignored
635      * @param externalIds if passed null, this parameter is ignored
636      * @param otherConfig if passed null, this parameter is ignored
637      * @return success of bridge addition
638      * @throws InterruptedException
639      */
640     public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
641                              final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
642                              final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
643                              final Class<? extends DatapathTypeBase> dpType,
644                              final List<BridgeExternalIds> externalIds,
645                              final List<ControllerEntry> controllerEntries,
646                              final List<BridgeOtherConfigs> otherConfigs,
647                              final String dpid, long timeout) throws InterruptedException {
648
649         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
650         if (bridgeIid == null) {
651             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
652         }
653         if (bridgeNodeId == null) {
654             bridgeNodeId = createManagedNodeId(bridgeIid);
655         }
656         bridgeNodeBuilder.setNodeId(bridgeNodeId);
657         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
658         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
659         if (setProtocolEntries) {
660             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
661         }
662         if (failMode != null) {
663             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
664         }
665         if (setManagedBy) {
666             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
667         }
668         if (dpType != null) {
669             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
670         }
671         if (externalIds != null) {
672             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
673         }
674         if (controllerEntries != null) {
675             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
676         }
677         if (otherConfigs != null) {
678             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
679         }
680         if (dpid != null && !dpid.isEmpty()) {
681             DatapathId datapathId = new DatapathId(dpid);
682             ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
683         }
684         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
685         LOG.debug("Built with the intent to store bridge data {}",
686                 ovsdbBridgeAugmentationBuilder.toString());
687         boolean result = provider.merge(LogicalDatastoreType.CONFIGURATION,
688                 bridgeIid, bridgeNodeBuilder.build());
689         if (timeout != 0) {
690             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
691         }
692         return result;
693     }
694
695     public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
696             final Class<? extends DatapathTypeBase> dpType, String mac) {
697         return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, mac, null, null);
698     }
699
700     public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
701                              final Class<? extends DatapathTypeBase> dpType, String mac,
702                              Long maxBackoff, Long inactivityProbe) {
703         List<BridgeOtherConfigs> otherConfigs = new ArrayList<>();
704         if (mac != null) {
705             BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
706             macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
707             macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
708             otherConfigs.add(macOtherConfigBuilder.build());
709         }
710
711         return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, otherConfigs, null, null);
712     }
713
714     public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
715             final Class<? extends DatapathTypeBase> dpType,
716             List<BridgeOtherConfigs> otherConfigs,
717             Long maxBackoff, Long inactivityProbe) {
718         boolean result;
719
720         LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
721         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
722         if (connectionInfo != null) {
723             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
724             InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
725             NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
726             bridgeNodeBuilder.setNodeId(bridgeNodeId);
727             OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
728             ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(
729                     controllersStr, maxBackoff, inactivityProbe));
730             ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
731             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
732             ovsdbBridgeAugmentationBuilder.setFailMode(OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
733             // TODO: Currently netvirt relies on this function to set disabled-in-band=true. However,
734             // TODO (cont): a better design would be to have netvirt pass that in. That way this function
735             // TODO (cont): can take a null otherConfigs to erase other_configs.
736             if (otherConfigs == null) {
737                 otherConfigs = new ArrayList<>();
738             }
739             BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
740             bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
741             bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
742             otherConfigs.add(bridgeOtherConfigsBuilder.build());
743             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
744             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(setBridgeExternalIds());
745             setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.key());
746             if (dpType != null) {
747                 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
748             }
749             if (isOvsdbNodeDpdk(ovsdbNode)) {
750                 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
751             }
752             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
753
754             Node node = bridgeNodeBuilder.build();
755             result = provider.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
756             LOG.info("addBridge: result: {}", result);
757         } else {
758             throw new InvalidParameterException("Could not find ConnectionInfo");
759         }
760         return result;
761     }
762
763     /**
764      * Set the controllers of an existing bridge node.
765      *
766      * @param ovsdbNode where the bridge is
767      * @param bridgeName Name of the bridge
768      * @param controllers controller strings
769      * @return success if the write to md-sal was successful
770      */
771     public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers) {
772         return setBridgeController(ovsdbNode, bridgeName, controllers, null, null);
773     }
774
775     /**
776      * Set the controllers of an existing bridge node.
777      *
778      * @param ovsdbNode where the bridge is
779      * @param bridgeName Name of the bridge
780      * @param controllers controller strings
781      * @param maxBackoff Max backoff in milliseconds
782      * @param inactivityProbe inactivity probe in milliseconds
783      * @return success if the write to md-sal was successful
784      */
785     public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers,
786             Long maxBackoff, Long inactivityProbe) {
787         LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
788                 ovsdbNode, bridgeName, controllers);
789
790         InstanceIdentifier<Node> bridgeNodeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
791         Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
792         if (bridgeNode == null) {
793             LOG.info("setBridgeController could not find bridge in configuration {}", bridgeNodeIid);
794             return false;
795         }
796
797         OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
798
799         //Only add controller entries that do not already exist on this bridge
800         List<ControllerEntry> existingControllerEntries = bridgeAug.getControllerEntry();
801         List<ControllerEntry> newControllerEntries = new ArrayList<>();
802         if (existingControllerEntries != null) {
803             NEW_ENTRY_LOOP:
804             for (ControllerEntry newEntry : createControllerEntries(controllers, maxBackoff, inactivityProbe)) {
805                 for (ControllerEntry existingEntry : existingControllerEntries) {
806                     if (newEntry.getTarget().equals(existingEntry.getTarget())) {
807                         continue NEW_ENTRY_LOOP;
808                     }
809                 }
810                 newControllerEntries.add(newEntry);
811             }
812         } else {
813             newControllerEntries = createControllerEntries(controllers,maxBackoff, inactivityProbe);
814         }
815
816         if (newControllerEntries.isEmpty()) {
817             return true;
818         }
819
820         NodeBuilder nodeBuilder = new NodeBuilder(bridgeNode);
821         OvsdbBridgeAugmentationBuilder augBuilder = new OvsdbBridgeAugmentationBuilder(bridgeAug);
822
823         augBuilder.setControllerEntry(newControllerEntries);
824         nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, augBuilder.build());
825         InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
826         return provider.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, nodeBuilder.build());
827     }
828
829     private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
830                               final ConnectionInfo connectionInfo) {
831         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
832         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
833     }
834
835     public boolean addTerminationPoint(
836             Node bridgeNode, String portName, String type, Map<String, String> options,
837             Map<String, String> externalIds) {
838         return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
839     }
840
841     public boolean addTerminationPoint(
842             Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
843             Long ofPort) {
844         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
845
846         tpAugmentationBuilder.setName(portName);
847         tpAugmentationBuilder.setOfport(ofPort);
848         if (type != null) {
849             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
850         }
851
852         if (options != null && options.size() > 0) {
853             List<Options> optionsList = new ArrayList<>();
854             for (Map.Entry<String, String> entry : options.entrySet()) {
855                 OptionsBuilder optionsBuilder = new OptionsBuilder();
856                 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
857                 optionsBuilder.setOption(entry.getKey());
858                 optionsBuilder.setValue(entry.getValue());
859                 optionsList.add(optionsBuilder.build());
860             }
861             tpAugmentationBuilder.setOptions(optionsList);
862         }
863
864         if (externalIds != null && externalIds.size() > 0) {
865             List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
866             for (Map.Entry<String, String> entry : externalIds.entrySet()) {
867                 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
868                 interfaceExternalIdsBuilder.withKey(new InterfaceExternalIdsKey(entry.getKey()));
869                 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
870                 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
871                 externalIdsList.add(interfaceExternalIdsBuilder.build());
872             }
873             tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
874         }
875
876         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
877         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
878         tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
879         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
880         return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
881     }
882
883     public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
884         return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
885     }
886
887     public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
888                                        String type, Map<String, String> options) {
889         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
890
891         tpAugmentationBuilder.setName(portName);
892         if (type != null) {
893             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
894         }
895
896         List<Options> optionsList = new ArrayList<>();
897         for (Map.Entry<String, String> entry : options.entrySet()) {
898             OptionsBuilder optionsBuilder = new OptionsBuilder();
899             optionsBuilder.withKey(new OptionsKey(entry.getKey()));
900             optionsBuilder.setOption(entry.getKey());
901             optionsBuilder.setValue(entry.getValue());
902             optionsList.add(optionsBuilder.build());
903         }
904         tpAugmentationBuilder.setOptions(optionsList);
905
906         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
907         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
908         tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
909         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
910         return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
911     }
912
913     public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
914         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
915         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
916                 new OvsdbTerminationPointAugmentationBuilder();
917
918         tpAugmentationBuilder.setName(portName);
919         if (type != null) {
920             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
921         }
922         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
923         tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
924         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
925         return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
926     }
927
928     public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
929         Map<String, String> option = new HashMap<>();
930         option.put("peer", peerPortName);
931         return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
932     }
933
934     private String getControllerIPAddress() {
935         String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
936         if (addressString != null) {
937             try {
938                 if (InetAddress.getByName(addressString) != null) {
939                     return addressString;
940                 }
941             } catch (UnknownHostException e) {
942                 LOG.error("Host {} is invalid", addressString, e);
943             }
944         }
945
946         addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
947         if (addressString != null) {
948             try {
949                 if (InetAddress.getByName(addressString) != null) {
950                     return addressString;
951                 }
952             } catch (UnknownHostException e) {
953                 LOG.error("Host {} is invalid", addressString, e);
954             }
955         }
956
957         return null;
958     }
959
960     private short getControllerOFPort() {
961         short openFlowPort = OPENFLOW_PORT;
962         String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
963         if (portString != null) {
964             try {
965                 openFlowPort = Short.parseShort(portString);
966             } catch (NumberFormatException e) {
967                 LOG.warn("Invalid port:{}, use default({})", portString,
968                         openFlowPort, e);
969             }
970         }
971         return openFlowPort;
972     }
973
974     public List<String> getControllersFromOvsdbNode(Node node) {
975         List<String> controllersStr = new ArrayList<>();
976
977         String controllerIpStr = getControllerIPAddress();
978         if (controllerIpStr != null) {
979             // If codepath makes it here, the ip address to be used was explicitly provided.
980             // Being so, also fetch openflowPort provided via ConfigProperties.
981             controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
982                     + ":" + controllerIpStr + ":" + getControllerOFPort());
983         } else {
984             // Check if ovsdb node has manager entries
985             OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
986             if (ovsdbNodeAugmentation != null) {
987                 List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
988                 if (managerEntries != null && !managerEntries.isEmpty()) {
989                     for (ManagerEntry managerEntry : managerEntries) {
990                         if (managerEntry == null || managerEntry.getTarget() == null) {
991                             continue;
992                         }
993                         String managerStr = managerEntry.getTarget().getValue().toLowerCase(Locale.ROOT);
994                         int firstColonIdx = managerStr.indexOf(':');
995                         int lastColonIdx = managerStr.lastIndexOf(':');
996                         if (lastColonIdx <= firstColonIdx) {
997                             continue;
998                         }
999                         controllerIpStr = managerStr.substring(firstColonIdx + 1, lastColonIdx);
1000                         if (managerStr.startsWith("tcp")) {
1001                             controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL + ":" + controllerIpStr + ":"
1002                                 + getControllerOFPort());
1003                         } else if (managerStr.startsWith("ssl")) {
1004                             controllersStr.add(OPENFLOW_SECURE_PROTOCOL + ":" + controllerIpStr + ":"
1005                                 + getControllerOFPort());
1006                         } else if (managerStr.startsWith("ptcp")) {
1007                             ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
1008                             /* If we're connected to switch ptcp, only then use connection info
1009                                 to configure controller. Ptcp is configured as:
1010                                 Manager "ptcp:<port>:<ip>"
1011                                 ip is optional
1012                              */
1013                             String managerPortStr =  managerStr.split(":", 3)[1];
1014                             if (connectionInfo != null && connectionInfo.getLocalIp() != null
1015                                     && connectionInfo.getRemotePort() != null
1016                                     && managerPortStr.equals(connectionInfo.getRemotePort().toString())) {
1017                                 IpAddress controllerIp = connectionInfo.getLocalIp();
1018                                 if (controllerIp.getIpv6Address() != null) {
1019                                     controllerIpStr = "[" + connectionInfo.getLocalIp().stringValue() + "]";
1020                                 } else {
1021                                     controllerIpStr = connectionInfo.getLocalIp().stringValue();
1022                                 }
1023                                 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
1024                                     + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
1025                             } else {
1026                                 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1027                             }
1028                         } else if (managerStr.startsWith("pssl")) {
1029                             ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
1030                             if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
1031                                 controllerIpStr = connectionInfo.getLocalIp().stringValue();
1032                                 controllersStr.add(OPENFLOW_SECURE_PROTOCOL
1033                                     + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
1034                             } else {
1035                                 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1036                             }
1037                         } else {
1038                             LOG.trace("Skipping manager entry {} for node {}",
1039                                     managerEntry.getTarget(), node.getNodeId().getValue());
1040                         }
1041                     }
1042                 } else {
1043                     LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
1044                 }
1045             }
1046         }
1047
1048         if (controllersStr.isEmpty()) {
1049             LOG.warn("Failed to determine OpenFlow controller ip address");
1050         } else if (LOG.isDebugEnabled()) {
1051             LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
1052                     controllersStr.stream().collect(Collectors.joining(" ")));
1053         }
1054         return controllersStr;
1055     }
1056
1057     public long getDataPathId(Node node) {
1058         long dpid = 0L;
1059         String datapathId = getDatapathId(node);
1060         if (datapathId != null) {
1061             dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
1062         }
1063         return dpid;
1064     }
1065
1066     public String getDataPathIdStr(final Node node) {
1067         if (node != null) {
1068             long dpId = getDataPathId(node);
1069             if (dpId != 0) {
1070                 return String.valueOf(dpId);
1071             }
1072         }
1073
1074         return null;
1075     }
1076
1077     public String getDatapathId(Node node) {
1078         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
1079         return getDatapathId(ovsdbBridgeAugmentation);
1080     }
1081
1082     public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
1083         String datapathId = null;
1084         if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
1085             datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
1086         }
1087         return datapathId;
1088     }
1089
1090     public String extractBridgeName(Node node) {
1091         return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
1092     }
1093
1094     public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
1095         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1096         if (ovsdbNodeAugmentation != null) {
1097             List<ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
1098             if (managedNodes != null) {
1099                 for (ManagedNodeEntry managedNode : managedNodes) {
1100                     if (matchesBridgeName(managedNode, bridgeName)) {
1101                         return true;
1102                     }
1103                 }
1104             }
1105         }
1106         return false;
1107     }
1108
1109     // see OVSDB-470 for background
1110     private static boolean matchesBridgeName(ManagedNodeEntry managedNode, String bridgeName) {
1111         InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
1112         for (PathArgument bridgeIidPathArg : bridgeIid.getPathArguments()) {
1113             if (bridgeIidPathArg instanceof IdentifiableItem<?, ?>) {
1114                 IdentifiableItem<?, ?> identifiableItem = (IdentifiableItem<?, ?>) bridgeIidPathArg;
1115                 Identifier<?> key = identifiableItem.getKey();
1116                 if (key instanceof NodeKey) {
1117                     // Do not combine the above if with that below, we want to
1118                     // avoid the toString() call in the else if this is a NodeKey
1119                     NodeKey nodeKey = (NodeKey) key;
1120                     if (nodeKey.getNodeId().getValue().contains(bridgeName)) {
1121                         return true;
1122                     }
1123                 } else if (key.toString().contains(bridgeName)) {
1124                     return true;
1125                 }
1126             } else if (bridgeIidPathArg instanceof Item<?>) {
1127                 if (((Item<?>) bridgeIidPathArg).getType().getName().contains(bridgeName)) {
1128                     return true;
1129                 }
1130             } else {
1131                 throw new IllegalArgumentException("Unknown kind of PathArgument: " + bridgeIidPathArg);
1132             }
1133         }
1134         return false;
1135     }
1136
1137     public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
1138         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
1139         InstanceIdentifier<Node> bridgeIid =
1140                 createInstanceIdentifier(node.key(), bridge);
1141         Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
1142         if (bridgeNode != null) {
1143             ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
1144         }
1145         return ovsdbBridgeAugmentation;
1146     }
1147
1148     private static void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
1149                                        NodeKey ovsdbNodeKey) {
1150         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
1151         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
1152     }
1153
1154     public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
1155         boolean found = false;
1156         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1157         if (ovsdbNodeAugmentation != null) {
1158             List<InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
1159             if (ifTypes != null) {
1160                 for (InterfaceTypeEntry ifType : ifTypes) {
1161                     if (ifType.getInterfaceType().equals(InterfaceTypeDpdk.class)) {
1162                         found = true;
1163                         break;
1164                     }
1165                 }
1166             }
1167         }
1168         return found;
1169     }
1170
1171     private static List<ControllerEntry> createControllerEntries(List<String> controllersStr,
1172             Long maxBackoff, Long inactivityProbe) {
1173         List<ControllerEntry> controllerEntries = new ArrayList<>();
1174         if (controllersStr != null) {
1175             for (String controllerStr : controllersStr) {
1176                 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
1177                 controllerEntryBuilder.setTarget(new Uri(controllerStr));
1178                 if (maxBackoff != null) {
1179                     controllerEntryBuilder.setMaxBackoff(maxBackoff);
1180                 }
1181                 if (inactivityProbe != null) {
1182                     controllerEntryBuilder.setInactivityProbe(inactivityProbe);
1183                 }
1184                 controllerEntries.add(controllerEntryBuilder.build());
1185             }
1186         }
1187         return controllerEntries;
1188     }
1189
1190     public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
1191         if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
1192             List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
1193             for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
1194                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1195                     return ovsdbTerminationPointAugmentation;
1196                 }
1197             }
1198         }
1199         return null;
1200     }
1201
1202     public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
1203         List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
1204         if (node == null) {
1205             LOG.error("extractTerminationPointAugmentations: Node value is null");
1206             return Collections.emptyList();
1207         }
1208         List<TerminationPoint> terminationPoints = node.getTerminationPoint();
1209         if (terminationPoints != null && !terminationPoints.isEmpty()) {
1210             for (TerminationPoint tp : terminationPoints) {
1211                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1212                         tp.augmentation(OvsdbTerminationPointAugmentation.class);
1213                 if (ovsdbTerminationPointAugmentation != null) {
1214                     tpAugmentations.add(ovsdbTerminationPointAugmentation);
1215                 }
1216             }
1217         }
1218         return tpAugmentations;
1219     }
1220
1221     /**
1222      * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1223      * <code>portName</code>.
1224      */
1225     public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1226         OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1227         if (tpAugmentation == null) {
1228             List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1229             if (tpAugmentations != null) {
1230                 for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
1231                     if (ovsdbTpAugmentation.getName().equals(portName)) {
1232                         return ovsdbTpAugmentation;
1233                     }
1234                 }
1235             }
1236         }
1237         return tpAugmentation;
1238     }
1239
1240     /**
1241      * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1242      */
1243     public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1244         if (node == null) {
1245             LOG.error("readTerminationPointAugmentations: Node value is null");
1246             return Collections.emptyList();
1247         }
1248         Node operNode = provider.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1249                 .create(NetworkTopology.class)
1250                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1251                 .child(Node.class, new NodeKey(node.getNodeId())));
1252         if (operNode != null) {
1253             return extractTerminationPointAugmentations(operNode);
1254         }
1255         return new ArrayList<>();
1256     }
1257
1258     /**
1259      * Get all OVSDB nodes from topology.
1260      * @return a list of nodes or null if the topology could not found
1261      */
1262     public List<Node> getOvsdbNodes() {
1263         InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1264                 new TopologyKey(OVSDB_TOPOLOGY_ID));
1265         Topology topology = provider.read(LogicalDatastoreType.OPERATIONAL, inst);
1266         return topology != null ? topology.getNode() : null;
1267     }
1268
1269     /**
1270      * Get OpenvSwitch other-config by key.
1271      * @param node OVSDB node
1272      * @param key key to extract from other-config
1273      * @return the value for key or null if key not found
1274      */
1275     public String getOpenvswitchOtherConfig(Node node, String key) {
1276         OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
1277         if (ovsdbNode == null) {
1278             Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1279             if (nodeFromReadOvsdbNode != null) {
1280                 ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
1281             }
1282         }
1283
1284         if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
1285             for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
1286                 if (openvswitchOtherConfigs.getOtherConfigKey().equals(key)) {
1287                     return openvswitchOtherConfigs.getOtherConfigValue();
1288                 }
1289             }
1290         }
1291
1292         return null;
1293     }
1294
1295     public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
1296         if (bridgeNode.getTerminationPoint() != null) {
1297             for (TerminationPoint tp : bridgeNode.getTerminationPoint()) {
1298                 OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
1299                 String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
1300                 if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
1301                     LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
1302                             interfaceName, bridgeNode, tp);
1303                     return tp;
1304                 }
1305             }
1306         }
1307         return null;
1308     }
1309
1310     // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
1311     public Node getNodeByTerminationPointExternalId(final String interfaceName) {
1312         List<Node> nodes = getOvsdbNodes();
1313         if (nodes != null) {
1314             for (Node node : nodes) {
1315                 TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
1316                 if (tp != null) {
1317                     return node;
1318                 }
1319             }
1320         }
1321         return null;
1322     }
1323
1324     public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
1325         if (ovsdbTp != null) {
1326             List<InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
1327             if (ifaceExtIds != null) {
1328                 for (InterfaceExternalIds entry : ifaceExtIds) {
1329                     if (entry.getExternalIdKey().equals(EXTERNAL_INTERFACE_ID_KEY)) {
1330                         return entry.getExternalIdValue();
1331                     }
1332                 }
1333             }
1334         }
1335         return null;
1336     }
1337
1338     public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
1339         Node node = provider.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
1340         String dpId = node != null ? getDataPathIdStr(node) : null;
1341         if (dpId != null) {
1342             return dpId;
1343         }
1344         return null;
1345     }
1346
1347     public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
1348         if (dbVersion == null || minVersion == null) {
1349             LOG.error("Invalid DB version {} or minVersion {}", dbVersion, minVersion);
1350             return false;
1351         }
1352         final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
1353         final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
1354         LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
1355         if (!dbVersionMatcher.find()) {
1356             LOG.error("Invalid DB version format {}", dbVersion);
1357             return false;
1358         }
1359         if (!minVersionMatcher.find()) {
1360             LOG.error("Invalid Min DB version format {}", minVersion);
1361             return false;
1362         }
1363
1364         if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
1365             final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
1366             final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
1367             final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
1368             final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
1369             final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
1370             final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
1371             if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
1372                     && dbVersionMatch3 == minVersionMatch3) {
1373                 return true;
1374             }
1375
1376             if (dbVersionMatch1 > minVersionMatch1) {
1377                 return true;
1378             }
1379
1380             if (dbVersionMatch1 < minVersionMatch1) {
1381                 return false;
1382             }
1383
1384             // major version is equal
1385             if (dbVersionMatch2 > minVersionMatch2) {
1386                 return true;
1387             }
1388
1389             if (dbVersionMatch2 < minVersionMatch2) {
1390                 return false;
1391             }
1392
1393             if (dbVersionMatch3 > minVersionMatch3) {
1394                 return true;
1395             }
1396         }
1397         return false;
1398     }
1399
1400     private List<BridgeExternalIds> setBridgeExternalIds() {
1401         List<BridgeExternalIds> externalIdsList = new ArrayList<>();
1402         externalIdsList.add(new BridgeExternalIdsBuilder()
1403                 .setBridgeExternalIdKey(CREATED_BY)
1404                 .setBridgeExternalIdValue(ODL)
1405                 .build());
1406         return externalIdsList;
1407     }
1408 }