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