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