Fix migration warnings
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-it / src / test / java / org / opendaylight / ovsdb / hwvtepsouthbound / it / HwvtepSouthboundIT.java
1 /*
2  * Copyright © 2015, 2017 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.ovsdb.hwvtepsouthbound.it;
9
10 import static org.junit.Assert.assertTrue;
11 import static org.junit.Assert.fail;
12 import static org.ops4j.pax.exam.CoreOptions.composite;
13 import static org.ops4j.pax.exam.CoreOptions.maven;
14 import static org.ops4j.pax.exam.CoreOptions.vmOption;
15 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
17
18 import java.lang.annotation.Annotation;
19 import java.lang.reflect.Method;
20 import java.net.InetAddress;
21 import java.net.UnknownHostException;
22 import java.util.Collection;
23 import java.util.HashSet;
24 import java.util.Map;
25 import java.util.Properties;
26 import java.util.Set;
27 import javax.inject.Inject;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.junit.After;
30 import org.junit.Assert;
31 import org.junit.Before;
32 import org.junit.Ignore;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
36 import org.opendaylight.mdsal.binding.api.DataBroker;
37 import org.opendaylight.mdsal.binding.api.DataObjectModification;
38 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
39 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
40 import org.opendaylight.mdsal.binding.api.DataTreeModification;
41 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
42 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
43 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
44 import org.opendaylight.ovsdb.utils.hwvtepsouthbound.utils.HwvtepSouthboundUtils;
45 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfoBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIps;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIpsKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIpsKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.Uint16;
69 import org.ops4j.pax.exam.Configuration;
70 import org.ops4j.pax.exam.Option;
71 import org.ops4j.pax.exam.junit.PaxExam;
72 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
73 import org.ops4j.pax.exam.options.MavenUrlReference;
74 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
75 import org.ops4j.pax.exam.spi.reactors.PerClass;
76 import org.ops4j.pax.exam.util.Filter;
77 import org.osgi.framework.BundleContext;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80
81 @RunWith(PaxExam.class)
82 @ExamReactorStrategy(PerClass.class)
83 public class HwvtepSouthboundIT extends AbstractMdsalTestBase {
84     private static final Logger LOG = LoggerFactory.getLogger(HwvtepSouthboundIT.class);
85
86     //Constants
87
88     public static final String CUSTOM_PROPERTIES = "etc/custom.properties";
89     public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
90     public static final String DEFAULT_SERVER_IPADDRESS = "127.0.0.1";
91     public static final String SERVER_PORT = "ovsdbserver.port";
92     public static final String DEFAULT_SERVER_PORT = "6640";
93     public static final String CONNECTION_TYPE = "ovsdbserver.connection";
94     public static final String CONNECTION_TYPE_ACTIVE = "active";
95     public static final String CONNECTION_TYPE_PASSIVE = "passive";
96     public static final int CONNECTION_INIT_TIMEOUT = 10000;
97     public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
98     private static final String PS_NAME = "ps0";
99
100     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
101     private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
102
103     private static MdsalUtils mdsalUtils = null;
104     private static boolean setup = false;
105     private static int testMethodsRemaining;
106     private static String addressStr;
107     private static Uint16 portNumber;
108     private static String connectionType;
109     private static Node hwvtepNode;
110     @Inject @Filter(timeout = 60000)
111     private static DataBroker dataBroker = null;
112     @Inject
113     private BundleContext bundleContext;
114
115     private static final NotifyingDataChangeListener OPERATIONAL_LISTENER =
116             new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL);
117
118     private static final class NotifyingDataChangeListener implements DataTreeChangeListener<Node> {
119         private final LogicalDatastoreType type;
120         private final Set<InstanceIdentifier<Node>> createdNodes = new HashSet<>();
121         private final Set<InstanceIdentifier<Node>> removedNodes = new HashSet<>();
122         private final Set<InstanceIdentifier<Node>> updatedNodes = new HashSet<>();
123
124         private NotifyingDataChangeListener(LogicalDatastoreType type) {
125             this.type = type;
126         }
127
128         @Override
129         public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
130             for (DataTreeModification<Node> change : changes) {
131                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
132                 final DataObjectModification<Node> mod = change.getRootNode();
133                 switch (mod.getModificationType()) {
134                     case DELETE:
135                         removedNodes.add(key);
136                         break;
137                     case SUBTREE_MODIFIED:
138                         updatedNodes.add(key);
139                         break;
140                     case WRITE:
141                         if (mod.getDataBefore() == null) {
142                             LOG.trace("Data added: {}", mod.getDataAfter());
143                             createdNodes.add(key);
144                         } else {
145                             updatedNodes.add(key);
146                         }
147                         break;
148                     default:
149                         throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
150                 }
151             }
152         }
153
154         public boolean isCreated(InstanceIdentifier<Node> iid) {
155             return createdNodes.remove(iid);
156         }
157
158         public boolean isRemoved(InstanceIdentifier<Node> iid) {
159             return removedNodes.remove(iid);
160         }
161
162         public boolean isUpdated(InstanceIdentifier<Node> iid) {
163             return updatedNodes.remove(iid);
164         }
165     }
166
167     @Override
168     @Configuration
169     public Option[] config() {
170         Option[] options = super.config();
171         Option[] propertyOptions = getPropertiesOptions();
172         Option[] otherOptions = getOtherOptions();
173         Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
174         System.arraycopy(options, 0, combinedOptions, 0, options.length);
175         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
176         System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
177                 otherOptions.length);
178         return combinedOptions;
179     }
180
181     private Option[] getOtherOptions() {
182         return new Option[] {
183                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
184                 keepRuntimeFolder()
185         };
186     }
187
188     @Override
189     public String getKarafDistro() {
190         return maven()
191                 .groupId("org.opendaylight.ovsdb")
192                 .artifactId("hwvtepsouthbound-karaf")
193                 .versionAsInProject()
194                 .type("zip")
195                 .getURL();
196     }
197
198     @Override
199     public MavenUrlReference getFeatureRepo() {
200         return maven()
201                 .groupId("org.opendaylight.ovsdb")
202                 .artifactId("hwvtepsouthbound-features")
203                 .classifier("features")
204                 .type("xml")
205                 .versionAsInProject();
206     }
207
208     @Override
209     public String getFeatureName() {
210         return "odl-ovsdb-hwvtepsouthbound-test";
211     }
212
213     protected String usage() {
214         return "Integration Test needs a valid connection configuration as follows :\n"
215                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
216                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
217     }
218
219     @Override
220     public Option getLoggingOption() {
221         Option option = editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
222                 "log4j2.logger.hwvtepsouthbound-it.name",
223                 HwvtepSouthboundIT.class.getPackage().getName());
224         option = composite(option, editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
225                 "log4j2.logger.hwvtepsouthbound-it.level",
226                 LogLevel.INFO.name()));
227         option = composite(option, super.getLoggingOption());
228         return option;
229     }
230
231     private Option[] getPropertiesOptions() {
232         Properties props = new Properties(System.getProperties());
233         String ipAddressStr = props.getProperty(SERVER_IPADDRESS, DEFAULT_SERVER_IPADDRESS);
234         String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
235         String connectionTypeStr = props.getProperty(CONNECTION_TYPE, CONNECTION_TYPE_ACTIVE);
236
237         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
238                 connectionTypeStr, ipAddressStr, portStr);
239
240         return new Option[] {
241                 editConfigurationFilePut(CUSTOM_PROPERTIES, SERVER_IPADDRESS, ipAddressStr),
242                 editConfigurationFilePut(CUSTOM_PROPERTIES, SERVER_PORT, portStr),
243                 editConfigurationFilePut(CUSTOM_PROPERTIES, CONNECTION_TYPE, connectionTypeStr),
244         };
245     }
246
247     @Before
248     @Override
249     public void setup() throws Exception {
250         if (setup) {
251             LOG.info("Skipping setup, already initialized");
252             return;
253         }
254
255         super.setup();
256
257         addressStr = bundleContext.getProperty(SERVER_IPADDRESS);
258         String portStr = bundleContext.getProperty(SERVER_PORT);
259         try {
260             portNumber = Uint16.valueOf(portStr);
261         } catch (IllegalArgumentException e) {
262             fail("Invalid port number " + portStr + System.lineSeparator() + usage() + e);
263         }
264
265         connectionType = bundleContext.getProperty(CONNECTION_TYPE);
266
267         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
268                 connectionType, addressStr, portNumber);
269         if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
270             if (addressStr == null) {
271                 fail(usage());
272             }
273         }
274
275         mdsalUtils = new MdsalUtils(dataBroker);
276         assertTrue("Did not find " + HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue(), getHwvtepTopology());
277         final ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
278         final InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo);
279         final DataTreeIdentifier<Node> treeId = DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, iid);
280
281         dataBroker.registerDataTreeChangeListener(treeId, OPERATIONAL_LISTENER);
282
283         hwvtepNode = connectHwvtepNode(connectionInfo);
284         // Let's count the test methods (we need to use this instead of @AfterClass on teardown() since the latter is
285         // useless with pax-exam)
286         for (Method method : getClass().getMethods()) {
287             boolean testMethod = false;
288             boolean ignoreMethod = false;
289             for (Annotation annotation : method.getAnnotations()) {
290                 if (Test.class.equals(annotation.annotationType())) {
291                     testMethod = true;
292                 }
293                 if (Ignore.class.equals(annotation.annotationType())) {
294                     ignoreMethod = true;
295                 }
296             }
297             if (testMethod && !ignoreMethod) {
298                 testMethodsRemaining++;
299             }
300         }
301         LOG.info("{} test methods to run", testMethodsRemaining);
302
303         setup = true;
304     }
305
306     private Boolean getHwvtepTopology() {
307         LOG.info("getHwvtepTopology: looking for {}...", HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
308         Boolean found = false;
309         final TopologyId topologyId = HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID;
310         InstanceIdentifier<Topology> path =
311                 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
312         for (int i = 0; i < 60; i++) {
313             Boolean topology = mdsalUtils.exists(LogicalDatastoreType.OPERATIONAL, path);
314             if (topology) {
315                 LOG.info("getHwvtepTopology: found {}...", HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
316                 found = true;
317                 break;
318             } else {
319                 LOG.info("getHwvtepTopology: still looking ({})...", i);
320                 try {
321                     Thread.sleep(1000);
322                 } catch (InterruptedException e) {
323                     LOG.warn("Interrupted while waiting for {}",
324                             HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue(), e);
325                 }
326             }
327         }
328         return found;
329     }
330
331     private Node connectHwvtepNode(ConnectionInfo connectionInfo) throws InterruptedException {
332         final InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo);
333         Assert.assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
334                         iid, HwvtepSouthboundUtils.createNode(connectionInfo)));
335         waitForOperationalCreation(iid);
336         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
337         Assert.assertNotNull(node);
338         LOG.info("Connected to {}", HwvtepSouthboundUtils.connectionInfoToString(connectionInfo));
339         return node;
340     }
341
342     private static void disconnectHwvtepNode(final ConnectionInfo connectionInfo) throws InterruptedException {
343         final InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo);
344         Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
345         waitForOperationalDeletion(iid);
346         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
347         Assert.assertNull(node);
348         LOG.info("Disconnected from {}", HwvtepSouthboundUtils.connectionInfoToString(connectionInfo));
349     }
350
351     private void waitForOperationalCreation(InstanceIdentifier<Node> iid) throws InterruptedException {
352         synchronized (OPERATIONAL_LISTENER) {
353             long start = System.currentTimeMillis();
354             LOG.info("Waiting for OPERATIONAL DataChanged creation on {}", iid);
355             while (!OPERATIONAL_LISTENER.isCreated(
356                     iid) && System.currentTimeMillis() - start < OVSDB_ROUNDTRIP_TIMEOUT) {
357                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
358             }
359             LOG.info("Woke up, waited {} for creation of {}", System.currentTimeMillis() - start, iid);
360         }
361     }
362
363     private static void waitForOperationalDeletion(InstanceIdentifier<Node> iid) throws InterruptedException {
364         synchronized (OPERATIONAL_LISTENER) {
365             long start = System.currentTimeMillis();
366             LOG.info("Waiting for OPERATIONAL DataChanged deletion on {}", iid);
367             while (!OPERATIONAL_LISTENER.isRemoved(
368                     iid) && System.currentTimeMillis() - start < OVSDB_ROUNDTRIP_TIMEOUT) {
369                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
370             }
371             LOG.info("Woke up, waited {} for deletion of {}", System.currentTimeMillis() - start, iid);
372         }
373     }
374
375     private ConnectionInfo getConnectionInfo(String ipAddressStr, Uint16 portNum) {
376         InetAddress inetAddress = null;
377         try {
378             inetAddress = InetAddress.getByName(ipAddressStr);
379         } catch (UnknownHostException e) {
380             fail("Could not resolve " + ipAddressStr + ": " + e);
381         }
382
383         IpAddress address = HwvtepSouthboundMapper.createIpAddress(inetAddress);
384         PortNumber port = new PortNumber(portNum);
385
386         final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
387                 .setRemoteIp(address)
388                 .setRemotePort(port)
389                 .build();
390         LOG.info("connectionInfo: {}", connectionInfo);
391         return connectionInfo;
392     }
393
394     private static class TestPhysicalSwitch implements AutoCloseable {
395         private final ConnectionInfo connectionInfo;
396         private final String psName;
397
398
399         TestPhysicalSwitch(final ConnectionInfo connectionInfo, String psName) {
400             this(connectionInfo, psName, null, null, null, true, null, null, null);
401         }
402
403         TestPhysicalSwitch(final ConnectionInfo connectionInfo, final String name,
404                         @Nullable InstanceIdentifier<Node> psIid, @Nullable NodeId psNodeId,
405                         @Nullable final String description, final boolean setManagedBy,
406                         @Nullable final Map<ManagementIpsKey, ManagementIps> managementIps,
407                         @Nullable final Map<TunnelIpsKey, TunnelIps> tunnelIps,
408                         @Nullable final Map<TunnelsKey, Tunnels> tunnels) {
409             this.connectionInfo = connectionInfo;
410             this.psName = name;
411             NodeBuilder psNodeBuilder = new NodeBuilder();
412             if (psIid == null) {
413                 psIid = HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo, new HwvtepNodeName(psName));
414             }
415             if (psNodeId == null) {
416                 psNodeId = HwvtepSouthboundMapper.createManagedNodeId(psIid);
417             }
418             psNodeBuilder.setNodeId(psNodeId);
419             PhysicalSwitchAugmentationBuilder psAugBuilder = new PhysicalSwitchAugmentationBuilder();
420             psAugBuilder.setHwvtepNodeName(new HwvtepNodeName(psName));
421             if (description != null) {
422                 psAugBuilder.setHwvtepNodeDescription(description);
423             }
424             if (setManagedBy) {
425                 InstanceIdentifier<Node> nodePath = HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo);
426                 psAugBuilder.setManagedBy(new HwvtepGlobalRef(nodePath));
427             }
428             psAugBuilder.setManagementIps(managementIps);
429             psAugBuilder.setTunnelIps(tunnelIps);
430             psAugBuilder.setTunnels(tunnels);
431             psNodeBuilder.addAugmentation(psAugBuilder.build());
432             LOG.debug("Built with intent to store PhysicalSwitch data {}", psAugBuilder);
433             Assert.assertTrue(
434                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, psIid, psNodeBuilder.build()));
435             try {
436                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
437             } catch (InterruptedException e) {
438                 LOG.warn("Sleep interrupted while waiting for bridge creation (bridge {})", psName, e);
439             }
440         }
441
442         @Override
443         public void close() {
444             final InstanceIdentifier<Node> iid =
445                             HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo, new HwvtepNodeName(psName));
446             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
447             try {
448                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
449             } catch (InterruptedException e) {
450                 LOG.warn("Sleep interrupted while waiting for bridge deletion (bridge {})", psName, e);
451             }
452         }
453     }
454
455     @After
456     public void teardown() {
457         testMethodsRemaining--;
458         LOG.info("{} test methods remaining", testMethodsRemaining);
459     }
460
461     @Test
462     public void testhwvtepsouthboundFeatureLoad() {
463         Assert.assertTrue(true);
464     }
465
466     @Test
467     public void testNetworkTopology() throws InterruptedException {
468         NetworkTopology networkTopology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION,
469                 InstanceIdentifier.create(NetworkTopology.class));
470         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
471                 networkTopology);
472
473         networkTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
474                 InstanceIdentifier.create(NetworkTopology.class));
475         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
476                 networkTopology);
477     }
478
479     @Test
480     public void testHwvtepTopology() throws InterruptedException {
481         InstanceIdentifier<Topology> path = InstanceIdentifier
482                 .create(NetworkTopology.class)
483                 .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID));
484
485         Topology topology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
486         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
487                 topology);
488
489         topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
490
491         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
492                 topology);
493     }
494
495     @Test
496     public void testAddDeleteHwvtepNode() throws InterruptedException {
497         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
498         // At this point we're connected, disconnect and reconnect (the connection will be removed at the very end)
499         disconnectHwvtepNode(connectionInfo);
500         connectHwvtepNode(connectionInfo);
501     }
502
503     @Test
504     public void testAddDeletePhysicalSwitch() throws InterruptedException {
505         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
506
507         try (TestPhysicalSwitch testPSwitch = new TestPhysicalSwitch(connectionInfo, PS_NAME)) {
508             PhysicalSwitchAugmentation phySwitch = getPhysicalSwitch(connectionInfo);
509             Assert.assertNotNull(phySwitch);
510             LOG.info("PhysicalSwitch: {}", phySwitch);
511         }
512     }
513
514     private PhysicalSwitchAugmentation getPhysicalSwitch(ConnectionInfo connectionInfo) {
515         return getPhysicalSwitch(connectionInfo, PS_NAME);
516     }
517
518     private PhysicalSwitchAugmentation getPhysicalSwitch(ConnectionInfo connectionInfo, String psName) {
519         return getPhysicalSwitch(connectionInfo, psName, LogicalDatastoreType.OPERATIONAL);
520     }
521
522     private PhysicalSwitchAugmentation getPhysicalSwitch(ConnectionInfo connectionInfo, String psName,
523                     LogicalDatastoreType dataStore) {
524         Node psNode = getPhysicalSwitchNode(connectionInfo, psName, dataStore);
525         Assert.assertNotNull(psNode);
526         PhysicalSwitchAugmentation psAugmentation = psNode.augmentation(PhysicalSwitchAugmentation.class);
527         Assert.assertNotNull(psAugmentation);
528         return psAugmentation;
529     }
530
531     private Node getPhysicalSwitchNode(ConnectionInfo connectionInfo, String psName, LogicalDatastoreType dataStore) {
532         InstanceIdentifier<Node> psIid =
533                         HwvtepSouthboundUtils.createInstanceIdentifier(connectionInfo, new HwvtepNodeName(psName));
534         return mdsalUtils.read(dataStore, psIid);
535     }
536 }