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