Merge "Added code for PhysicalPort, LogicalSwitch"
[ovsdb.git] / southbound / southbound-it / src / test / java / org / opendaylight / ovsdb / southbound / it / SouthboundIT.java
1 /*
2  * Copyright (c) 2015 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 package org.opendaylight.ovsdb.southbound.it;
9
10 import static org.junit.Assert.assertNotNull;
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.CoreOptions.when;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
17 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
18 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
19
20 import com.google.common.collect.ImmutableBiMap;
21 import com.google.common.collect.Lists;
22 import com.google.common.collect.Sets;
23
24 import java.io.File;
25 import java.net.InetAddress;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Properties;
32 import java.util.Set;
33
34 import javax.inject.Inject;
35
36 import org.junit.Assert;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
41 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
42 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
43 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
44 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
45 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
46 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
47 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
48 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
49 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
104 import org.opendaylight.yangtools.concepts.Builder;
105 import org.opendaylight.yangtools.yang.binding.DataObject;
106 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
107 import org.ops4j.pax.exam.Configuration;
108 import org.ops4j.pax.exam.Option;
109 import org.ops4j.pax.exam.junit.PaxExam;
110 import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
111 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
112 import org.ops4j.pax.exam.options.MavenUrlReference;
113 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
114 import org.ops4j.pax.exam.spi.reactors.PerClass;
115 import org.osgi.framework.BundleContext;
116 import org.slf4j.Logger;
117 import org.slf4j.LoggerFactory;
118
119 /**
120  * Integration tests for southbound-impl
121  *
122  * @author Sam Hague (shague@redhat.com)
123  */
124 @RunWith(PaxExam.class)
125 @ExamReactorStrategy(PerClass.class)
126 public class SouthboundIT extends AbstractMdsalTestBase {
127     private static final String NETDEV_DP_TYPE = "netdev";
128     private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
129     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
130     private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
131     private static final String FORMAT_STR = "%s_%s_%d";
132     private static String addressStr;
133     private static int portNumber;
134     private static String connectionType;
135     private static boolean setup = false;
136     private static MdsalUtils mdsalUtils = null;
137
138     // TODO Constants copied from AbstractConfigTestBase, need to be removed (see TODO below)
139     private static final String PAX_EXAM_UNPACK_DIRECTORY = "target/exam";
140     private static final String KARAF_DEBUG_PORT = "5005";
141     private static final String KARAF_DEBUG_PROP = "karaf.debug";
142     private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
143
144     @Inject
145     private BundleContext bundleContext;
146
147     private static final NotifyingDataChangeListener CONFIGURATION_LISTENER =
148             new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION);
149     private static final NotifyingDataChangeListener OPERATIONAL_LISTENER =
150             new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL);
151
152     private static class NotifyingDataChangeListener implements DataChangeListener {
153         private final LogicalDatastoreType type;
154         private final Set<InstanceIdentifier<?>> createdIids = new HashSet<>();
155         private final Set<InstanceIdentifier<?>> removedIids = new HashSet<>();
156         private final Set<InstanceIdentifier<?>> updatedIids = new HashSet<>();
157
158         private NotifyingDataChangeListener(LogicalDatastoreType type) {
159             this.type = type;
160         }
161
162         @Override
163         public void onDataChanged(
164                 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
165             LOG.info("{} DataChanged: created {}", type, asyncDataChangeEvent.getCreatedData().keySet());
166             LOG.info("{} DataChanged: removed {}", type, asyncDataChangeEvent.getRemovedPaths());
167             LOG.info("{} DataChanged: updated {}", type, asyncDataChangeEvent.getUpdatedData().keySet());
168             createdIids.addAll(asyncDataChangeEvent.getCreatedData().keySet());
169             removedIids.addAll(asyncDataChangeEvent.getRemovedPaths());
170             updatedIids.addAll(asyncDataChangeEvent.getUpdatedData().keySet());
171             // Handled managed iids
172             for (DataObject obj : asyncDataChangeEvent.getCreatedData().values()) {
173                 if (obj instanceof ManagedNodeEntry) {
174                     ManagedNodeEntry managedNodeEntry = (ManagedNodeEntry) obj;
175                     LOG.info("{} DataChanged: created managed {}", managedNodeEntry.getBridgeRef().getValue());
176                     createdIids.add(managedNodeEntry.getBridgeRef().getValue());
177                 }
178             }
179             synchronized(this) {
180                 notifyAll();
181             }
182         }
183
184         public boolean isCreated(InstanceIdentifier<?> iid) {
185             return createdIids.remove(iid);
186         }
187
188         public boolean isRemoved(InstanceIdentifier<?> iid) {
189             return removedIids.remove(iid);
190         }
191
192         public boolean isUpdated(InstanceIdentifier<?> iid) {
193             return updatedIids.remove(iid);
194         }
195     }
196
197     @Configuration
198     public Option[] config() {
199         // TODO Figure out how to use the parent Karaf setup, then just use super.config()
200         Option[] options = new Option[] {
201                 when(Boolean.getBoolean(KARAF_DEBUG_PROP))
202                         .useOptions(KarafDistributionOption.debugConfiguration(KARAF_DEBUG_PORT, true)),
203                 karafDistributionConfiguration().frameworkUrl(getKarafDistro())
204                         .unpackDirectory(new File(PAX_EXAM_UNPACK_DIRECTORY))
205                         .useDeployFolder(false),
206                 when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
207                 // Works only if we don't specify the feature repo and name
208                 getLoggingOption()};
209         Option[] propertyOptions = getPropertiesOptions();
210         Option[] otherOptions = getOtherOptions();
211         Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
212         System.arraycopy(options, 0, combinedOptions, 0, options.length);
213         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
214         System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
215                 otherOptions.length);
216         return combinedOptions;
217     }
218
219     private Option[] getOtherOptions() {
220         return new Option[] {
221                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
222                 keepRuntimeFolder()
223         };
224     }
225
226     @Override
227     public String getKarafDistro() {
228         return maven()
229                 .groupId("org.opendaylight.ovsdb")
230                 .artifactId("southbound-karaf")
231                 .versionAsInProject()
232                 .type("zip")
233                 .getURL();
234     }
235
236     @Override
237     public String getModuleName() {
238         return "southbound-impl";
239     }
240
241     @Override
242     public String getInstanceName() {
243         return "southbound-default";
244     }
245
246     @Override
247     public MavenUrlReference getFeatureRepo() {
248         return maven()
249                 .groupId("org.opendaylight.ovsdb")
250                 .artifactId("southbound-features")
251                 .classifier("features")
252                 .type("xml")
253                 .versionAsInProject();
254     }
255
256     @Override
257     public String getFeatureName() {
258         return "odl-ovsdb-southbound-impl-ui";
259     }
260
261     protected String usage() {
262         return "Integration Test needs a valid connection configuration as follows :\n"
263                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
264                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
265     }
266
267     @Override
268     public Option getLoggingOption() {
269         return composite(
270                 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
271                         "log4j.logger.org.opendaylight.ovsdb",
272                         LogLevelOption.LogLevel.TRACE.name()),
273                 super.getLoggingOption());
274     }
275
276     private Option[] getPropertiesOptions() {
277         Properties props = new Properties(System.getProperties());
278         String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
279                 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
280         String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
281                 SouthboundITConstants.DEFAULT_SERVER_PORT);
282         String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
283                 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
284
285         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
286                 connectionType, addressStr, portStr);
287
288         return new Option[] {
289                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
290                         SouthboundITConstants.SERVER_IPADDRESS, addressStr),
291                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
292                         SouthboundITConstants.SERVER_PORT, portStr),
293                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
294                         SouthboundITConstants.CONNECTION_TYPE, connectionType),
295         };
296     }
297
298     @Before
299     @Override
300     public void setup() throws InterruptedException {
301         if (setup) {
302             LOG.info("Skipping setup, already initialized");
303             return;
304         }
305
306         try {
307             super.setup();
308         } catch (Exception e) {
309             e.printStackTrace();
310         }
311         //dataBroker = getSession().getSALService(DataBroker.class);
312         Thread.sleep(3000);
313         DataBroker dataBroker = SouthboundProvider.getDb();
314         Assert.assertNotNull("db should not be null", dataBroker);
315
316         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
317         String portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
318         try {
319             portNumber = Integer.parseInt(portStr);
320         } catch (NumberFormatException e) {
321             fail("Invalid port number " + portStr + System.lineSeparator() + usage());
322         }
323         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
324
325         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
326                 connectionType, addressStr, portNumber);
327         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
328             if (addressStr == null) {
329                 fail(usage());
330             }
331         }
332
333         mdsalUtils = new MdsalUtils(dataBroker);
334         dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
335                 createInstanceIdentifier(getConnectionInfo(addressStr, portNumber)), CONFIGURATION_LISTENER,
336                 AsyncDataBroker.DataChangeScope.SUBTREE);
337         dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
338                 createInstanceIdentifier(getConnectionInfo(addressStr, portNumber)), OPERATIONAL_LISTENER,
339                 AsyncDataBroker.DataChangeScope.SUBTREE);
340
341         setup = true;
342     }
343
344     /**
345      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
346      * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms.
347      *
348      * @throws InterruptedException
349      */
350     @Test
351     public void testPassiveNode() throws InterruptedException {
352         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
353             //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
354             Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
355         }
356     }
357
358     private ConnectionInfo getConnectionInfo(final String addressStr, final int portNumber) {
359         InetAddress inetAddress = null;
360         try {
361             inetAddress = InetAddress.getByName(addressStr);
362         } catch (UnknownHostException e) {
363             fail("Could not resolve " + addressStr + ": " + e);
364         }
365
366         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
367         PortNumber port = new PortNumber(portNumber);
368
369         final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
370                 .setRemoteIp(address)
371                 .setRemotePort(port)
372                 .build();
373         LOG.info("connectionInfo: {}", connectionInfo);
374         return connectionInfo;
375     }
376
377     private String connectionInfoToString(final ConnectionInfo connectionInfo) {
378         return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
379     }
380
381     @Test
382     public void testNetworkTopology() throws InterruptedException {
383         NetworkTopology networkTopology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION,
384                 InstanceIdentifier.create(NetworkTopology.class));
385         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
386                 networkTopology);
387
388         networkTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
389                 InstanceIdentifier.create(NetworkTopology.class));
390         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
391                 networkTopology);
392     }
393
394     @Test
395     public void testOvsdbTopology() throws InterruptedException {
396         InstanceIdentifier<Topology> path = InstanceIdentifier
397                 .create(NetworkTopology.class)
398                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
399
400         Topology topology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
401         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
402                 topology);
403
404         topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
405
406         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
407                 topology);
408     }
409
410     private InstanceIdentifier<Node> createInstanceIdentifier(
411             ConnectionInfo connectionInfo) {
412         return InstanceIdentifier
413                 .create(NetworkTopology.class)
414                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
415                 .child(Node.class,
416                         createNodeKey(connectionInfo.getRemoteIp(), connectionInfo.getRemotePort()));
417     }
418
419     private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
420         final InstanceIdentifier<Node> iid = createInstanceIdentifier(connectionInfo);
421         Assert.assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, createNode(connectionInfo)));
422         waitForOperationalCreation(iid);
423         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
424         Assert.assertNotNull(node);
425         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
426         return node;
427     }
428
429     private void waitForOperationalCreation(InstanceIdentifier<Node> iid) throws InterruptedException {
430         synchronized (OPERATIONAL_LISTENER) {
431             long _start = System.currentTimeMillis();
432             LOG.info("Waiting for OPERATIONAL DataChanged creation on {}", iid);
433             while (!OPERATIONAL_LISTENER.isCreated(
434                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
435                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
436             }
437             LOG.info("Woke up, waited {} for creation of {}", (System.currentTimeMillis() - _start), iid);
438         }
439     }
440
441     private void waitForOperationalDeletion(InstanceIdentifier<Node> iid) throws InterruptedException {
442         synchronized (OPERATIONAL_LISTENER) {
443             long _start = System.currentTimeMillis();
444             LOG.info("Waiting for OPERATIONAL DataChanged deletion on {}", iid);
445             while (!OPERATIONAL_LISTENER.isRemoved(
446                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
447                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
448             }
449             LOG.info("Woke up, waited {} for deletion of {}", (System.currentTimeMillis() - _start), iid);
450         }
451     }
452
453     private void waitForOperationalUpdate(InstanceIdentifier<Node> iid) throws InterruptedException {
454         synchronized (OPERATIONAL_LISTENER) {
455             long _start = System.currentTimeMillis();
456             LOG.info("Waiting for OPERATIONAL DataChanged update on {}", iid);
457             while (!OPERATIONAL_LISTENER.isUpdated(
458                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
459                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
460             }
461             LOG.info("Woke up, waited {} for update of {}", (System.currentTimeMillis() - _start), iid);
462         }
463     }
464
465     private void disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
466         final InstanceIdentifier<Node> iid = createInstanceIdentifier(connectionInfo);
467         Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
468         waitForOperationalDeletion(iid);
469         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
470         Assert.assertNull(node);
471         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
472     }
473
474     @Test
475     public void testAddDeleteOvsdbNode() throws InterruptedException {
476         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
477         connectOvsdbNode(connectionInfo);
478         disconnectOvsdbNode(connectionInfo);
479     }
480
481     @Test
482     public void testDpdkSwitch() throws InterruptedException {
483         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
484         Node ovsdbNode = connectOvsdbNode(connectionInfo);
485         List<DatapathTypeEntry> datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class)
486                 .getDatapathTypeEntry();
487         if (datapathTypeEntries == null) {
488             LOG.info("DPDK not supported on this node.");
489         } else {
490             for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) {
491                 Class<? extends DatapathTypeBase> dpType = dpTypeEntry.getDatapathType();
492                 String dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
493                 LOG.info("dp type is {}", dpTypeStr);
494                 if (dpTypeStr.equals(NETDEV_DP_TYPE)) {
495                     LOG.info("Found a DPDK node; adding a corresponding netdev device");
496                     InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo,
497                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
498                     NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
499                     addBridge(connectionInfo, bridgeIid, SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null,
500                             true, dpType, null, null, null);
501
502                     // Verify that the device is netdev
503                     OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
504                     Assert.assertNotNull(bridge);
505                     Assert.assertEquals(dpType, bridge.getDatapathType());
506
507                     // Add port for all dpdk interface types (dpdkvhost not supported in existing dpdk ovs)
508                     List<String> dpdkTypes = new ArrayList<String>();
509                     dpdkTypes.add("dpdk");
510                     dpdkTypes.add("dpdkr");
511                     dpdkTypes.add("dpdkvhostuser");
512                     //dpdkTypes.add("dpdkvhost");
513
514                     for (String dpdkType : dpdkTypes) {
515                         String testPortname = "test"+dpdkType+"port";
516                         LOG.info("DPDK portname and type is {}, {}", testPortname, dpdkType);
517                         Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
518                                 .get( dpdkType);
519                         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationpointBuilder =
520                                 createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(testPortname, dpdkIfType);
521                         Assert.assertTrue(addTerminationPoint(bridgeNodeId, testPortname , ovsdbTerminationpointBuilder));
522                     }
523
524                     // Verify that all DPDK ports are created
525                     InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
526                     Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
527                             terminationPointIid);
528                     Assert.assertNotNull(terminationPointNode);
529
530                     // Verify that each termination point has the specific DPDK ifType
531                     for (String dpdkType : dpdkTypes) {
532                         String testPortname = "test"+dpdkType+"port";
533                         Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
534                                 .get(dpdkType);
535                         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
536                         for (TerminationPoint terminationPoint : terminationPoints) {
537                             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
538                                     .getAugmentation(OvsdbTerminationPointAugmentation.class);
539                             if (ovsdbTerminationPointAugmentation.getName().equals(testPortname)) {
540                                 Class<? extends InterfaceTypeBase> opPort = ovsdbTerminationPointAugmentation
541                                         .getInterfaceType();
542                                 Assert.assertEquals(dpdkIfType, opPort);
543                             }
544                         }
545                     }
546                 }
547                 Assert.assertTrue(deleteBridge(connectionInfo));
548                 break;
549             }
550         }
551         disconnectOvsdbNode(connectionInfo);
552     }
553
554     @Test
555     public void testOvsdbNodeOvsVersion() throws InterruptedException {
556         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
557         Node ovsdbNode = connectOvsdbNode(connectionInfo);
558         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
559         Assert.assertNotNull(ovsdbNodeAugmentation);
560         assertNotNull(ovsdbNodeAugmentation.getOvsVersion());
561         disconnectOvsdbNode(connectionInfo);
562     }
563
564     @Test
565     public void testOpenVSwitchOtherConfig() throws InterruptedException {
566         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
567         Node ovsdbNode = connectOvsdbNode(connectionInfo);
568         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
569         Assert.assertNotNull(ovsdbNodeAugmentation);
570         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
571         if (otherConfigsList != null) {
572             for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
573                 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
574                     LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
575                     break;
576                 } else {
577                     LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
578                 }
579             }
580         } else {
581             LOG.info("other_config is not present");
582         }
583         disconnectOvsdbNode(connectionInfo);
584     }
585
586     @Test
587     public void testOvsdbBridgeControllerInfo() throws InterruptedException {
588         ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portNumber);
589         Node ovsdbNode = connectOvsdbNode(connectionInfo);
590         String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
591         assertNotNull("Failed to get controller target", controllerTarget);
592         List<ControllerEntry> setControllerEntry = createControllerEntry(controllerTarget);
593         Uri setUri = new Uri(controllerTarget);
594         Assert.assertTrue(addBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
595                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
596                 setControllerEntry, null));
597         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
598         Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
599         Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
600                 bridge.getControllerEntry());
601         List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
602         for (ControllerEntry entry : getControllerEntries) {
603             if (entry.getTarget() != null) {
604                 Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
605             }
606         }
607
608         Assert.assertTrue(deleteBridge(connectionInfo));
609         disconnectOvsdbNode(connectionInfo);
610     }
611
612     private List<ControllerEntry> createControllerEntry(String controllerTarget) {
613         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
614         controllerEntriesList.add(new ControllerEntryBuilder()
615                 .setTarget(new Uri(controllerTarget))
616                 .build());
617         return controllerEntriesList;
618     }
619
620     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
621                               final ConnectionInfo connectionInfo) {
622         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
623         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
624     }
625
626     private List<ProtocolEntry> createMdsalProtocols() {
627         List<ProtocolEntry> protocolList = new ArrayList<>();
628         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
629                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
630         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
631         return protocolList;
632     }
633
634     private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() {
635         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder =
636                 new OvsdbTerminationPointAugmentationBuilder();
637         ovsdbTerminationPointAugmentationBuilder.setInterfaceType(
638                 new InterfaceTypeEntryBuilder()
639                         .setInterfaceType(
640                                 SouthboundMapper.createInterfaceType("internal"))
641                         .build().getInterfaceType());
642         return ovsdbTerminationPointAugmentationBuilder;
643     }
644
645     private OvsdbTerminationPointAugmentationBuilder createGenericDpdkOvsdbTerminationPointAugmentationBuilder(
646             final String portName) {
647         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
648                 createGenericOvsdbTerminationPointAugmentationBuilder();
649         ovsdbTerminationBuilder.setName(portName);
650         Class<? extends InterfaceTypeBase> ifType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
651                 .get("dpdk");
652         ovsdbTerminationBuilder.setInterfaceType(ifType);
653         return ovsdbTerminationBuilder;
654     }
655
656     private OvsdbTerminationPointAugmentationBuilder createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(
657             String testPortname,Class<? extends InterfaceTypeBase> dpdkIfType) {
658         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
659                 createGenericOvsdbTerminationPointAugmentationBuilder();
660         ovsdbTerminationBuilder.setName(testPortname);
661         ovsdbTerminationBuilder.setInterfaceType(dpdkIfType);
662         return ovsdbTerminationBuilder;
663     }
664
665     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
666                                         final OvsdbTerminationPointAugmentationBuilder
667                                                 ovsdbTerminationPointAugmentationBuilder)
668             throws InterruptedException {
669
670         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
671         NodeBuilder portNodeBuilder = new NodeBuilder();
672         NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid);
673         portNodeBuilder.setNodeId(portNodeId);
674         TerminationPointBuilder entry = new TerminationPointBuilder();
675         entry.setKey(new TerminationPointKey(new TpId(portName)));
676         entry.addAugmentation(
677                 OvsdbTerminationPointAugmentation.class,
678                 ovsdbTerminationPointAugmentationBuilder.build());
679         portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build()));
680         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
681                 portIid, portNodeBuilder.build());
682         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
683         return result;
684     }
685
686     /*
687      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
688      *
689      * @param connectionInfo
690      * @param bridgeIid if passed null, one is created
691      * @param bridgeName cannot be null
692      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
693      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
694      * @param failMode toggles whether default fail mode is set for the bridge
695      * @param setManagedBy toggles whether to setManagedBy for the bridge
696      * @param dpType if passed null, this parameter is ignored
697      * @param externalIds if passed null, this parameter is ignored
698      * @param otherConfigs if passed null, this parameter is ignored
699      * @return success of bridge addition
700      * @throws InterruptedException
701      */
702     private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
703                               final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
704                               final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
705                               final Class<? extends DatapathTypeBase> dpType,
706                               final List<BridgeExternalIds> externalIds,
707                               final List<ControllerEntry> controllerEntries,
708                               final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
709
710         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
711         if (bridgeIid == null) {
712             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
713         }
714         if (bridgeNodeId == null) {
715             bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
716         }
717         bridgeNodeBuilder.setNodeId(bridgeNodeId);
718         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
719         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
720         if (setProtocolEntries) {
721             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
722         }
723         if (failMode != null) {
724             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
725         }
726         if (setManagedBy) {
727             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
728         }
729         if (dpType != null) {
730             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
731         }
732         if (externalIds != null) {
733             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
734         }
735         if (controllerEntries != null) {
736             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
737         }
738         if (otherConfigs != null) {
739             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
740         }
741         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
742         LOG.debug("Built with the intent to store bridge data {}", ovsdbBridgeAugmentationBuilder.toString());
743         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
744                 bridgeIid, bridgeNodeBuilder.build());
745         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
746         return result;
747     }
748
749     private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
750             throws InterruptedException {
751
752         return addBridge(connectionInfo, null, bridgeName, null, true,
753                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
754     }
755
756     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
757         return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
758     }
759
760     /**
761      * Extract the <code>store</code> type data store contents for the particular bridge identified by
762      * <code>bridgeName</code>.
763      *
764      * @param connectionInfo the connection information
765      * @param bridgeName the bridge name
766      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
767      * @return <code>store</code> type data store contents
768      */
769     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
770                                               LogicalDatastoreType store) {
771         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
772         Assert.assertNotNull(bridgeNode);
773         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
774         Assert.assertNotNull(ovsdbBridgeAugmentation);
775         return ovsdbBridgeAugmentation;
776     }
777
778     /**
779      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
780      * identified by <code>bridgeName</code>
781      *
782      * @param connectionInfo the connection information
783      * @param bridgeName the bridge name
784      * @see <code>SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
785      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
786      */
787     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
788         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
789     }
790
791     /**
792      * Extract the node contents from <code>store</code> type data store for the
793      * bridge identified by <code>bridgeName</code>
794      *
795      * @param connectionInfo the connection information
796      * @param bridgeName the bridge name
797      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
798      * @return <code>store</code> type data store contents
799      */
800     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
801         InstanceIdentifier<Node> bridgeIid =
802                 createInstanceIdentifier(connectionInfo,
803                         new OvsdbBridgeName(bridgeName));
804         return mdsalUtils.read(store, bridgeIid);
805     }
806
807     /**
808      * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
809      * bridge identified by <code>bridgeName</code>
810      *
811      * @param connectionInfo the connection information
812      * @param bridgeName the bridge name
813      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
814      */
815     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
816         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
817     }
818
819     private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException {
820         return deleteBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
821     }
822
823     private boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName)
824             throws InterruptedException {
825
826         final InstanceIdentifier<Node> iid = createInstanceIdentifier(connectionInfo,
827                 new OvsdbBridgeName(bridgeName));
828         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid);
829         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
830         return result;
831     }
832
833     @Test
834     public void testAddDeleteBridge() throws InterruptedException {
835         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
836         connectOvsdbNode(connectionInfo);
837
838         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
839         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
840         Assert.assertNotNull(bridge);
841         LOG.info("bridge: {}", bridge);
842
843         Assert.assertTrue(deleteBridge(connectionInfo));
844
845         disconnectOvsdbNode(connectionInfo);
846     }
847
848     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
849         return createInstanceIdentifier(connectionInfo,
850                 bridge.getBridgeName());
851     }
852
853     /**
854      * Extracts the <code>TerminationPointAugmentation</code> for the <code>index</code> <code>TerminationPoint</code>
855      * on <code>bridgeName</code>
856      *
857      * @param connectionInfo the connection information
858      * @param bridgeName the bridge name
859      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
860      * @param index the index we're interested in
861      * @return the augmentation (or {@code null} if none)
862      */
863     private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
864             ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) {
865
866         List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
867         if (tpList == null) {
868             return null;
869         }
870         return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class);
871     }
872
873     @Test
874     public void testCRDTerminationPointOfPort() throws InterruptedException {
875         final Long OFPORT_EXPECTED = 45002L;
876
877         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
878         connectOvsdbNode(connectionInfo);
879
880         // CREATE
881         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
882         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
883         Assert.assertNotNull(bridge);
884         LOG.info("bridge: {}", bridge);
885         NodeId nodeId = SouthboundMapper.createManagedNodeId(createInstanceIdentifier(
886                 connectionInfo, bridge.getBridgeName()));
887         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
888                 createGenericOvsdbTerminationPointAugmentationBuilder();
889         String portName = "testOfPort";
890         ovsdbTerminationBuilder.setName(portName);
891
892         ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
893         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
894         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
895         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
896         Assert.assertNotNull(terminationPointNode);
897
898         // READ
899         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
900         for (TerminationPoint terminationPoint : terminationPoints) {
901             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
902                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
903             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
904                 Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
905                 // if ephemeral port 45002 is in use, ofPort is set to 1
906                 Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
907                 LOG.info("ofPort: {}", ofPort);
908             }
909         }
910
911         // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
912         //   "A client should ideally set this column’s value in the same database transaction that it uses to create
913         //   the interface."
914
915         // DELETE
916         Assert.assertTrue(deleteBridge(connectionInfo));
917         disconnectOvsdbNode(connectionInfo);
918     }
919
920     @Test
921     public void testCRDTerminationPointOfPortRequest() throws InterruptedException {
922         final Long OFPORT_EXPECTED = 45008L;
923         final Long OFPORT_INPUT = 45008L;
924
925         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
926         connectOvsdbNode(connectionInfo);
927
928         // CREATE
929         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
930         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
931         Assert.assertNotNull(bridge);
932         NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
933                 connectionInfo, bridge.getBridgeName()));
934         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
935                 createGenericOvsdbTerminationPointAugmentationBuilder();
936         String portName = "testOfPortRequest";
937         ovsdbTerminationBuilder.setName(portName);
938         Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
939         ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
940         ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
941         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
942         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
943         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
944         Assert.assertNotNull(terminationPointNode);
945
946         // READ
947         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
948         for (TerminationPoint terminationPoint : terminationPoints) {
949             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
950                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
951             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
952                 Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
953                 // if ephemeral port 45008 is in use, ofPort is set to 1
954                 Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
955                 LOG.info("ofPort: {}", ofPort);
956
957                 Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
958                 Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
959                 LOG.info("ofPortRequest: {}", ofPortRequest);
960             }
961         }
962
963         // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
964         //   "A client should ideally set this column’s value in the same database transaction that it uses to create
965         //   the interface. "
966
967         // DELETE
968         Assert.assertTrue(deleteBridge(connectionInfo));
969         disconnectOvsdbNode(connectionInfo);
970     }
971
972     private <T> void assertExpectedExist(List<T> expected, List<T> test) {
973         if (expected != null && test != null) {
974             for (T exp : expected) {
975                 Assert.assertTrue("The retrieved values don't contain " + exp, test.contains(exp));
976             }
977         }
978     }
979
980     private interface SouthboundTerminationPointHelper<T> {
981         void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<T> values);
982         List<T> readValues(OvsdbTerminationPointAugmentation augmentation);
983     }
984
985     /*
986      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
987      *
988      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
989      */
990     private <T> void testCRUDTerminationPoint(
991             KeyValueBuilder<T> builder, String prefix, SouthboundTerminationPointHelper<T> helper)
992             throws InterruptedException {
993         final int TERMINATION_POINT_TEST_INDEX = 0;
994
995         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
996         connectOvsdbNode(connectionInfo);
997
998         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
999         // the update has been performed.
1000         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
1001         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
1002
1003         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
1004             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
1005                 String testBridgeAndPortName = String.format("%s_%s", prefix, updateToTestCase.name);
1006
1007                 // CREATE: Create the test bridge
1008                 Assert.assertTrue(addBridge(connectionInfo, null, testBridgeAndPortName, null, true,
1009                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null));
1010                 NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1011                         connectionInfo, new OvsdbBridgeName(testBridgeAndPortName)));
1012                 OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1013                         createGenericOvsdbTerminationPointAugmentationBuilder();
1014                 tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1015                 helper.writeValues(tpCreateAugmentationBuilder, updateFromTestCase.inputValues);
1016                 Assert.assertTrue(
1017                         addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1018
1019                 // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
1020                 // then repeat for OPERATIONAL data store
1021                 OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1022                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1023                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1024                 if (updateFromConfigurationTerminationPointAugmentation != null) {
1025                     List<T> updateFromConfigurationValues =
1026                             helper.readValues(updateFromConfigurationTerminationPointAugmentation);
1027                     assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
1028                 }
1029                 OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1030                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1031                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1032                 if (updateFromOperationalTerminationPointAugmentation != null) {
1033                     List<T> updateFromOperationalValues =
1034                             helper.readValues(updateFromOperationalTerminationPointAugmentation);
1035                     assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
1036                 }
1037
1038                 // UPDATE:  update the values
1039                 testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1040                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1041                         new OvsdbTerminationPointAugmentationBuilder();
1042                 helper.writeValues(tpUpdateAugmentationBuilder, updateToTestCase.inputValues);
1043                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1044                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1045                 NodeId portUpdateNodeId = createManagedNodeId(portIid);
1046                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1047                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1048                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1049                 tpUpdateBuilder.addAugmentation(
1050                         OvsdbTerminationPointAugmentation.class,
1051                         tpUpdateAugmentationBuilder.build());
1052                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1053                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1054                         portIid, portUpdateNodeBuilder.build()));
1055                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1056
1057                 // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
1058                 // then repeat for OPERATIONAL data store
1059                 OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1060                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1061                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1062                 if (updateToConfigurationTerminationPointAugmentation != null) {
1063                     List<T> updateToConfigurationValues =
1064                             helper.readValues(updateToConfigurationTerminationPointAugmentation);
1065                     assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
1066                     assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationValues);
1067                 }
1068                 OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1069                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1070                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1071                 if (updateToOperationalTerminationPointAugmentation != null) {
1072                     List<T> updateToOperationalValues =
1073                             helper.readValues(updateToOperationalTerminationPointAugmentation);
1074                     if (updateFromTestCase.expectedValues != null ) {
1075                         assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
1076                         assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalValues);
1077                     }
1078                 }
1079
1080                 // DELETE
1081                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeAndPortName));
1082             }
1083         }
1084         disconnectOvsdbNode(connectionInfo);
1085     }
1086
1087     /*
1088      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
1089      *
1090      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1091      */
1092     @Test
1093     public void testCRUDTerminationPointPortExternalIds() throws InterruptedException {
1094         testCRUDTerminationPoint(new SouthboundPortExternalIdsBuilder(), "TPPortExternalIds",
1095                 new PortExternalIdsSouthboundHelper());
1096     }
1097
1098     /*
1099      * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
1100      *
1101      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1102      */
1103     @Test
1104     public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException {
1105         testCRUDTerminationPoint(new SouthboundInterfaceExternalIdsBuilder(), "TPInterfaceExternalIds",
1106                 new InterfaceExternalIdsSouthboundHelper());
1107     }
1108
1109     /*
1110      * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
1111      *
1112      * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
1113      */
1114     @Test
1115     public void testCRUDTerminationPointOptions() throws InterruptedException {
1116         testCRUDTerminationPoint(new SouthboundOptionsBuilder(), "TPOptions", new OptionsSouthboundHelper());
1117     }
1118
1119     /*
1120      * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
1121      *
1122      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1123      */
1124     @Test
1125     public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
1126         testCRUDTerminationPoint(new SouthboundInterfaceOtherConfigsBuilder(), "TPInterfaceOtherConfigs",
1127                 new InterfaceOtherConfigsSouthboundHelper());
1128     }
1129
1130     /*
1131      * Tests the CRUD operations for <code>Port</code> <code>other_configs</code>.
1132      *
1133      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1134      */
1135     @Test
1136     public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
1137         testCRUDTerminationPoint(new SouthboundPortOtherConfigsBuilder(), "TPPortOtherConfigs",
1138                 new PortOtherConfigsSouthboundHelper());
1139     }
1140
1141     @Test
1142     public void testCRUDTerminationPointVlan() throws InterruptedException {
1143         final Integer CREATED_VLAN_ID = 4000;
1144         final Integer UPDATED_VLAN_ID = 4001;
1145
1146         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1147         connectOvsdbNode(connectionInfo);
1148
1149         // CREATE
1150         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
1151         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1152         Assert.assertNotNull(bridge);
1153         NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
1154                 connectionInfo, bridge.getBridgeName()));
1155         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1156                 createGenericOvsdbTerminationPointAugmentationBuilder();
1157         String portName = "testTerminationPointVlanId";
1158         ovsdbTerminationBuilder.setName(portName);
1159         ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
1160         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1161         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1162         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1163         Assert.assertNotNull(terminationPointNode);
1164
1165         // READ
1166         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1167         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation;
1168         for (TerminationPoint terminationPoint : terminationPoints) {
1169             ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1170                     OvsdbTerminationPointAugmentation.class);
1171             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1172                 VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1173                 Assert.assertNotNull(actualVlanId);
1174                 Integer actualVlanIdInt = actualVlanId.getValue();
1175                 Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
1176             }
1177         }
1178
1179         // UPDATE
1180         NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1181         OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1182                 new OvsdbTerminationPointAugmentationBuilder();
1183         tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
1184         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1185         NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1186         NodeId portUpdateNodeId = createManagedNodeId(portIid);
1187         portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1188         TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1189         tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1190         tpUpdateBuilder.addAugmentation(
1191                 OvsdbTerminationPointAugmentation.class,
1192                 tpUpdateAugmentationBuilder.build());
1193         tpUpdateBuilder.setTpId(new TpId(portName));
1194         portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1195         Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1196         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1197
1198         terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1199         terminationPoints = terminationPointNode.getTerminationPoint();
1200         for (TerminationPoint terminationPoint : terminationPoints) {
1201             ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1202                     OvsdbTerminationPointAugmentation.class);
1203             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1204                 VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1205                 Assert.assertNotNull(actualVlanId);
1206                 Integer actualVlanIdInt = actualVlanId.getValue();
1207                 Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
1208             }
1209         }
1210
1211         // DELETE
1212         Assert.assertTrue(deleteBridge(connectionInfo));
1213         disconnectOvsdbNode(connectionInfo);
1214     }
1215
1216     @Test
1217     public void testCRUDTerminationPointVlanModes() throws InterruptedException {
1218         final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
1219         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1220         connectOvsdbNode(connectionInfo);
1221         VlanMode []vlanModes = VlanMode.values();
1222         for (VlanMode vlanMode : vlanModes) {
1223             // CREATE
1224             Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
1225             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1226             Assert.assertNotNull(bridge);
1227             NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
1228                     connectionInfo, bridge.getBridgeName()));
1229             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1230                     createGenericOvsdbTerminationPointAugmentationBuilder();
1231             String portName = "testTerminationPointVlanMode" + vlanMode.toString();
1232             ovsdbTerminationBuilder.setName(portName);
1233             ovsdbTerminationBuilder.setVlanMode(vlanMode);
1234             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1235             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1236             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1237             Assert.assertNotNull(terminationPointNode);
1238
1239             // READ
1240             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1241             for (TerminationPoint terminationPoint : terminationPoints) {
1242                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1243                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1244                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1245                     //test
1246                     Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
1247                 }
1248             }
1249
1250             // UPDATE
1251             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1252             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1253                     new OvsdbTerminationPointAugmentationBuilder();
1254             tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
1255             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1256             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1257             NodeId portUpdateNodeId = createManagedNodeId(portIid);
1258             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1259             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1260             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1261             tpUpdateBuilder.addAugmentation(
1262                     OvsdbTerminationPointAugmentation.class,
1263                     tpUpdateAugmentationBuilder.build());
1264             tpUpdateBuilder.setTpId(new TpId(portName));
1265             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1266             Assert.assertTrue(
1267                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1268             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1269
1270             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1271             terminationPoints = terminationPointNode.getTerminationPoint();
1272             for (TerminationPoint terminationPoint : terminationPoints) {
1273                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1274                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1275                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1276                     //test
1277                     Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
1278                 }
1279             }
1280
1281             // DELETE
1282             Assert.assertTrue(deleteBridge(connectionInfo));
1283         }
1284         disconnectOvsdbNode(connectionInfo);
1285     }
1286
1287     @SuppressWarnings("unchecked")
1288     private List<Set<Integer>> generateVlanSets() {
1289         int min = 0;
1290         int max = 4095;
1291         return Lists.newArrayList(
1292                 Collections.<Integer>emptySet(),
1293                 Sets.newHashSet(2222),
1294                 Sets.newHashSet(min, max, min + 1, max - 1, (max - min) / 2));
1295     }
1296
1297     private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
1298         List<Trunks> trunkList = Lists.newArrayList();
1299         for (Integer trunk : trunkSet) {
1300             TrunksBuilder trunkBuilder = new TrunksBuilder();
1301             trunkBuilder.setTrunk(new VlanId(trunk));
1302             trunkList.add(trunkBuilder.build());
1303         }
1304         return trunkList;
1305     }
1306
1307     @Test
1308     public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
1309         final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
1310         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1311         connectOvsdbNode(connectionInfo);
1312         Iterable<Set<Integer>> vlanSets = generateVlanSets();
1313         int testCase = 0;
1314         for (Set<Integer> vlanSet : vlanSets) {
1315             ++testCase;
1316             // CREATE
1317             Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
1318             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1319             Assert.assertNotNull(bridge);
1320             NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
1321                     connectionInfo, bridge.getBridgeName()));
1322             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1323                     createGenericOvsdbTerminationPointAugmentationBuilder();
1324             String portName = "testTerminationPointVlanTrunks" + testCase;
1325             ovsdbTerminationBuilder.setName(portName);
1326             List<Trunks> trunks = buildTrunkList(vlanSet);
1327             ovsdbTerminationBuilder.setTrunks(trunks);
1328             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1329             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1330             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1331             Assert.assertNotNull(terminationPointNode);
1332
1333             // READ
1334             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1335             for (TerminationPoint terminationPoint : terminationPoints) {
1336                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1337                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1338                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1339                     List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
1340                     for (Trunks trunk : trunks) {
1341                         Assert.assertTrue(actualTrunks.contains(trunk));
1342                     }
1343                 }
1344             }
1345
1346
1347             // UPDATE
1348             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1349             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1350                     new OvsdbTerminationPointAugmentationBuilder();
1351             tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
1352             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1353             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1354             NodeId portUpdateNodeId = createManagedNodeId(portIid);
1355             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1356             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1357             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1358             tpUpdateBuilder.addAugmentation(
1359                     OvsdbTerminationPointAugmentation.class,
1360                     tpUpdateAugmentationBuilder.build());
1361             tpUpdateBuilder.setTpId(new TpId(portName));
1362             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1363             Assert.assertTrue(
1364                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1365             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1366
1367             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1368             terminationPoints = terminationPointNode.getTerminationPoint();
1369             for (TerminationPoint terminationPoint : terminationPoints) {
1370                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1371                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1372                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1373                     //test
1374                     Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
1375                 }
1376             }
1377
1378             // DELETE
1379             Assert.assertTrue(deleteBridge(connectionInfo));
1380         }
1381         disconnectOvsdbNode(connectionInfo);
1382     }
1383
1384     @Test
1385     public void testGetOvsdbNodes() throws InterruptedException {
1386         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1387         connectOvsdbNode(connectionInfo);
1388         InstanceIdentifier<Topology> topologyPath = InstanceIdentifier
1389                 .create(NetworkTopology.class)
1390                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
1391
1392         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
1393         InstanceIdentifier<Node> expectedNodeIid = createInstanceIdentifier(connectionInfo);
1394         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
1395         Node foundNode = null;
1396         Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
1397         Assert.assertNotNull("Expected to find some nodes" + topology.getNode());
1398         LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode());
1399         for (Node node : topology.getNode()) {
1400             if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) {
1401                 foundNode = node;
1402                 break;
1403             }
1404         }
1405         Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
1406         disconnectOvsdbNode(connectionInfo);
1407     }
1408
1409     /*
1410      * @see <code>SouthboundIT.generateBridgeOtherConfigsTestCases()</code> for specific test case information.
1411      */
1412     @Test
1413     public void testCRUDBridgeOtherConfigs() throws InterruptedException {
1414         testCRUDBridge("BridgeOtherConfigs", new SouthboundBridgeOtherConfigsBuilder(),
1415                 new BridgeOtherConfigsSouthboundHelper());
1416     }
1417
1418     private interface SouthboundBridgeHelper<T> {
1419         void writeValues(OvsdbBridgeAugmentationBuilder builder, List<T> values);
1420         List<T> readValues(OvsdbBridgeAugmentation augmentation);
1421     }
1422
1423     private <T> void testCRUDBridge(String prefix, KeyValueBuilder<T> builder, SouthboundBridgeHelper<T> helper)
1424             throws InterruptedException {
1425         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1426         connectOvsdbNode(connectionInfo);
1427         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1428         // the update has been performed.
1429         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
1430         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
1431         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
1432             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
1433                 String testBridgeName = String.format("%s_%s", prefix, updateToTestCase.name);
1434
1435                 // CREATE: Create the test bridge
1436                 final OvsdbBridgeName ovsdbBridgeName = new OvsdbBridgeName(testBridgeName);
1437                 final InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, ovsdbBridgeName);
1438                 final NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
1439                 final NodeBuilder bridgeCreateNodeBuilder = new NodeBuilder();
1440                 bridgeCreateNodeBuilder.setNodeId(bridgeNodeId);
1441                 OvsdbBridgeAugmentationBuilder bridgeCreateAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
1442                 bridgeCreateAugmentationBuilder.setBridgeName(ovsdbBridgeName);
1443                 bridgeCreateAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
1444                 bridgeCreateAugmentationBuilder.setFailMode(
1445                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
1446                 setManagedBy(bridgeCreateAugmentationBuilder, connectionInfo);
1447                 helper.writeValues(bridgeCreateAugmentationBuilder, updateFromTestCase.inputValues);
1448                 bridgeCreateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
1449                         bridgeCreateAugmentationBuilder.build());
1450                 LOG.debug("Built with the intent to store bridge data {}", bridgeCreateAugmentationBuilder.toString());
1451                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
1452                         bridgeCreateNodeBuilder.build()));
1453                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1454
1455                 // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
1456                 // then repeat for OPERATIONAL data store
1457                 List<T> updateFromConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
1458                         LogicalDatastoreType.CONFIGURATION));
1459                 assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationExternalIds);
1460                 List<T> updateFromOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
1461                 assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalExternalIds);
1462
1463                 // UPDATE:  update the values
1464                 final OvsdbBridgeAugmentationBuilder bridgeUpdateAugmentationBuilder =
1465                         new OvsdbBridgeAugmentationBuilder();
1466                 helper.writeValues(bridgeUpdateAugmentationBuilder, updateToTestCase.inputValues);
1467                 final NodeBuilder bridgeUpdateNodeBuilder = new NodeBuilder();
1468                 final Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
1469                 bridgeUpdateNodeBuilder.setNodeId(bridgeNode.getNodeId());
1470                 bridgeUpdateNodeBuilder.setKey(bridgeNode.getKey());
1471                 bridgeUpdateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
1472                         bridgeUpdateAugmentationBuilder.build());
1473                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
1474                         bridgeUpdateNodeBuilder.build()));
1475                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1476
1477                 // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
1478                 // then repeat for OPERATIONAL data store
1479                 List<T> updateToConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
1480                         LogicalDatastoreType.CONFIGURATION));
1481                 assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationExternalIds);
1482                 assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationExternalIds);
1483                 List<T> updateToOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
1484                 if (updateFromTestCase.expectedValues != null) {
1485                     assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalExternalIds);
1486                     assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalExternalIds);
1487                 }
1488
1489                 // DELETE
1490                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
1491             }
1492         }
1493         disconnectOvsdbNode(connectionInfo);
1494     }
1495
1496     /*
1497      * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
1498      */
1499     @Test
1500     public void testCRUDBridgeExternalIds() throws InterruptedException {
1501         testCRUDBridge("BridgeExternalIds", new SouthboundBridgeExternalIdsBuilder(),
1502                 new BridgeExternalIdsSouthboundHelper());
1503     }
1504
1505     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
1506         return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
1507     }
1508
1509     public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
1510         return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
1511     }
1512
1513     public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
1514         return new NodeId(createNodeId(ip,port).getValue()
1515                 + "/" + SouthboundConstants.BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
1516     }
1517
1518     public static NodeId createNodeId(IpAddress ip, PortNumber port) {
1519         String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
1520                 + new String(ip.getValue()) + ":" + port.getValue();
1521         Uri uri = new Uri(uriString);
1522         return new NodeId(uri);
1523     }
1524
1525     public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
1526         return new NodeKey(createNodeId(ip,port));
1527     }
1528
1529     public static Node createNode(ConnectionInfo key) {
1530         NodeBuilder nodeBuilder = new NodeBuilder();
1531         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(),key.getRemotePort()));
1532         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
1533         return nodeBuilder.build();
1534     }
1535
1536     public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
1537         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
1538         ovsdbNodeBuilder.setConnectionInfo(key);
1539         return ovsdbNodeBuilder.build();
1540     }
1541
1542     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
1543         NodeKey nodeKey = iid.firstKeyOf(Node.class, NodeKey.class);
1544         return nodeKey.getNodeId();
1545     }
1546
1547     /**
1548      * <p>
1549      * Representation of a southbound test case. Each test case has a name, a list of input values and a list of
1550      * expected values. The input values are provided to the augmentation builder, and the expected values are checked
1551      * against the output of the resulting augmentation.
1552      * </p>
1553      * <p>
1554      * Instances of this class are immutable.
1555      * </p>
1556      *
1557      * @param <T> The type of data used for the test case.
1558      */
1559     private static final class SouthboundTestCase<T> {
1560         private final String name;
1561         private final List<T> inputValues;
1562         private final List<T> expectedValues;
1563
1564         /**
1565          * Creates an instance of a southbound test case.
1566          *
1567          * @param name The test case's name.
1568          * @param inputValues The input values (provided as input to the underlying augmentation builder).
1569          * @param expectedValues The expected values (checked against the output of the underlying augmentation).
1570          */
1571         public SouthboundTestCase(
1572                 final String name, final List<T> inputValues, final List<T> expectedValues) {
1573             this.name = name;
1574             this.inputValues = inputValues;
1575             this.expectedValues = expectedValues;
1576         }
1577     }
1578
1579     /**
1580      * Southbound test case builder.
1581      *
1582      * @param <T> The type of data used for the test case.
1583      */
1584     private static final class SouthboundTestCaseBuilder<T> {
1585         private String name;
1586         private List<T> inputValues;
1587         private List<T> expectedValues;
1588
1589         /**
1590          * Creates a builder. Builders may be reused, the generated immutable instances are independent of the
1591          * builders. There are no default values.
1592          */
1593         public SouthboundTestCaseBuilder() {
1594             // Nothing to do
1595         }
1596
1597         /**
1598          * Sets the test case's name.
1599          *
1600          * @param name The test case's name.
1601          * @return The builder.
1602          */
1603         public SouthboundTestCaseBuilder<T> name(final String name) {
1604             this.name = name;
1605             return this;
1606         }
1607
1608         /**
1609          * Sets the input values.
1610          *
1611          * @param inputValues The input values.
1612          * @return The builder.
1613          */
1614         @SafeVarargs
1615         public final SouthboundTestCaseBuilder<T> input(final T... inputValues) {
1616             this.inputValues = Lists.newArrayList(inputValues);
1617             return this;
1618         }
1619
1620         /**
1621          * Indicates that the provided input values should be expected as output values.
1622          *
1623          * @return The builder.
1624          */
1625         public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
1626             this.expectedValues = this.inputValues;
1627             return this;
1628         }
1629
1630         /**
1631          * Indicates that no output should be expected.
1632          *
1633          * @return The builder.
1634          */
1635         public SouthboundTestCaseBuilder<T> expectNoOutput() {
1636             this.expectedValues = null;
1637             return this;
1638         }
1639
1640         /**
1641          * Builds an immutable instance representing the test case.
1642          *
1643          * @return The test case.
1644          */
1645         @SuppressWarnings("unchecked")
1646         public SouthboundTestCase<T> build() {
1647             return new SouthboundTestCase<>(name, inputValues, expectedValues);
1648         }
1649     }
1650
1651     private abstract static class KeyValueBuilder<T> {
1652         private static final int COUNTER_START = 0;
1653         private int counter = COUNTER_START;
1654
1655         protected abstract Builder<T> builder();
1656
1657         protected abstract void setKey(Builder<T> builder, String key);
1658
1659         protected abstract void setValue(Builder<T> builder, String value);
1660
1661         public final T build(final String testName, final String key, final String value) {
1662             final Builder<T> builder = builder();
1663             this.counter++;
1664             if (key != null) {
1665                 setKey(builder, String.format(FORMAT_STR, testName, key, this.counter));
1666             }
1667             if (value != null) {
1668                 setValue(builder, String.format(FORMAT_STR, testName, value, this.counter));
1669             }
1670             return builder.build();
1671         }
1672
1673         public final void reset() {
1674             this.counter = COUNTER_START;
1675         }
1676     }
1677
1678     private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder<PortExternalIds> {
1679         @Override
1680         protected Builder<PortExternalIds> builder() {
1681             return new PortExternalIdsBuilder();
1682         }
1683
1684         @Override
1685         protected void setKey(Builder<PortExternalIds> builder, String key) {
1686             ((PortExternalIdsBuilder) builder).setExternalIdKey(key);
1687         }
1688
1689         @Override
1690         protected void setValue(Builder<PortExternalIds> builder, String value) {
1691             ((PortExternalIdsBuilder) builder).setExternalIdValue(value);
1692         }
1693     }
1694
1695     private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder<InterfaceExternalIds> {
1696         @Override
1697         protected Builder<InterfaceExternalIds> builder() {
1698             return new InterfaceExternalIdsBuilder();
1699         }
1700
1701         @Override
1702         protected void setKey(Builder<InterfaceExternalIds> builder, String key) {
1703             ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key);
1704         }
1705
1706         @Override
1707         protected void setValue(Builder<InterfaceExternalIds> builder, String value) {
1708             ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value);
1709         }
1710     }
1711
1712     private static final class SouthboundOptionsBuilder extends KeyValueBuilder<Options> {
1713         @Override
1714         protected Builder<Options> builder() {
1715             return new OptionsBuilder();
1716         }
1717
1718         @Override
1719         protected void setKey(Builder<Options> builder, String key) {
1720             ((OptionsBuilder) builder).setOption(key);
1721         }
1722
1723         @Override
1724         protected void setValue(Builder<Options> builder, String value) {
1725             ((OptionsBuilder) builder).setValue(value);
1726         }
1727     }
1728
1729     private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder<InterfaceOtherConfigs> {
1730         @Override
1731         protected Builder<InterfaceOtherConfigs> builder() {
1732             return new InterfaceOtherConfigsBuilder();
1733         }
1734
1735         @Override
1736         protected void setKey(Builder<InterfaceOtherConfigs> builder, String key) {
1737             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key);
1738         }
1739
1740         @Override
1741         protected void setValue(Builder<InterfaceOtherConfigs> builder, String value) {
1742             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value);
1743         }
1744     }
1745
1746     private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder<PortOtherConfigs> {
1747         @Override
1748         protected Builder<PortOtherConfigs> builder() {
1749             return new PortOtherConfigsBuilder();
1750         }
1751
1752         @Override
1753         protected void setKey(Builder<PortOtherConfigs> builder, String key) {
1754             ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key);
1755         }
1756
1757         @Override
1758         protected void setValue(Builder<PortOtherConfigs> builder, String value) {
1759             ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value);
1760         }
1761     }
1762
1763     private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder<BridgeOtherConfigs> {
1764         @Override
1765         protected Builder<BridgeOtherConfigs> builder() {
1766             return new BridgeOtherConfigsBuilder();
1767         }
1768
1769         @Override
1770         protected void setKey(Builder<BridgeOtherConfigs> builder, String key) {
1771             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key);
1772         }
1773
1774         @Override
1775         protected void setValue(Builder<BridgeOtherConfigs> builder, String value) {
1776             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value);
1777         }
1778     }
1779
1780     private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder<BridgeExternalIds> {
1781         @Override
1782         protected Builder<BridgeExternalIds> builder() {
1783             return new BridgeExternalIdsBuilder();
1784         }
1785
1786         @Override
1787         protected void setKey(Builder<BridgeExternalIds> builder, String key) {
1788             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key);
1789         }
1790
1791         @Override
1792         protected void setValue(Builder<BridgeExternalIds> builder, String value) {
1793             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
1794         }
1795     }
1796
1797     /*
1798      * Generates the test cases involved in testing key-value-based data.  See inline comments for descriptions of
1799      * the particular cases considered.
1800      */
1801     private static <T> List<SouthboundTestCase<T>> generateKeyValueTestCases(
1802             KeyValueBuilder<T> builder, String testName) {
1803         List<SouthboundTestCase<T>> testCases = new ArrayList<>();
1804
1805         final String GOOD_KEY = "GoodKey";
1806         final String GOOD_VALUE = "GoodValue";
1807         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1808
1809         final String idKey = testName + "Key";
1810         final String idValue = testName + "Value";
1811
1812         // Test Case 1:  TestOne
1813         // Test Type:    Positive
1814         // Description:  Create a termination point with one value
1815         // Expected:     A port is created with the single value specified below
1816         final String testOneName = "TestOne" + testName;
1817         testCases.add(new SouthboundTestCaseBuilder<T>()
1818                 .name(testOneName)
1819                 .input(builder.build(testOneName, idKey, idValue))
1820                 .expectInputAsOutput()
1821                 .build());
1822
1823         // Test Case 2:  TestFive
1824         // Test Type:    Positive
1825         // Description:  Create a termination point with multiple (five) values
1826         // Expected:     A port is created with the five values specified below
1827         final String testFiveName = "TestFive" + testName;
1828         builder.reset();
1829         testCases.add(new SouthboundTestCaseBuilder<T>()
1830                 .name(testFiveName)
1831                 .input(
1832                         builder.build(testFiveName, idKey, idValue),
1833                         builder.build(testFiveName, idKey, idValue),
1834                         builder.build(testFiveName, idKey, idValue),
1835                         builder.build(testFiveName, idKey, idValue),
1836                         builder.build(testFiveName, idKey, idValue))
1837                 .expectInputAsOutput()
1838                 .build());
1839
1840         // Test Case 3:  TestOneGoodOneMalformedValue
1841         // Test Type:    Negative
1842         // Description:
1843         //     One perfectly fine input
1844         //        (TestOneGoodOneMalformedValue_GoodKey_1,
1845         //        TestOneGoodOneMalformedValue_GoodValue_1)
1846         //     and one malformed input which only has key specified
1847         //        (TestOneGoodOneMalformedValue_NoValueForKey_2,
1848         //        UNSPECIFIED)
1849         // Expected:     A port is created without any values
1850         final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName;
1851         builder.reset();
1852         testCases.add(new SouthboundTestCaseBuilder<T>()
1853                 .name(testOneGoodOneMalformedValueName)
1854                 .input(
1855                         builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE),
1856                         builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null))
1857                 .expectNoOutput()
1858                 .build());
1859         builder.reset();
1860
1861         return testCases;
1862     }
1863
1864     private static class PortExternalIdsSouthboundHelper implements SouthboundTerminationPointHelper<PortExternalIds> {
1865         @Override
1866         public void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<PortExternalIds> values) {
1867             builder.setPortExternalIds(values);
1868         }
1869
1870         @Override
1871         public List<PortExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
1872             return augmentation.getPortExternalIds();
1873         }
1874     }
1875
1876     private static class InterfaceExternalIdsSouthboundHelper implements
1877             SouthboundTerminationPointHelper<InterfaceExternalIds> {
1878         @Override
1879         public void writeValues(
1880                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceExternalIds> values) {
1881             builder.setInterfaceExternalIds(values);
1882         }
1883
1884         @Override
1885         public List<InterfaceExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
1886             return augmentation.getInterfaceExternalIds();
1887         }
1888     }
1889
1890     private static class OptionsSouthboundHelper implements SouthboundTerminationPointHelper<Options> {
1891         @Override
1892         public void writeValues(
1893                 OvsdbTerminationPointAugmentationBuilder builder, List<Options> values) {
1894             builder.setOptions(values);
1895         }
1896
1897         @Override
1898         public List<Options> readValues(OvsdbTerminationPointAugmentation augmentation) {
1899             return augmentation.getOptions();
1900         }
1901     }
1902
1903     private static class InterfaceOtherConfigsSouthboundHelper implements
1904             SouthboundTerminationPointHelper<InterfaceOtherConfigs> {
1905         @Override
1906         public void writeValues(
1907                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceOtherConfigs> values) {
1908             builder.setInterfaceOtherConfigs(values);
1909         }
1910
1911         @Override
1912         public List<InterfaceOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
1913             return augmentation.getInterfaceOtherConfigs();
1914         }
1915     }
1916
1917     private static class PortOtherConfigsSouthboundHelper implements
1918             SouthboundTerminationPointHelper<PortOtherConfigs> {
1919         @Override
1920         public void writeValues(
1921                 OvsdbTerminationPointAugmentationBuilder builder, List<PortOtherConfigs> values) {
1922             builder.setPortOtherConfigs(values);
1923         }
1924
1925         @Override
1926         public List<PortOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
1927             return augmentation.getPortOtherConfigs();
1928         }
1929     }
1930
1931     private static class BridgeExternalIdsSouthboundHelper implements SouthboundBridgeHelper<BridgeExternalIds> {
1932         @Override
1933         public void writeValues(
1934                 OvsdbBridgeAugmentationBuilder builder, List<BridgeExternalIds> values) {
1935             builder.setBridgeExternalIds(values);
1936         }
1937
1938         @Override
1939         public List<BridgeExternalIds> readValues(OvsdbBridgeAugmentation augmentation) {
1940             return augmentation.getBridgeExternalIds();
1941         }
1942     }
1943
1944     private static class BridgeOtherConfigsSouthboundHelper implements SouthboundBridgeHelper<BridgeOtherConfigs> {
1945         @Override
1946         public void writeValues(
1947                 OvsdbBridgeAugmentationBuilder builder, List<BridgeOtherConfigs> values) {
1948             builder.setBridgeOtherConfigs(values);
1949         }
1950
1951         @Override
1952         public List<BridgeOtherConfigs> readValues(OvsdbBridgeAugmentation augmentation) {
1953             return augmentation.getBridgeOtherConfigs();
1954         }
1955     }
1956 }