4014f45d66877e9c8158f669bc593b8fd66bfa9a
[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.propagateSystemProperties;
15 import static org.ops4j.pax.exam.CoreOptions.vmOption;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
17 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
18
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Method;
21 import java.net.InetAddress;
22 import java.net.UnknownHostException;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Properties;
28 import java.util.Set;
29
30 import javax.annotation.Nullable;
31 import javax.inject.Inject;
32
33 import org.junit.After;
34 import org.junit.Assert;
35 import org.junit.Assume;
36 import org.junit.Before;
37 import org.junit.Ignore;
38 import org.junit.Test;
39 import org.junit.internal.AssumptionViolatedException;
40 import org.junit.runner.RunWith;
41 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
42 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
43 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
44 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
45 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
46 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
47 import org.opendaylight.ovsdb.lib.OvsdbClient;
48 import org.opendaylight.ovsdb.lib.notation.Version;
49 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
50 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
51 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
52 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
53 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
54 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
55 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeBase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIds;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIdsBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.Mappings;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.MappingsBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListKey;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldp;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldpBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
126 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
127 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
128 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
129 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
130 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
131 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
132 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
133 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
134 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
135 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
136 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
137 import org.opendaylight.yangtools.concepts.Builder;
138 import org.opendaylight.yangtools.yang.binding.DataObject;
139 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
140 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
141 import org.ops4j.pax.exam.Configuration;
142 import org.ops4j.pax.exam.Option;
143 import org.ops4j.pax.exam.junit.PaxExam;
144 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
145 import org.ops4j.pax.exam.options.MavenUrlReference;
146 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
147 import org.ops4j.pax.exam.spi.reactors.PerClass;
148 import org.osgi.framework.BundleContext;
149 import org.slf4j.Logger;
150 import org.slf4j.LoggerFactory;
151
152 import com.google.common.collect.ImmutableBiMap;
153 import com.google.common.collect.ImmutableList;
154 import com.google.common.collect.Lists;
155 import com.google.common.collect.Sets;
156
157 /**
158  * Integration tests for southbound-impl
159  *
160  * @author Sam Hague (shague@redhat.com)
161  */
162 @RunWith(PaxExam.class)
163 @ExamReactorStrategy(PerClass.class)
164 public class SouthboundIT extends AbstractMdsalTestBase {
165     private static final String NETDEV_DP_TYPE = "netdev";
166     private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
167     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
168     private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
169     private static final String FORMAT_STR = "%s_%s_%d";
170     private static final Version AUTOATTACH_FROM_VERSION = Version.fromString("7.11.2");
171     private static String addressStr;
172     private static int portNumber;
173     private static String connectionType;
174     private static boolean setup = false;
175     private static MdsalUtils mdsalUtils = null;
176     private static Node ovsdbNode;
177     private static int testMethodsRemaining;
178     private static DataBroker dataBroker;
179     private static Version schemaVersion;
180     private static OvsdbClient ovsdbClient;
181     private static DatabaseSchema dbSchema;
182
183     @Inject
184     private BundleContext bundleContext;
185
186     private static final NotifyingDataChangeListener CONFIGURATION_LISTENER =
187             new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION);
188     private static final NotifyingDataChangeListener OPERATIONAL_LISTENER =
189             new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL);
190
191     private static class NotifyingDataChangeListener implements DataChangeListener {
192         private final LogicalDatastoreType type;
193         private final Set<InstanceIdentifier<?>> createdIids = new HashSet<>();
194         private final Set<InstanceIdentifier<?>> removedIids = new HashSet<>();
195         private final Set<InstanceIdentifier<?>> updatedIids = new HashSet<>();
196         private final InstanceIdentifier<?> iid;
197         private final int RETRY_WAIT = 100;
198
199         private NotifyingDataChangeListener(LogicalDatastoreType type) {
200             this.type = type;
201             this.iid = null;
202         }
203
204         private NotifyingDataChangeListener(LogicalDatastoreType type, InstanceIdentifier<?> iid) {
205             this.type = type;
206             this.iid = iid;
207         }
208
209         @Override
210         public void onDataChanged(
211                 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
212             LOG.info("{} DataChanged: created {}", type, asyncDataChangeEvent.getCreatedData().keySet());
213             LOG.info("{} DataChanged: removed {}", type, asyncDataChangeEvent.getRemovedPaths());
214             LOG.info("{} DataChanged: updated {}", type, asyncDataChangeEvent.getUpdatedData().keySet());
215             createdIids.addAll(asyncDataChangeEvent.getCreatedData().keySet());
216             removedIids.addAll(asyncDataChangeEvent.getRemovedPaths());
217             updatedIids.addAll(asyncDataChangeEvent.getUpdatedData().keySet());
218             // Handled managed iids
219             for (DataObject obj : asyncDataChangeEvent.getCreatedData().values()) {
220                 if (obj instanceof ManagedNodeEntry) {
221                     ManagedNodeEntry managedNodeEntry = (ManagedNodeEntry) obj;
222                     LOG.info("{} DataChanged: created managed {}", managedNodeEntry.getBridgeRef().getValue());
223                     createdIids.add(managedNodeEntry.getBridgeRef().getValue());
224                 }
225             }
226             synchronized(this) {
227                 notifyAll();
228             }
229         }
230
231         public boolean isCreated(InstanceIdentifier<?> iid) {
232             return createdIids.remove(iid);
233         }
234
235         public boolean isRemoved(InstanceIdentifier<?> iid) {
236             return removedIids.remove(iid);
237         }
238
239         public boolean isUpdated(InstanceIdentifier<?> iid) {
240             return updatedIids.remove(iid);
241         }
242
243         public void clear() {
244             createdIids.clear();
245             removedIids.clear();
246             updatedIids.clear();
247         }
248
249         public void registerDataChangeListener() {
250             dataBroker.registerDataChangeListener(type, iid, this, AsyncDataBroker.DataChangeScope.SUBTREE);
251         }
252
253         public void waitForCreation(long timeout) throws InterruptedException {
254             synchronized (this) {
255                 long _start = System.currentTimeMillis();
256                 LOG.info("Waiting for {} DataChanged creation on {}", type, iid);
257                 while (!isCreated(iid) && (System.currentTimeMillis() - _start) < timeout) {
258                     wait(RETRY_WAIT);
259                 }
260                 LOG.info("Woke up, waited {}ms for creation of {}", (System.currentTimeMillis() - _start), iid);
261             }
262         }
263
264         public void waitForDeletion(long timeout) throws InterruptedException {
265             synchronized (this) {
266                 long _start = System.currentTimeMillis();
267                 LOG.info("Waiting for {} DataChanged deletion on {}", type, iid);
268                 while (!isRemoved(iid) && (System.currentTimeMillis() - _start) < timeout) {
269                     wait(RETRY_WAIT);
270                 }
271                 LOG.info("Woke up, waited {}ms for deletion of {}", (System.currentTimeMillis() - _start), iid);
272             }
273         }
274
275         public void waitForUpdate(long timeout) throws InterruptedException {
276             synchronized (this) {
277                 long _start = System.currentTimeMillis();
278                 LOG.info("Waiting for {} DataChanged update on {}", type, iid);
279                 while (!isUpdated(iid) && (System.currentTimeMillis() - _start) < timeout) {
280                     wait(RETRY_WAIT);
281                 }
282                 LOG.info("Woke up, waited {}ms for update of {}", (System.currentTimeMillis() - _start), iid);
283             }
284         }
285
286     }
287
288     @Configuration
289     public Option[] config() {
290         Option[] options = super.config();
291         Option[] propertyOptions = getPropertiesOptions();
292         Option[] otherOptions = getOtherOptions();
293         Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
294         System.arraycopy(options, 0, combinedOptions, 0, options.length);
295         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
296         System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
297                 otherOptions.length);
298         return combinedOptions;
299     }
300
301     private Option[] getOtherOptions() {
302         return new Option[] {
303                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
304                 keepRuntimeFolder()
305         };
306     }
307
308     @Override
309     public String getKarafDistro() {
310         return maven()
311                 .groupId("org.opendaylight.ovsdb")
312                 .artifactId("southbound-karaf")
313                 .versionAsInProject()
314                 .type("zip")
315                 .getURL();
316     }
317
318     @Override
319     public MavenUrlReference getFeatureRepo() {
320         return maven()
321                 .groupId("org.opendaylight.ovsdb")
322                 .artifactId("southbound-features")
323                 .classifier("features")
324                 .type("xml")
325                 .versionAsInProject();
326     }
327
328     @Override
329     public String getFeatureName() {
330         return "odl-ovsdb-southbound-test";
331     }
332
333     protected String usage() {
334         return "Integration Test needs a valid connection configuration as follows :\n"
335                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
336                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
337     }
338
339     @Override
340     public Option getLoggingOption() {
341         return composite(
342                 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
343                         "log4j.logger.org.opendaylight.ovsdb",
344                         LogLevelOption.LogLevel.TRACE.name()),
345                 super.getLoggingOption());
346     }
347
348     private Option[] getPropertiesOptions() {
349         Properties props = new Properties(System.getProperties());
350         String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
351                 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
352         String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
353                 SouthboundITConstants.DEFAULT_SERVER_PORT);
354         String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
355                 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
356
357         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
358                 connectionType, addressStr, portStr);
359
360         return new Option[] {
361                 propagateSystemProperties(
362                         SouthboundITConstants.SERVER_IPADDRESS,
363                         SouthboundITConstants.SERVER_PORT,
364                         SouthboundITConstants.CONNECTION_TYPE),
365                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
366                         SouthboundITConstants.SERVER_IPADDRESS, addressStr),
367                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
368                         SouthboundITConstants.SERVER_PORT, portStr),
369                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
370                         SouthboundITConstants.CONNECTION_TYPE, connectionType),
371         };
372     }
373
374     @Before
375     @Override
376     public void setup() throws InterruptedException {
377         if (setup) {
378             LOG.info("Skipping setup, already initialized");
379             return;
380         }
381
382         try {
383             super.setup();
384         } catch (Exception e) {
385             LOG.warn("Failed to setup test", e);
386         }
387         //dataBroker = getSession().getSALService(DataBroker.class);
388         Thread.sleep(3000);
389         dataBroker = SouthboundProvider.getDb();
390         Assert.assertNotNull("db should not be null", dataBroker);
391
392         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
393         String portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
394         try {
395             portNumber = Integer.parseInt(portStr);
396         } catch (NumberFormatException e) {
397             fail("Invalid port number " + portStr + System.lineSeparator() + usage());
398         }
399         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
400
401         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
402                 connectionType, addressStr, portNumber);
403         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
404             if (addressStr == null) {
405                 fail(usage());
406             }
407         }
408
409         mdsalUtils = new MdsalUtils(dataBroker);
410         final ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
411         final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
412         dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
413                 iid, CONFIGURATION_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE);
414         dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
415                 iid, OPERATIONAL_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE);
416
417         ovsdbNode = connectOvsdbNode(connectionInfo);
418         try {
419             ovsdbClient = SouthboundIntegrationTestUtils.getTestConnection(this);
420             assertNotNull("Invalid Client. Check connection params", ovsdbClient);
421
422             dbSchema = ovsdbClient.getSchema(SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA).get();
423             assertNotNull("Invalid dbSchema.", dbSchema);
424             schemaVersion = dbSchema.getVersion();
425             LOG.info("{} schema version = {}", SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA, schemaVersion);
426         } catch (Exception e) {
427             fail("Error accessing schemaVersion in SouthboundIT setUp()." + usage());
428         }
429
430         // Let's count the test methods (we need to use this instead of @AfterClass on teardown() since the latter is
431         // useless with pax-exam)
432         for (Method method : getClass().getMethods()) {
433             boolean testMethod = false;
434             boolean ignoreMethod = false;
435             for (Annotation annotation : method.getAnnotations()) {
436                 if (Test.class.equals(annotation.annotationType())) {
437                     testMethod = true;
438                 }
439                 if (Ignore.class.equals(annotation.annotationType())) {
440                     ignoreMethod = true;
441                 }
442             }
443             if (testMethod && !ignoreMethod) {
444                 testMethodsRemaining++;
445             }
446         }
447         LOG.info("{} test methods to run", testMethodsRemaining);
448
449         setup = true;
450     }
451
452     @After
453     public void teardown() {
454         testMethodsRemaining--;
455         LOG.info("{} test methods remaining", testMethodsRemaining);
456         if (testMethodsRemaining == 0) {
457             try {
458                 disconnectOvsdbNode(getConnectionInfo(addressStr, portNumber));
459             } catch (InterruptedException e) {
460                 LOG.warn("Interrupted while disconnecting", e);
461             }
462         }
463     }
464
465     /**
466      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
467      * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms.
468      *
469      * @throws InterruptedException
470      */
471     @Test
472     public void testPassiveNode() throws InterruptedException {
473         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
474             //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
475             Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
476         }
477     }
478
479     private static ConnectionInfo getConnectionInfo(final String addressStr, final int portNumber) {
480         InetAddress inetAddress = null;
481         try {
482             inetAddress = InetAddress.getByName(addressStr);
483         } catch (UnknownHostException e) {
484             fail("Could not resolve " + addressStr + ": " + e);
485         }
486
487         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
488         PortNumber port = new PortNumber(portNumber);
489
490         final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
491                 .setRemoteIp(address)
492                 .setRemotePort(port)
493                 .build();
494         LOG.info("connectionInfo: {}", connectionInfo);
495         return connectionInfo;
496     }
497
498     @Test
499     public void testNetworkTopology() throws InterruptedException {
500         NetworkTopology networkTopology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION,
501                 InstanceIdentifier.create(NetworkTopology.class));
502         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
503                 networkTopology);
504
505         networkTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
506                 InstanceIdentifier.create(NetworkTopology.class));
507         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
508                 networkTopology);
509     }
510
511     @Test
512     public void testOvsdbTopology() throws InterruptedException {
513         InstanceIdentifier<Topology> path = InstanceIdentifier
514                 .create(NetworkTopology.class)
515                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
516
517         Topology topology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
518         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
519                 topology);
520
521         topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
522
523         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
524                 topology);
525     }
526
527     private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
528         final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
529         Assert.assertTrue(
530                 mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, SouthboundUtils.createNode(connectionInfo)));
531         waitForOperationalCreation(iid);
532         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
533         Assert.assertNotNull(node);
534         LOG.info("Connected to {}", SouthboundUtils.connectionInfoToString(connectionInfo));
535         return node;
536     }
537
538     private void waitForOperationalCreation(InstanceIdentifier<Node> iid) throws InterruptedException {
539         synchronized (OPERATIONAL_LISTENER) {
540             long _start = System.currentTimeMillis();
541             LOG.info("Waiting for OPERATIONAL DataChanged creation on {}", iid);
542             while (!OPERATIONAL_LISTENER.isCreated(
543                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
544                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
545             }
546             LOG.info("Woke up, waited {} for creation of {}", (System.currentTimeMillis() - _start), iid);
547         }
548     }
549
550     private static void waitForOperationalDeletion(InstanceIdentifier<Node> iid) throws InterruptedException {
551         synchronized (OPERATIONAL_LISTENER) {
552             long _start = System.currentTimeMillis();
553             LOG.info("Waiting for OPERATIONAL DataChanged deletion on {}", iid);
554             while (!OPERATIONAL_LISTENER.isRemoved(
555                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
556                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
557             }
558             LOG.info("Woke up, waited {} for deletion of {}", (System.currentTimeMillis() - _start), iid);
559         }
560     }
561
562     private void waitForOperationalUpdate(InstanceIdentifier<Node> iid) throws InterruptedException {
563         synchronized (OPERATIONAL_LISTENER) {
564             long _start = System.currentTimeMillis();
565             LOG.info("Waiting for OPERATIONAL DataChanged update on {}", iid);
566             while (!OPERATIONAL_LISTENER.isUpdated(
567                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
568                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
569             }
570             LOG.info("Woke up, waited {} for update of {}", (System.currentTimeMillis() - _start), iid);
571         }
572     }
573
574     private static void disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
575         final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
576         Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
577         waitForOperationalDeletion(iid);
578         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
579         Assert.assertNull(node);
580         LOG.info("Disconnected from {}", SouthboundUtils.connectionInfoToString(connectionInfo));
581     }
582
583     @Test
584     public void testAddDeleteOvsdbNode() throws InterruptedException {
585         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
586         // At this point we're connected, disconnect and reconnect (the connection will be removed at the very end)
587         disconnectOvsdbNode(connectionInfo);
588         connectOvsdbNode(connectionInfo);
589     }
590
591     @Test
592     public void testDpdkSwitch() throws InterruptedException {
593         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
594         List<DatapathTypeEntry> datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class)
595                 .getDatapathTypeEntry();
596         if (datapathTypeEntries == null) {
597             LOG.info("DPDK not supported on this node.");
598         } else {
599             for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) {
600                 Class<? extends DatapathTypeBase> dpType = dpTypeEntry.getDatapathType();
601                 String dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
602                 LOG.info("dp type is {}", dpTypeStr);
603                 if (dpTypeStr.equals(NETDEV_DP_TYPE)) {
604                     LOG.info("Found a DPDK node; adding a corresponding netdev device");
605                     InstanceIdentifier<Node> bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo,
606                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
607                     NodeId bridgeNodeId = SouthboundUtils.createManagedNodeId(bridgeIid);
608                     try (TestBridge testBridge = new TestBridge(connectionInfo, bridgeIid,
609                             SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null, true, dpType, null, null,
610                             null)) {
611                         // Verify that the device is netdev
612                         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
613                         Assert.assertNotNull(bridge);
614                         Assert.assertEquals(dpType, bridge.getDatapathType());
615
616                         // Add port for all dpdk interface types (dpdkvhost not supported in existing dpdk ovs)
617                         List<String> dpdkTypes = new ArrayList<String>();
618                         dpdkTypes.add("dpdk");
619                         dpdkTypes.add("dpdkr");
620                         dpdkTypes.add("dpdkvhostuser");
621                         //dpdkTypes.add("dpdkvhost");
622
623                         for (String dpdkType : dpdkTypes) {
624                             String testPortname = "test"+dpdkType+"port";
625                             LOG.info("DPDK portname and type is {}, {}", testPortname, dpdkType);
626                             Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
627                                     .get(dpdkType);
628                             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationpointBuilder =
629                                     createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(testPortname,
630                                             dpdkIfType);
631                             Assert.assertTrue(
632                                     addTerminationPoint(bridgeNodeId, testPortname, ovsdbTerminationpointBuilder));
633                         }
634
635                         // Verify that all DPDK ports are created
636                         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
637                         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
638                                 terminationPointIid);
639                         Assert.assertNotNull(terminationPointNode);
640
641                         // Verify that each termination point has the specific DPDK ifType
642                         for (String dpdkType : dpdkTypes) {
643                             String testPortname = "test"+dpdkType+"port";
644                             Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
645                                     .get(dpdkType);
646                             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
647                             for (TerminationPoint terminationPoint : terminationPoints) {
648                                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
649                                         .getAugmentation(OvsdbTerminationPointAugmentation.class);
650                                 if (ovsdbTerminationPointAugmentation.getName().equals(testPortname)) {
651                                     Class<? extends InterfaceTypeBase> opPort = ovsdbTerminationPointAugmentation
652                                             .getInterfaceType();
653                                     Assert.assertEquals(dpdkIfType, opPort);
654                                 }
655                             }
656                         }
657                     }
658                 }
659                 break;
660             }
661         }
662     }
663
664     @Test
665     public void testOvsdbNodeOvsVersion() throws InterruptedException {
666         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
667         Assert.assertNotNull(ovsdbNodeAugmentation);
668         assertNotNull(ovsdbNodeAugmentation.getOvsVersion());
669     }
670
671     @Test
672     public void testOpenVSwitchOtherConfig() throws InterruptedException {
673         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
674         Assert.assertNotNull(ovsdbNodeAugmentation);
675         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
676         if (otherConfigsList != null) {
677             for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
678                 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
679                     LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
680                     break;
681                 } else {
682                     LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
683                 }
684             }
685         } else {
686             LOG.info("other_config is not present");
687         }
688     }
689
690     @Test
691     public void testOvsdbBridgeControllerInfo() throws InterruptedException {
692         ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portNumber);
693         String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
694         assertNotNull("Failed to get controller target", controllerTarget);
695         List<ControllerEntry> setControllerEntry = createControllerEntry(controllerTarget);
696         Uri setUri = new Uri(controllerTarget);
697         try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
698                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
699                 setControllerEntry, null)) {
700             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
701             Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
702             Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
703                     bridge.getControllerEntry());
704             List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
705             for (ControllerEntry entry : getControllerEntries) {
706                 if (entry.getTarget() != null) {
707                     Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
708                 }
709             }
710         }
711     }
712
713     private List<ControllerEntry> createControllerEntry(String controllerTarget) {
714         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
715         controllerEntriesList.add(new ControllerEntryBuilder()
716                 .setTarget(new Uri(controllerTarget))
717                 .build());
718         return controllerEntriesList;
719     }
720
721     private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
722                               final ConnectionInfo connectionInfo) {
723         InstanceIdentifier<Node> connectionNodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo);
724         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
725     }
726
727     private static List<ProtocolEntry> createMdsalProtocols() {
728         List<ProtocolEntry> protocolList = new ArrayList<>();
729         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
730                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
731         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
732         return protocolList;
733     }
734
735     private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() {
736         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder =
737                 new OvsdbTerminationPointAugmentationBuilder();
738         ovsdbTerminationPointAugmentationBuilder.setInterfaceType(
739                 new InterfaceTypeEntryBuilder()
740                         .setInterfaceType(
741                                 SouthboundMapper.createInterfaceType("internal"))
742                         .build().getInterfaceType());
743         return ovsdbTerminationPointAugmentationBuilder;
744     }
745
746     private OvsdbTerminationPointAugmentationBuilder createGenericDpdkOvsdbTerminationPointAugmentationBuilder(
747             final String portName) {
748         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
749                 createGenericOvsdbTerminationPointAugmentationBuilder();
750         ovsdbTerminationBuilder.setName(portName);
751         Class<? extends InterfaceTypeBase> ifType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
752                 .get("dpdk");
753         ovsdbTerminationBuilder.setInterfaceType(ifType);
754         return ovsdbTerminationBuilder;
755     }
756
757     private OvsdbTerminationPointAugmentationBuilder createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(
758             String testPortname,Class<? extends InterfaceTypeBase> dpdkIfType) {
759         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
760                 createGenericOvsdbTerminationPointAugmentationBuilder();
761         ovsdbTerminationBuilder.setName(testPortname);
762         ovsdbTerminationBuilder.setInterfaceType(dpdkIfType);
763         return ovsdbTerminationBuilder;
764     }
765
766     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
767                                         final OvsdbTerminationPointAugmentationBuilder
768                                                 ovsdbTerminationPointAugmentationBuilder)
769             throws InterruptedException {
770
771         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
772         NodeBuilder portNodeBuilder = new NodeBuilder();
773         NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid);
774         portNodeBuilder.setNodeId(portNodeId);
775         TerminationPointBuilder entry = new TerminationPointBuilder();
776         entry.setKey(new TerminationPointKey(new TpId(portName)));
777         entry.addAugmentation(
778                 OvsdbTerminationPointAugmentation.class,
779                 ovsdbTerminationPointAugmentationBuilder.build());
780         portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build()));
781         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
782                 portIid, portNodeBuilder.build());
783         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
784         return result;
785     }
786
787     private static class TestBridge implements AutoCloseable {
788         private final ConnectionInfo connectionInfo;
789         private final String bridgeName;
790
791         /**
792          * Creates a test bridge which can be automatically removed when no longer necessary.
793          *
794          * @param connectionInfo The connection information.
795          * @param bridgeIid The bridge identifier; if {@code null}, one is created based on {@code bridgeName}.
796          * @param bridgeName The bridge name; must be provided.
797          * @param bridgeNodeId The bridge node identifier; if {@code null}, one is created based on {@code bridgeIid}.
798          * @param setProtocolEntries {@code true} to set default protocol entries for the bridge.
799          * @param failMode The fail mode to set for the bridge.
800          * @param setManagedBy {@code true} to specify {@code setManagedBy} for the bridge.
801          * @param dpType The datapath type.
802          * @param externalIds The external identifiers if any.
803          * @param otherConfigs The other configuration items if any.
804          */
805         public TestBridge(final ConnectionInfo connectionInfo, @Nullable InstanceIdentifier<Node> bridgeIid,
806                                   final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
807                                   final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
808                                   @Nullable final Class<? extends DatapathTypeBase> dpType,
809                                   @Nullable final List<BridgeExternalIds> externalIds,
810                                   @Nullable final List<ControllerEntry> controllerEntries,
811                                   @Nullable final List<BridgeOtherConfigs> otherConfigs) {
812             this.connectionInfo = connectionInfo;
813             this.bridgeName = bridgeName;
814             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
815             if (bridgeIid == null) {
816                 bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
817             }
818             if (bridgeNodeId == null) {
819                 bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
820             }
821             bridgeNodeBuilder.setNodeId(bridgeNodeId);
822             OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
823             ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
824             if (setProtocolEntries) {
825                 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
826             }
827             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
828             if (setManagedBy) {
829                 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
830             }
831             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
832             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
833             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
834             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
835             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
836             LOG.debug("Built with the intent to store bridge data {}", ovsdbBridgeAugmentationBuilder.toString());
837             Assert.assertTrue(
838                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build()));
839             try {
840                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
841             } catch (InterruptedException e) {
842                 LOG.warn("Sleep interrupted while waiting for bridge creation (bridge {})", bridgeName, e);
843             }
844         }
845
846         public TestBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
847             this(connectionInfo, null, bridgeName, null, true,
848                     SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
849         }
850
851         @Override
852         public void close() {
853             final InstanceIdentifier<Node> iid =
854                     SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
855             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
856             try {
857                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
858             } catch (InterruptedException e) {
859                 LOG.warn("Sleep interrupted while waiting for bridge deletion (bridge {})", bridgeName, e);
860             }
861         }
862     }
863
864     private static class TestAutoAttach implements AutoCloseable {
865         private final ConnectionInfo connectionInfo;
866         private final Uri autoattachId;
867         private final Uri bridgeId;
868
869         public TestAutoAttach (final ConnectionInfo connectionInfo,
870                 final Uri autoattachId,
871                 final Uri bridgeId,
872                 @Nullable final String systemName,
873                 @Nullable final String systemDescription,
874                 @Nullable final List<Mappings> mappings,
875                 @Nullable final List<AutoattachExternalIds> externalIds) {
876             this.connectionInfo = connectionInfo;
877             this.autoattachId = autoattachId;
878             this.bridgeId = bridgeId;
879
880             Autoattach aaEntry = new AutoattachBuilder()
881                     .setAutoattachId(autoattachId)
882                     .setBridgeId(bridgeId)
883                     .setSystemName(systemName)
884                     .setSystemDescription(systemDescription)
885                     .setMappings(mappings)
886                     .setAutoattachExternalIds(externalIds)
887                     .build();
888             InstanceIdentifier<Autoattach> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
889                     .augmentation(OvsdbNodeAugmentation.class)
890                     .child(Autoattach.class, aaEntry.getKey());
891             final NotifyingDataChangeListener aaOperationalListener =
892                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid);
893             aaOperationalListener.registerDataChangeListener();
894
895             Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, aaEntry));
896             try {
897                 aaOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT);
898             } catch (InterruptedException e) {
899                 LOG.warn("Sleep interrupted while waiting for queue {}", iid, e);
900             }
901         }
902         @Override
903         public void close() {
904             final InstanceIdentifier<Autoattach> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
905                     .augmentation(OvsdbNodeAugmentation.class)
906                     .child(Autoattach.class, new AutoattachKey(this.autoattachId));
907             final NotifyingDataChangeListener aaOperationalListener =
908                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid);
909             aaOperationalListener.registerDataChangeListener();
910
911             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
912             try {
913                 aaOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT);
914             } catch (InterruptedException e) {
915                 LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", iid, e);
916             }
917         }
918     }
919
920     @Test
921     public void testCRUDAutoAttach() throws InterruptedException {
922         final boolean isOldSchema = schemaVersion.compareTo(AUTOATTACH_FROM_VERSION) < 0;
923
924         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
925         String testAutoattachId = new String("testAutoattachEntry");
926         String testSystemName = new String("testSystemName");
927         String testSystemDescription = new String("testSystemDescription");
928         String testAutoattachExternalKey = new String("testAutoattachExternalKey");
929         String testAutoattachExternalValue = new String("testAutoattachExternalValue");
930
931         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
932             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
933             Assert.assertNotNull(bridge);
934
935             // CREATE: Create Autoattach table
936             NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
937                     connectionInfo, bridge.getBridgeName()));
938             String bridgeId = nodeId.getValue();
939             try(TestAutoAttach testAutoattach = new TestAutoAttach(connectionInfo, new Uri(testAutoattachId),
940                     new Uri(bridgeId), testSystemName, testSystemDescription, null, null)) {
941                 // READ: Read md-sal operational datastore to see if the AutoAttach table was created
942                 // and if Bridge table was updated with AutoAttach Uuid
943                 OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
944                         LogicalDatastoreType.OPERATIONAL);
945                 Autoattach operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId));
946
947                 // skip tests after verifying that Autoattach doesn't break with unsupported schema
948                 Assume.assumeFalse(isOldSchema);
949
950                 // FIXME: Remove once CRUD is supported
951                 Assume.assumeFalse(operAa == null);
952
953                 Assert.assertNotNull(operAa);
954                 Assert.assertEquals(testSystemName, operAa.getSystemName());
955                 bridge = getBridge(connectionInfo);
956                 Uuid aaUuid = new Uuid(operAa.getAutoattachUuid().getValue());
957                 Assert.assertEquals(aaUuid, bridge.getAutoAttach());
958
959                 // UPDATE: Update mappings column of AutoAttach table that was created
960                 List<Mappings> mappings = ImmutableList.of(new MappingsBuilder().setMappingsKey(100L).setMappingsValue(200).build());
961                 Autoattach updatedAa = new AutoattachBuilder()
962                         .setAutoattachId(new Uri(testAutoattachId))
963                         .setMappings(mappings)
964                         .build();
965                 InstanceIdentifier<Autoattach> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
966                         .augmentation(OvsdbNodeAugmentation.class)
967                         .child(Autoattach.class, updatedAa.getKey());
968                 final NotifyingDataChangeListener aaOperationalListener =
969                         new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid);
970                 aaOperationalListener.registerDataChangeListener();
971                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa));
972                 aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
973
974                 // UPDATE: Update external_ids column of AutoAttach table that was created
975                 List<AutoattachExternalIds> externalIds = new ArrayList<>();
976                 externalIds.add(new AutoattachExternalIdsBuilder()
977                         .setAutoattachExternalIdKey(testAutoattachExternalKey)
978                         .setAutoattachExternalIdValue(testAutoattachExternalValue)
979                         .build());
980                 updatedAa = new AutoattachBuilder()
981                         .setAutoattachId(new Uri(testAutoattachId))
982                         .setAutoattachExternalIds(externalIds)
983                         .build();
984                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa));
985                 aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
986
987                 // READ: Read the updated AutoAttach table for latest mappings and external_ids column value
988                 ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
989                         LogicalDatastoreType.OPERATIONAL);
990                 operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId));
991                 Assert.assertNotNull(operAa);
992                 List<Mappings> operMappingsList = operAa.getMappings();
993                 for (Mappings operMappings: operMappingsList) {
994                     Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsKey(), operMappings.getMappingsKey());
995                     Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsValue(), operMappings.getMappingsValue());
996                 }
997                 List<AutoattachExternalIds> operExternalIds = operAa.getAutoattachExternalIds();
998                 externalIds.add(new AutoattachExternalIdsBuilder()
999                         .setAutoattachExternalIdKey(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY)
1000                         .setAutoattachExternalIdValue(operAa.getAutoattachId().getValue())
1001                         .build());
1002                 for (AutoattachExternalIds operExternalId : operExternalIds) {
1003                     Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdKey(),
1004                             operExternalId.getAutoattachExternalIdKey());
1005                     Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdValue(),
1006                             operExternalId.getAutoattachExternalIdValue());
1007                 }
1008
1009                 // DELETE: Delete AutoAttach table
1010                 Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
1011                 aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
1012                 ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
1013                         LogicalDatastoreType.OPERATIONAL);
1014                 operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId));
1015                 Assert.assertNull(operAa);
1016             } catch (AssumptionViolatedException e) {
1017                 LOG.warn("Skipped test for Autoattach due to unsupported schema", e);
1018             } catch (Exception e) {
1019                 fail("Unexpected exception in CRUD test for Autoattach table for schema:" + schemaVersion.toString() +". " + e);
1020             }
1021         }
1022     }
1023
1024     private Autoattach getAutoAttach(OvsdbNodeAugmentation ovsdbNodeAugmentation, Uri uri) {
1025         if (ovsdbNodeAugmentation.getAutoattach() != null
1026                 && !ovsdbNodeAugmentation.getAutoattach().isEmpty()) {
1027             for (Autoattach aa : ovsdbNodeAugmentation.getAutoattach()) {
1028                 if (aa.getKey().getAutoattachId().equals(uri)) {
1029                     return aa;
1030                 }
1031             }
1032         }
1033         return null;
1034     }
1035
1036     private static class TestQos implements AutoCloseable {
1037         private final ConnectionInfo connectionInfo;
1038         private final Uri qosId;
1039
1040         /**
1041          * Creates a test qos entry which can be automatically removed when no longer necessary.
1042          *
1043          * @param connectionInfo The connection information.
1044          * @param qosId The Qos identifier.
1045          * @param qosType The qos type.
1046          * @param externalIds The external identifiers if any.
1047          * @param otherConfigs The other configuration items if any.
1048          */
1049         public TestQos(final ConnectionInfo connectionInfo,
1050                                   final Uri qosId,
1051                                   final Class<? extends QosTypeBase> qosType,
1052                                   @Nullable final List<QosExternalIds> externalIds,
1053                                   @Nullable final List<QosOtherConfig> otherConfigs) {
1054             this.connectionInfo = connectionInfo;
1055             this.qosId = qosId;
1056
1057             QosEntries qosEntry = new QosEntriesBuilder()
1058                 .setQosId(qosId)
1059                 .setQosType(qosType)
1060                 .setQosExternalIds(externalIds)
1061                 .setQosOtherConfig(otherConfigs)
1062                 .build();
1063             InstanceIdentifier<QosEntries> qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
1064                     .augmentation(OvsdbNodeAugmentation.class)
1065                     .child(QosEntries.class, qosEntry.getKey());
1066             final NotifyingDataChangeListener qosOperationalListener =
1067                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid);
1068             qosOperationalListener.registerDataChangeListener();
1069
1070             Assert.assertTrue(
1071                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1072                     qeIid, qosEntry));
1073
1074             try {
1075                 qosOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT);
1076             } catch (InterruptedException e) {
1077                 LOG.warn("Sleep interrupted while waiting for queue {}", qeIid, e);
1078             }
1079
1080         }
1081
1082         @Override
1083         public void close() {
1084             final InstanceIdentifier<QosEntries> qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
1085                     .augmentation(OvsdbNodeAugmentation.class)
1086                     .child(QosEntries.class, new QosEntriesKey(this.qosId));
1087             final NotifyingDataChangeListener qosOperationalListener =
1088                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid);
1089             qosOperationalListener.registerDataChangeListener();
1090
1091             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qeIid));
1092             try {
1093                 qosOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT);
1094             } catch (InterruptedException e) {
1095                 LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", qeIid, e);
1096             }
1097         }
1098     }
1099
1100     private static class TestQueue implements AutoCloseable {
1101         private final ConnectionInfo connectionInfo;
1102         private final Uri queueId;
1103
1104         /**
1105          * Creates a test queue entry which can be automatically removed when no longer necessary.
1106          *
1107          * @param connectionInfo The connection information.
1108          * @param queueId The Queue identifier.
1109          * @param queueDscp The queue dscp value.
1110          * @param externalIds The external identifiers if any.
1111          * @param otherConfigs The other configuration items if any.
1112          */
1113         public TestQueue(final ConnectionInfo connectionInfo,
1114                                   final Uri queueId,
1115                                   final Short queueDscp,
1116                                   @Nullable final List<QueuesExternalIds> externalIds,
1117                                   @Nullable final List<QueuesOtherConfig> otherConfigs) {
1118             this.connectionInfo = connectionInfo;
1119             this.queueId = queueId;
1120
1121             Queues queue = new QueuesBuilder()
1122                 .setQueueId(queueId)
1123                 .setDscp(queueDscp)
1124                 .setQueuesExternalIds(externalIds)
1125                 .setQueuesOtherConfig(otherConfigs)
1126                 .build();
1127             InstanceIdentifier<Queues> qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
1128                     .augmentation(OvsdbNodeAugmentation.class)
1129                     .child(Queues.class, queue.getKey());
1130             final NotifyingDataChangeListener queueOperationalListener =
1131                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid);
1132             queueOperationalListener.registerDataChangeListener();
1133
1134             Assert.assertTrue(
1135                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1136                     qIid, queue));
1137
1138             try {
1139                 queueOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT);
1140             } catch (InterruptedException e) {
1141                 LOG.warn("Sleep interrupted while waiting for queue {}", queueId, e);
1142             }
1143         }
1144
1145         @Override
1146         public void close() {
1147             InstanceIdentifier<Queues> qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
1148                     .augmentation(OvsdbNodeAugmentation.class)
1149                     .child(Queues.class, new QueuesKey(this.queueId));
1150             final NotifyingDataChangeListener queueOperationalListener =
1151                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid);
1152             queueOperationalListener.registerDataChangeListener();
1153
1154             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qIid));
1155             try {
1156                 queueOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT);
1157             } catch (InterruptedException e) {
1158                 LOG.warn("Sleep interrupted while waiting for queue deletion (queue {})", queueId, e);
1159             }
1160         }
1161     }
1162
1163     private OvsdbNodeAugmentation getOvsdbNode(ConnectionInfo connectionInfo, LogicalDatastoreType store) {
1164         InstanceIdentifier<Node> nodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
1165         Node node = mdsalUtils.read(store, nodeIid);
1166         Assert.assertNotNull(node);
1167         OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
1168         Assert.assertNotNull(ovsdbNodeAugmentation);
1169         return ovsdbNodeAugmentation;
1170     }
1171
1172     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
1173         return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1174     }
1175
1176     /**
1177      * Extract the <code>store</code> type data store contents for the particular bridge identified by
1178      * <code>bridgeName</code>.
1179      *
1180      * @param connectionInfo the connection information
1181      * @param bridgeName the bridge name
1182      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
1183      * @return <code>store</code> type data store contents
1184      */
1185     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
1186                                               LogicalDatastoreType store) {
1187         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
1188         Assert.assertNotNull(bridgeNode);
1189         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
1190         Assert.assertNotNull(ovsdbBridgeAugmentation);
1191         return ovsdbBridgeAugmentation;
1192     }
1193
1194     /**
1195      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
1196      * identified by <code>bridgeName</code>
1197      *
1198      * @param connectionInfo the connection information
1199      * @param bridgeName the bridge name
1200      * @see <code>SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
1201      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
1202      */
1203     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
1204         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
1205     }
1206
1207     /**
1208      * Extract the node contents from <code>store</code> type data store for the
1209      * bridge identified by <code>bridgeName</code>
1210      *
1211      * @param connectionInfo the connection information
1212      * @param bridgeName the bridge name
1213      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
1214      * @return <code>store</code> type data store contents
1215      */
1216     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
1217         InstanceIdentifier<Node> bridgeIid =
1218                 SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
1219         return mdsalUtils.read(store, bridgeIid);
1220     }
1221
1222     /**
1223      * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
1224      * bridge identified by <code>bridgeName</code>
1225      *
1226      * @param connectionInfo the connection information
1227      * @param bridgeName the bridge name
1228      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
1229      */
1230     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
1231         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
1232     }
1233
1234     @Test
1235     public void testAddDeleteBridge() throws InterruptedException {
1236         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1237
1238         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1239             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1240             Assert.assertNotNull(bridge);
1241             LOG.info("bridge: {}", bridge);
1242         }
1243     }
1244
1245     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
1246         return SouthboundUtils.createInstanceIdentifier(connectionInfo, bridge.getBridgeName());
1247     }
1248
1249     /**
1250      * Extracts the <code>TerminationPointAugmentation</code> for the <code>index</code> <code>TerminationPoint</code>
1251      * on <code>bridgeName</code>
1252      *
1253      * @param connectionInfo the connection information
1254      * @param bridgeName the bridge name
1255      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
1256      * @param index the index we're interested in
1257      * @return the augmentation (or {@code null} if none)
1258      */
1259     private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
1260             ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) {
1261
1262         List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
1263         if (tpList == null) {
1264             return null;
1265         }
1266         return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class);
1267     }
1268
1269     @Test
1270     public void testCRDTerminationPointOfPort() throws InterruptedException {
1271         final Long OFPORT_EXPECTED = 45002L;
1272
1273         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1274
1275         // CREATE
1276         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1277             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1278             Assert.assertNotNull(bridge);
1279             LOG.info("bridge: {}", bridge);
1280             NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1281                     connectionInfo, bridge.getBridgeName()));
1282             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1283                     createGenericOvsdbTerminationPointAugmentationBuilder();
1284             String portName = "testOfPort";
1285             ovsdbTerminationBuilder.setName(portName);
1286
1287             ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
1288             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1289             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1290             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1291             Assert.assertNotNull(terminationPointNode);
1292
1293             // READ
1294             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1295             for (TerminationPoint terminationPoint : terminationPoints) {
1296                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1297                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1298                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1299                     Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
1300                     // if ephemeral port 45002 is in use, ofPort is set to 1
1301                     Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L));
1302                     LOG.info("ofPort: {}", ofPort);
1303                 }
1304             }
1305
1306             // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
1307             //   "A client should ideally set this column’s value in the same database transaction that it uses to create
1308             //   the interface."
1309
1310             // DELETE handled by TestBridge
1311         }
1312     }
1313
1314     @Test
1315     public void testCRDTerminationPointOfPortRequest() throws InterruptedException {
1316         final Long OFPORT_EXPECTED = 45008L;
1317         final Long OFPORT_INPUT = 45008L;
1318
1319         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1320
1321         // CREATE
1322         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1323             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1324             Assert.assertNotNull(bridge);
1325             NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1326                     connectionInfo, bridge.getBridgeName()));
1327             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1328                     createGenericOvsdbTerminationPointAugmentationBuilder();
1329             String portName = "testOfPortRequest";
1330             ovsdbTerminationBuilder.setName(portName);
1331             Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
1332             ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
1333             ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
1334             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1335             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1336             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1337             Assert.assertNotNull(terminationPointNode);
1338
1339             // READ
1340             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1341             for (TerminationPoint terminationPoint : terminationPoints) {
1342                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1343                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1344                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1345                     Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
1346                     // if ephemeral port 45008 is in use, ofPort is set to 1
1347                     Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L));
1348                     LOG.info("ofPort: {}", ofPort);
1349
1350                     Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
1351                     Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
1352                     LOG.info("ofPortRequest: {}", ofPortRequest);
1353                 }
1354             }
1355
1356             // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
1357             //   "A client should ideally set this column’s value in the same database transaction that it uses to
1358             //   create the interface. "
1359
1360             // DELETE handled by TestBridge
1361         }
1362     }
1363
1364     private <T> void assertExpectedExist(List<T> expected, List<T> test) {
1365         if (expected != null && test != null) {
1366             for (T exp : expected) {
1367                 Assert.assertTrue("The retrieved values don't contain " + exp, test.contains(exp));
1368             }
1369         }
1370     }
1371
1372     private interface SouthboundTerminationPointHelper<T> {
1373         void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<T> values);
1374         List<T> readValues(OvsdbTerminationPointAugmentation augmentation);
1375     }
1376
1377     /*
1378      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
1379      *
1380      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1381      */
1382     private <T> void testCRUDTerminationPoint(
1383             KeyValueBuilder<T> builder, String prefix, SouthboundTerminationPointHelper<T> helper)
1384             throws InterruptedException {
1385         final int TERMINATION_POINT_TEST_INDEX = 0;
1386
1387         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1388
1389         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1390         // the update has been performed.
1391         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
1392         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
1393
1394         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
1395             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
1396                 String testBridgeAndPortName = String.format("%s_%s", prefix, updateToTestCase.name);
1397
1398                 // CREATE: Create the test bridge
1399                 try (TestBridge testBridge = new TestBridge(connectionInfo, null, testBridgeAndPortName, null, true,
1400                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null,
1401                         null)) {
1402                     NodeId testBridgeNodeId = SouthboundUtils.createManagedNodeId(
1403                             SouthboundUtils.createInstanceIdentifier(connectionInfo,
1404                                     new OvsdbBridgeName(testBridgeAndPortName)));
1405                     OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1406                             createGenericOvsdbTerminationPointAugmentationBuilder();
1407                     tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1408                     helper.writeValues(tpCreateAugmentationBuilder, updateFromTestCase.inputValues);
1409                     Assert.assertTrue(
1410                             addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1411
1412                     // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
1413                     // then repeat for OPERATIONAL data store
1414                     OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1415                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1416                                     LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1417                     if (updateFromConfigurationTerminationPointAugmentation != null) {
1418                         List<T> updateFromConfigurationValues =
1419                                 helper.readValues(updateFromConfigurationTerminationPointAugmentation);
1420                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
1421                     }
1422                     OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1423                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1424                                     LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1425                     if (updateFromOperationalTerminationPointAugmentation != null) {
1426                         List<T> updateFromOperationalValues =
1427                                 helper.readValues(updateFromOperationalTerminationPointAugmentation);
1428                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
1429                     }
1430
1431                     // UPDATE:  update the values
1432                     testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1433                     OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1434                             new OvsdbTerminationPointAugmentationBuilder();
1435                     helper.writeValues(tpUpdateAugmentationBuilder, updateToTestCase.inputValues);
1436                     InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1437                     NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1438                     NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1439                     portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1440                     TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1441                     tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1442                     tpUpdateBuilder.addAugmentation(
1443                             OvsdbTerminationPointAugmentation.class,
1444                             tpUpdateAugmentationBuilder.build());
1445                     portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1446                     Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1447                             portIid, portUpdateNodeBuilder.build()));
1448                     Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1449
1450                     // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
1451                     // then repeat for OPERATIONAL data store
1452                     OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1453                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1454                                     LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1455                     if (updateToConfigurationTerminationPointAugmentation != null) {
1456                         List<T> updateToConfigurationValues =
1457                                 helper.readValues(updateToConfigurationTerminationPointAugmentation);
1458                         assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
1459                         assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationValues);
1460                     }
1461                     OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1462                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1463                                     LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1464                     if (updateToOperationalTerminationPointAugmentation != null) {
1465                         List<T> updateToOperationalValues =
1466                                 helper.readValues(updateToOperationalTerminationPointAugmentation);
1467                         if (updateFromTestCase.expectedValues != null) {
1468                             assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
1469                             assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalValues);
1470                         }
1471                     }
1472
1473                     // DELETE handled by TestBridge
1474                 }
1475             }
1476         }
1477     }
1478
1479     /*
1480      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
1481      *
1482      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1483      */
1484     @Test
1485     public void testCRUDTerminationPointPortExternalIds() throws InterruptedException {
1486         testCRUDTerminationPoint(new SouthboundPortExternalIdsBuilder(), "TPPortExternalIds",
1487                 new PortExternalIdsSouthboundHelper());
1488     }
1489
1490     /*
1491      * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
1492      *
1493      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1494      */
1495     @Test
1496     public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException {
1497         testCRUDTerminationPoint(new SouthboundInterfaceExternalIdsBuilder(), "TPInterfaceExternalIds",
1498                 new InterfaceExternalIdsSouthboundHelper());
1499     }
1500
1501     /*
1502      * Tests the CRUD operations for <code>Interface</code> <code>lldp</code>.
1503      *
1504      * @see <code>SouthboundIT.generateInterfaceLldpTestCases()</code> for specific test case information
1505      */
1506     @Test
1507     public void testCRUDTerminationPointInterfaceLldp() throws InterruptedException {
1508         testCRUDTerminationPoint(new SouthboundInterfaceLldpBuilder(), "TPInterfaceLldp",
1509                 new InterfaceLldpSouthboundHelper());
1510     }
1511
1512     /*
1513      * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
1514      *
1515      * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
1516      */
1517     @Test
1518     public void testCRUDTerminationPointOptions() throws InterruptedException {
1519         testCRUDTerminationPoint(new SouthboundOptionsBuilder(), "TPOptions", new OptionsSouthboundHelper());
1520     }
1521
1522     /*
1523      * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
1524      *
1525      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1526      */
1527     @Test
1528     public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
1529         testCRUDTerminationPoint(new SouthboundInterfaceOtherConfigsBuilder(), "TPInterfaceOtherConfigs",
1530                 new InterfaceOtherConfigsSouthboundHelper());
1531     }
1532
1533     /*
1534      * Tests the CRUD operations for <code>Port</code> <code>other_configs</code>.
1535      *
1536      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1537      */
1538     @Test
1539     public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
1540         testCRUDTerminationPoint(new SouthboundPortOtherConfigsBuilder(), "TPPortOtherConfigs",
1541                 new PortOtherConfigsSouthboundHelper());
1542     }
1543
1544     @Test
1545     public void testCRUDTerminationPoints() throws InterruptedException {
1546         String port1 = "vx1";
1547         String port2 = "vxlanport";
1548         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1549
1550         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1551             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1552             Assert.assertNotNull(bridge);
1553             NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1554                     connectionInfo, bridge.getBridgeName()));
1555             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1556                     createGenericOvsdbTerminationPointAugmentationBuilder();
1557
1558             // add and delete a single port
1559             String portName = port1;
1560             ovsdbTerminationBuilder.setName(portName);
1561             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1562             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1563             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1564             Assert.assertNotNull(terminationPointNode);
1565
1566             SouthboundUtils.createInstanceIdentifier(connectionInfo,
1567                     new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
1568             portName = port1;
1569             InstanceIdentifier<TerminationPoint> nodePath =
1570                     SouthboundUtils.createInstanceIdentifier(connectionInfo,
1571                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))
1572                             .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
1573
1574             Assert.assertTrue("failed to delete port " + portName,
1575                     mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath));
1576             LOG.info("shague: waiting for delete {}", portName);
1577             Thread.sleep(1000);
1578             TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath);
1579             Assert.assertNull(terminationPoint);
1580
1581             // add two ports, then delete them
1582             portName = port1;
1583             ovsdbTerminationBuilder.setName(portName);
1584             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1585             terminationPointIid = getTpIid(connectionInfo, bridge);
1586             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1587             Assert.assertNotNull(terminationPointNode);
1588
1589             portName = port2;
1590             ovsdbTerminationBuilder.setName(portName);
1591             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1592             terminationPointIid = getTpIid(connectionInfo, bridge);
1593             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1594             Assert.assertNotNull(terminationPointNode);
1595
1596             SouthboundUtils.createInstanceIdentifier(connectionInfo,
1597                     new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
1598             portName = port1;
1599             nodePath =
1600                     SouthboundUtils.createInstanceIdentifier(connectionInfo,
1601                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))
1602                             .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
1603
1604             Assert.assertTrue("failed to delete port " + portName,
1605                     mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath));
1606             LOG.info("shague: waiting for delete {}", portName);
1607             Thread.sleep(1000);
1608             terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath);
1609             Assert.assertNull(terminationPoint);
1610
1611             portName = port2;
1612             nodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo,
1613                     new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))
1614                     .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
1615
1616             Assert.assertTrue("failed to delete port " + portName,
1617                     mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath));
1618             LOG.info("shague: waiting for delete {}", portName);
1619             Thread.sleep(1000);
1620             terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath);
1621             Assert.assertNull(terminationPoint);
1622
1623             // DELETE handled by TestBridge
1624         }
1625     }
1626
1627     @Test
1628     public void testCRUDTerminationPointVlan() throws InterruptedException {
1629         final Integer CREATED_VLAN_ID = 4000;
1630         final Integer UPDATED_VLAN_ID = 4001;
1631
1632         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1633
1634         // CREATE
1635         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1636             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1637             Assert.assertNotNull(bridge);
1638             NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1639                     connectionInfo, bridge.getBridgeName()));
1640             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1641                     createGenericOvsdbTerminationPointAugmentationBuilder();
1642             String portName = "testTerminationPointVlanId";
1643             ovsdbTerminationBuilder.setName(portName);
1644             ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
1645             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1646             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1647             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1648             Assert.assertNotNull(terminationPointNode);
1649
1650             // READ
1651             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1652             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation;
1653             for (TerminationPoint terminationPoint : terminationPoints) {
1654                 ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1655                         OvsdbTerminationPointAugmentation.class);
1656                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1657                     VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1658                     Assert.assertNotNull(actualVlanId);
1659                     Integer actualVlanIdInt = actualVlanId.getValue();
1660                     Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
1661                 }
1662             }
1663
1664             // UPDATE
1665             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1666             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1667                     new OvsdbTerminationPointAugmentationBuilder();
1668             tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
1669             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1670             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1671             NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1672             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1673             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1674             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1675             tpUpdateBuilder.addAugmentation(
1676                     OvsdbTerminationPointAugmentation.class,
1677                     tpUpdateAugmentationBuilder.build());
1678             tpUpdateBuilder.setTpId(new TpId(portName));
1679             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1680             Assert.assertTrue(
1681                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1682             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1683
1684             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1685             terminationPoints = terminationPointNode.getTerminationPoint();
1686             for (TerminationPoint terminationPoint : terminationPoints) {
1687                 ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1688                         OvsdbTerminationPointAugmentation.class);
1689                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1690                     VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1691                     Assert.assertNotNull(actualVlanId);
1692                     Integer actualVlanIdInt = actualVlanId.getValue();
1693                     Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
1694                 }
1695             }
1696
1697             // DELETE handled by TestBridge
1698         }
1699     }
1700
1701     @Test
1702     public void testCRUDTerminationPointVlanModes() throws InterruptedException {
1703         final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
1704         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1705         VlanMode []vlanModes = VlanMode.values();
1706         for (VlanMode vlanMode : vlanModes) {
1707             // CREATE
1708             try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1709                 OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1710                 Assert.assertNotNull(bridge);
1711                 NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1712                         connectionInfo, bridge.getBridgeName()));
1713                 OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1714                         createGenericOvsdbTerminationPointAugmentationBuilder();
1715                 String portName = "testTerminationPointVlanMode" + vlanMode.toString();
1716                 ovsdbTerminationBuilder.setName(portName);
1717                 ovsdbTerminationBuilder.setVlanMode(vlanMode);
1718                 Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1719                 InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1720                 Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1721                 Assert.assertNotNull(terminationPointNode);
1722
1723                 // READ
1724                 List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1725                 for (TerminationPoint terminationPoint : terminationPoints) {
1726                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1727                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1728                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1729                         //test
1730                         Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
1731                     }
1732                 }
1733
1734                 // UPDATE
1735                 NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1736                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1737                         new OvsdbTerminationPointAugmentationBuilder();
1738                 tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
1739                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1740                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1741                 NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1742                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1743                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1744                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1745                 tpUpdateBuilder.addAugmentation(
1746                         OvsdbTerminationPointAugmentation.class,
1747                         tpUpdateAugmentationBuilder.build());
1748                 tpUpdateBuilder.setTpId(new TpId(portName));
1749                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1750                 Assert.assertTrue(
1751                         mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1752                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1753
1754                 terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1755                 terminationPoints = terminationPointNode.getTerminationPoint();
1756                 for (TerminationPoint terminationPoint : terminationPoints) {
1757                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1758                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1759                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1760                         //test
1761                         Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
1762                     }
1763                 }
1764
1765                 // DELETE handled by TestBridge
1766             }
1767         }
1768     }
1769
1770     @SuppressWarnings("unchecked")
1771     private List<Set<Integer>> generateVlanSets() {
1772         int min = 0;
1773         int max = 4095;
1774         return Lists.newArrayList(
1775                 Collections.<Integer>emptySet(),
1776                 Sets.newHashSet(2222),
1777                 Sets.newHashSet(min, max, min + 1, max - 1, (max - min) / 2));
1778     }
1779
1780     private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
1781         List<Trunks> trunkList = Lists.newArrayList();
1782         for (Integer trunk : trunkSet) {
1783             TrunksBuilder trunkBuilder = new TrunksBuilder();
1784             trunkBuilder.setTrunk(new VlanId(trunk));
1785             trunkList.add(trunkBuilder.build());
1786         }
1787         return trunkList;
1788     }
1789
1790     @Test
1791     public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
1792         final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
1793         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1794         Iterable<Set<Integer>> vlanSets = generateVlanSets();
1795         int testCase = 0;
1796         for (Set<Integer> vlanSet : vlanSets) {
1797             ++testCase;
1798             // CREATE
1799             try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1800                 OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1801                 Assert.assertNotNull(bridge);
1802                 NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName());
1803                 OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1804                         createGenericOvsdbTerminationPointAugmentationBuilder();
1805                 String portName = "testTerminationPointVlanTrunks" + testCase;
1806                 ovsdbTerminationBuilder.setName(portName);
1807                 List<Trunks> trunks = buildTrunkList(vlanSet);
1808                 ovsdbTerminationBuilder.setTrunks(trunks);
1809                 Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1810                 InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1811                 Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1812                 Assert.assertNotNull(terminationPointNode);
1813
1814                 // READ
1815                 List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1816                 for (TerminationPoint terminationPoint : terminationPoints) {
1817                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1818                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1819                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1820                         List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
1821                         for (Trunks trunk : trunks) {
1822                             Assert.assertTrue(actualTrunks.contains(trunk));
1823                         }
1824                     }
1825                 }
1826
1827
1828                 // UPDATE
1829                 NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1830                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1831                         new OvsdbTerminationPointAugmentationBuilder();
1832                 tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
1833                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1834                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1835                 NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1836                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1837                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1838                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1839                 tpUpdateBuilder.addAugmentation(
1840                         OvsdbTerminationPointAugmentation.class,
1841                         tpUpdateAugmentationBuilder.build());
1842                 tpUpdateBuilder.setTpId(new TpId(portName));
1843                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1844                 Assert.assertTrue(
1845                         mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1846                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1847
1848                 terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1849                 terminationPoints = terminationPointNode.getTerminationPoint();
1850                 for (TerminationPoint terminationPoint : terminationPoints) {
1851                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1852                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1853                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1854                         //test
1855                         Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
1856                     }
1857                 }
1858
1859                 // DELETE handled by TestBridge
1860             }
1861         }
1862     }
1863
1864     /*
1865      * Tests setting and deleting <code>qos</code> field in a <code>port</code>.
1866      */
1867     @Test
1868     public void testCRUDTerminationPointQos() throws InterruptedException {
1869         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1870         String testQosId = new String("testQosEntry");
1871
1872         // CREATE
1873         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1874                 TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId),
1875                         SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HFSC), null, null)) {
1876             OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
1877                     LogicalDatastoreType.OPERATIONAL);
1878             QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
1879             Assert.assertNotNull(operQos);
1880             Uuid qosUuid = new Uuid(operQos.getQosUuid().getValue());
1881
1882             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1883             Assert.assertNotNull(bridge);
1884             NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName());
1885             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1886                     createGenericOvsdbTerminationPointAugmentationBuilder();
1887             String portName = "testTerminationPointQos";
1888             ovsdbTerminationBuilder.setName(portName);
1889             ovsdbTerminationBuilder.setQos(qosUuid);
1890             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1891
1892             // READ and check that qos uuid has been added to the port
1893             InstanceIdentifier<TerminationPoint> tpEntryIid = getTpIid(connectionInfo, bridge)
1894                     .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
1895             TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid);
1896             Assert.assertNotNull(terminationPoint);
1897             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1898                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1899             Assert.assertEquals(ovsdbTerminationPointAugmentation.getQos(), qosUuid);
1900
1901             // UPDATE - remove the qos entry from the port
1902             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1903                     new OvsdbTerminationPointAugmentationBuilder();
1904             tpUpdateAugmentationBuilder.setName(portName);
1905             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1906             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1907             tpUpdateBuilder.addAugmentation(
1908                     OvsdbTerminationPointAugmentation.class,
1909                     tpUpdateAugmentationBuilder.build());
1910             tpUpdateBuilder.setTpId(new TpId(portName));
1911
1912             Assert.assertTrue(
1913                     mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpEntryIid, tpUpdateBuilder.build()));
1914             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1915
1916             // READ and verify that qos uuid has been removed from port
1917             TerminationPoint terminationPointUpdate = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid);
1918             Assert.assertNotNull(terminationPointUpdate);
1919             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentationUpdate =
1920                     terminationPointUpdate.getAugmentation(OvsdbTerminationPointAugmentation.class);
1921             Assert.assertNull(ovsdbTerminationPointAugmentationUpdate.getQos());
1922
1923             // DELETE handled by TestBridge
1924         }
1925     }
1926
1927     @Test
1928     public void testGetOvsdbNodes() throws InterruptedException {
1929         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1930         InstanceIdentifier<Topology> topologyPath = InstanceIdentifier
1931                 .create(NetworkTopology.class)
1932                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
1933
1934         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
1935         InstanceIdentifier<Node> expectedNodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
1936         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
1937         Node foundNode = null;
1938         Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
1939         Assert.assertNotNull("Expected to find some nodes" + topology.getNode());
1940         LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode());
1941         for (Node node : topology.getNode()) {
1942             if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) {
1943                 foundNode = node;
1944                 break;
1945             }
1946         }
1947         Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
1948     }
1949
1950     /*
1951      * @see <code>SouthboundIT.generateBridgeOtherConfigsTestCases()</code> for specific test case information.
1952      */
1953     @Test
1954     public void testCRUDBridgeOtherConfigs() throws InterruptedException {
1955         testCRUDBridge("BridgeOtherConfigs", new SouthboundBridgeOtherConfigsBuilder(),
1956                 new BridgeOtherConfigsSouthboundHelper());
1957     }
1958
1959     private interface SouthboundBridgeHelper<T> {
1960         void writeValues(OvsdbBridgeAugmentationBuilder builder, List<T> values);
1961         List<T> readValues(OvsdbBridgeAugmentation augmentation);
1962     }
1963
1964     private <T> void testCRUDBridge(String prefix, KeyValueBuilder<T> builder, SouthboundBridgeHelper<T> helper)
1965             throws InterruptedException {
1966         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1967         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1968         // the update has been performed.
1969         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
1970         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
1971         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
1972             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
1973                 String testBridgeName = String.format("%s_%s", prefix, updateToTestCase.name);
1974
1975                 // CREATE: Create the test bridge
1976                 final OvsdbBridgeName ovsdbBridgeName = new OvsdbBridgeName(testBridgeName);
1977                 final InstanceIdentifier<Node> bridgeIid =
1978                         SouthboundUtils.createInstanceIdentifier(connectionInfo, ovsdbBridgeName);
1979                 final NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
1980                 final NodeBuilder bridgeCreateNodeBuilder = new NodeBuilder();
1981                 bridgeCreateNodeBuilder.setNodeId(bridgeNodeId);
1982                 OvsdbBridgeAugmentationBuilder bridgeCreateAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
1983                 bridgeCreateAugmentationBuilder.setBridgeName(ovsdbBridgeName);
1984                 bridgeCreateAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
1985                 bridgeCreateAugmentationBuilder.setFailMode(
1986                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
1987                 setManagedBy(bridgeCreateAugmentationBuilder, connectionInfo);
1988                 helper.writeValues(bridgeCreateAugmentationBuilder, updateFromTestCase.inputValues);
1989                 bridgeCreateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
1990                         bridgeCreateAugmentationBuilder.build());
1991                 LOG.debug("Built with the intent to store bridge data {}", bridgeCreateAugmentationBuilder.toString());
1992                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
1993                         bridgeCreateNodeBuilder.build()));
1994                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1995
1996                 // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
1997                 // then repeat for OPERATIONAL data store
1998                 List<T> updateFromConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
1999                         LogicalDatastoreType.CONFIGURATION));
2000                 assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationExternalIds);
2001                 List<T> updateFromOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
2002                 assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalExternalIds);
2003
2004                 // UPDATE:  update the values
2005                 final OvsdbBridgeAugmentationBuilder bridgeUpdateAugmentationBuilder =
2006                         new OvsdbBridgeAugmentationBuilder();
2007                 helper.writeValues(bridgeUpdateAugmentationBuilder, updateToTestCase.inputValues);
2008                 final NodeBuilder bridgeUpdateNodeBuilder = new NodeBuilder();
2009                 final Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
2010                 bridgeUpdateNodeBuilder.setNodeId(bridgeNode.getNodeId());
2011                 bridgeUpdateNodeBuilder.setKey(bridgeNode.getKey());
2012                 bridgeUpdateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
2013                         bridgeUpdateAugmentationBuilder.build());
2014                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
2015                         bridgeUpdateNodeBuilder.build()));
2016                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2017
2018                 // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
2019                 // then repeat for OPERATIONAL data store
2020                 List<T> updateToConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
2021                         LogicalDatastoreType.CONFIGURATION));
2022                 assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationExternalIds);
2023                 assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationExternalIds);
2024                 List<T> updateToOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
2025                 if (updateFromTestCase.expectedValues != null) {
2026                     assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalExternalIds);
2027                     assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalExternalIds);
2028                 }
2029
2030                 // DELETE
2031                 Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, bridgeIid));
2032                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2033             }
2034         }
2035     }
2036
2037     /*
2038      * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
2039      */
2040     @Test
2041     public void testCRUDBridgeExternalIds() throws InterruptedException {
2042         testCRUDBridge("BridgeExternalIds", new SouthboundBridgeExternalIdsBuilder(),
2043                 new BridgeExternalIdsSouthboundHelper());
2044     }
2045
2046     @Test
2047     public void testAddDeleteQos() throws InterruptedException {
2048         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2049         OvsdbNodeAugmentation ovsdbNodeAugmentation;
2050         Uri qosUri = new Uri("QOS-ROW");
2051         List<String> typeList = new ArrayList<String>();
2052         typeList.add(SouthboundConstants.QOS_LINUX_HTB);
2053         typeList.add(SouthboundConstants.QOS_LINUX_HFSC);
2054
2055         for (String qosType : typeList) {
2056             try (TestQos testQos = new TestQos(connectionInfo, qosUri, SouthboundMapper.createQosType(qosType), null, null)) {
2057                 ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2058                         LogicalDatastoreType.OPERATIONAL);
2059                 QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation);
2060                 Assert.assertNotNull(operQosHtb);
2061             }
2062             ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2063                     LogicalDatastoreType.OPERATIONAL);
2064             QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation);
2065             Assert.assertNull(operQosHtb);
2066         }
2067     }
2068
2069     @Test
2070     public void testAddDeleteQueue() throws InterruptedException {
2071         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2072         Uri queueUri = new Uri("QUEUE-A1");
2073
2074         try (TestQueue testQueue = new TestQueue(connectionInfo, queueUri, new Short("25"), null, null)) {
2075             OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2076                     LogicalDatastoreType.OPERATIONAL);
2077             Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation);
2078             Assert.assertNotNull(operQueue);
2079         }
2080         OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2081                 LogicalDatastoreType.OPERATIONAL);
2082         Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation);
2083         Assert.assertNull(operQueue);
2084     }
2085
2086     private static class SouthboundQueuesExternalIdsHelper implements SouthboundQueueHelper<QueuesExternalIds> {
2087         @Override
2088         public void writeValues(QueuesBuilder builder, List<QueuesExternalIds> values) {
2089             builder.setQueuesExternalIds(values);
2090         }
2091
2092         @Override
2093         public List<QueuesExternalIds> readValues(Queues queue) {
2094             return queue.getQueuesExternalIds();
2095         }
2096     }
2097
2098     private static class SouthboundQueuesOtherConfigHelper implements SouthboundQueueHelper<QueuesOtherConfig> {
2099         @Override
2100         public void writeValues(QueuesBuilder builder, List<QueuesOtherConfig> values) {
2101             builder.setQueuesOtherConfig(values);
2102         }
2103
2104         @Override
2105         public List<QueuesOtherConfig> readValues(Queues queue) {
2106             return queue.getQueuesOtherConfig();
2107         }
2108     }
2109
2110     private interface SouthboundQueueHelper<T> {
2111         void writeValues(QueuesBuilder builder, List<T> values);
2112         List<T> readValues(Queues queue);
2113     }
2114
2115     private Queues getQueue(Uri queueId, OvsdbNodeAugmentation node) {
2116         for (Queues queue : node.getQueues()) {
2117             if (queue.getKey().getQueueId().getValue().equals(queueId.getValue()))
2118                 return queue;
2119         }
2120         return null;
2121     }
2122
2123     private static class SouthboundQosExternalIdsHelper implements SouthboundQosHelper<QosExternalIds> {
2124         @Override
2125         public void writeValues(QosEntriesBuilder builder, List<QosExternalIds> values) {
2126             builder.setQosExternalIds(values);
2127         }
2128
2129         @Override
2130         public List<QosExternalIds> readValues(QosEntries qos) {
2131             return qos.getQosExternalIds();
2132         }
2133     }
2134
2135     private static class SouthboundQosOtherConfigHelper implements SouthboundQosHelper<QosOtherConfig> {
2136         @Override
2137         public void writeValues(QosEntriesBuilder builder, List<QosOtherConfig> values) {
2138             builder.setQosOtherConfig(values);
2139         }
2140
2141         @Override
2142         public List<QosOtherConfig> readValues(QosEntries qos) {
2143             return qos.getQosOtherConfig();
2144         }
2145     }
2146
2147     private interface SouthboundQosHelper<T> {
2148         void writeValues(QosEntriesBuilder builder, List<T> values);
2149         List<T> readValues(QosEntries qos);
2150     }
2151
2152     private QosEntries getQos(Uri qosId, OvsdbNodeAugmentation node) {
2153         for (QosEntries qos : node.getQosEntries()) {
2154             if (qos.getKey().getQosId().equals(qosId))
2155                 return qos;
2156         }
2157         return null;
2158     }
2159
2160     private <T> void testCRUDQueue(
2161             KeyValueBuilder<T> builder, String prefix, SouthboundQueueHelper<T> helper)
2162             throws InterruptedException {
2163
2164         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2165
2166         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
2167         // the update has been performed.
2168         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
2169         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
2170
2171         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
2172             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
2173                 String testQueueId = String.format("%s_%s", prefix, updateToTestCase.name);
2174
2175                 // CREATE: and update the test queue with starting values.
2176                 try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("45"), null, null)) {
2177                     QueuesBuilder queuesBuilder = new QueuesBuilder();
2178                     queuesBuilder.setQueueId(new Uri(testQueueId));
2179                     InstanceIdentifier<Queues> queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
2180                             .augmentation(OvsdbNodeAugmentation.class)
2181                             .child(Queues.class, queuesBuilder.build().getKey());
2182                     final NotifyingDataChangeListener queueConfigurationListener =
2183                             new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, queueIid);
2184                     queueConfigurationListener.registerDataChangeListener();
2185                     final NotifyingDataChangeListener queueOperationalListener =
2186                             new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid);
2187                     queueOperationalListener.registerDataChangeListener();
2188
2189                     helper.writeValues(queuesBuilder, updateFromTestCase.inputValues);
2190                     Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2191                             queueIid, queuesBuilder.build()));
2192                     queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2193
2194                     // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store,
2195                     // then repeat for OPERATIONAL data store
2196                     OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2197                             LogicalDatastoreType.CONFIGURATION);
2198                     Queues queueFromConfig = getQueue(new Uri(testQueueId), updateFromConfigurationOvsdbNodeAugmentation);
2199                     if (queueFromConfig != null) {
2200                         List<T> updateFromConfigurationValues =
2201                                 helper.readValues(queueFromConfig);
2202                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
2203                     }
2204
2205                     queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2206                     OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2207                             LogicalDatastoreType.OPERATIONAL);
2208                     Queues queueFromOper = getQueue(new Uri(testQueueId), updateFromOperationalOvsdbNodeAugmentation);
2209                     if (queueFromOper != null) {
2210                         List<T> updateFromOperationalValues =
2211                                 helper.readValues(queueFromOper);
2212                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
2213                     }
2214
2215                     // UPDATE:  update the values
2216                     QueuesBuilder queuesUpdateBuilder = new QueuesBuilder();
2217                     queuesUpdateBuilder.setQueueId(new Uri(testQueueId));
2218                     helper.writeValues(queuesUpdateBuilder, updateToTestCase.inputValues);
2219                     Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2220                             queueIid, queuesUpdateBuilder.build()));
2221                     queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2222
2223                     // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store,
2224                     // then repeat for OPERATIONAL data store
2225                     OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2226                             LogicalDatastoreType.CONFIGURATION);
2227                     Queues queueToConfig = getQueue(new Uri(testQueueId), updateToConfigurationOvsdbNodeAugmentation);
2228                     if (queueToConfig != null) {
2229                         List<T> updateToConfigurationValues =
2230                                 helper.readValues(queueToConfig);
2231                         assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
2232                     }
2233
2234                     queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2235                     OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2236                             LogicalDatastoreType.OPERATIONAL);
2237                     Queues queueToOper = getQueue(new Uri(testQueueId), updateToOperationalOvsdbNodeAugmentation);
2238                     if (queueToOper != null) {
2239                         List<T> updateToOperationalValues =
2240                                 helper.readValues(queueToOper);
2241                         assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
2242                     }
2243
2244                     // DELETE handled by TestQueue
2245                 }
2246             }
2247         }
2248     }
2249
2250     @Test
2251     public void testCRUDQueueExternalIds() throws InterruptedException {
2252         testCRUDQueue(new SouthboundQueuesExternalIdsBuilder(), "QueueExternalIds",
2253                 new SouthboundQueuesExternalIdsHelper());
2254     }
2255
2256     @Test
2257     public void testCRUDQueueOtherConfig() throws InterruptedException {
2258         testCRUDQueue(new SouthboundQueuesOtherConfigBuilder(), "QueueOtherConfig",
2259                 new SouthboundQueuesOtherConfigHelper());
2260     }
2261
2262     @Test
2263     public void testCRUDQueueDscp() throws InterruptedException {
2264         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2265         String testQueueId = "testQueueDscp";
2266
2267         // CREATE: and update the test queue with starting values.
2268         try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("0"), null, null)) {
2269             for (Short dscp = 1; dscp < 64; dscp++) {
2270                 QueuesBuilder queuesBuilder = new QueuesBuilder();
2271                 queuesBuilder.setQueueId(new Uri(testQueueId));
2272                 InstanceIdentifier<Queues> queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
2273                         .augmentation(OvsdbNodeAugmentation.class)
2274                         .child(Queues.class, queuesBuilder.build().getKey());
2275                 final NotifyingDataChangeListener queueOperationalListener =
2276                         new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid);
2277                 queueOperationalListener.registerDataChangeListener();
2278
2279                 queuesBuilder.setDscp(dscp);
2280                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2281                         queueIid, queuesBuilder.build()));
2282                 queueOperationalListener.waitForUpdate(OVSDB_ROUNDTRIP_TIMEOUT);
2283
2284                 // READ: Read the test queue and ensure changes are propagated to the OPERATIONAL data store
2285                 // assumption is that CONFIGURATION was updated if OPERATIONAL is correct
2286                 OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2287                         LogicalDatastoreType.OPERATIONAL);
2288                 Queues operQueue = getQueue(new Uri(testQueueId), ovsdbNodeAugmentation);
2289                 Assert.assertNotNull(operQueue);
2290                 Short operDscp = operQueue.getDscp();
2291                 Assert.assertNotNull(operDscp);
2292                 Assert.assertEquals(dscp, operDscp);
2293             }
2294
2295             // DELETE handled by TestQueue
2296         }
2297
2298     }
2299
2300     private <T> void testCRUDQos(
2301             KeyValueBuilder<T> builder, String prefix, SouthboundQosHelper<T> helper)
2302             throws InterruptedException {
2303
2304         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2305
2306         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
2307         // the update has been performed.
2308         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
2309         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
2310
2311         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
2312             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
2313                 String testQosId = String.format("%s_%s", prefix, updateToTestCase.name);
2314
2315                 // CREATE: and update the test qos with starting values.
2316                 try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null)) {
2317                     QosEntriesBuilder qosBuilder = new QosEntriesBuilder();
2318                     qosBuilder.setQosId(new Uri(testQosId));
2319                     InstanceIdentifier<QosEntries> qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
2320                             .augmentation(OvsdbNodeAugmentation.class)
2321                             .child(QosEntries.class, qosBuilder.build().getKey());
2322                     final NotifyingDataChangeListener qosConfigurationListener =
2323                             new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, qosIid);
2324                     qosConfigurationListener.registerDataChangeListener();
2325                     final NotifyingDataChangeListener qosOperationalListener =
2326                             new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid);
2327                     qosOperationalListener.registerDataChangeListener();
2328
2329                     helper.writeValues(qosBuilder, updateFromTestCase.inputValues);
2330                     Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2331                             qosIid, qosBuilder.build()));
2332                     qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2333
2334                     // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store,
2335                     // then repeat for OPERATIONAL data store
2336                     OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2337                             LogicalDatastoreType.CONFIGURATION);
2338                     QosEntries qosFromConfig = getQos(new Uri(testQosId), updateFromConfigurationOvsdbNodeAugmentation);
2339                     if (qosFromConfig != null) {
2340                         List<T> updateFromConfigurationValues =
2341                                 helper.readValues(qosFromConfig);
2342                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
2343                     }
2344
2345                     qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2346                     OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2347                             LogicalDatastoreType.OPERATIONAL);
2348                     QosEntries qosFromOper = getQos(new Uri(testQosId), updateFromOperationalOvsdbNodeAugmentation);
2349                     if (qosFromOper != null) {
2350                         List<T> updateFromOperationalValues =
2351                                 helper.readValues(qosFromOper);
2352                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
2353                     }
2354
2355                     // UPDATE:  update the values
2356                     QosEntriesBuilder qosUpdateBuilder = new QosEntriesBuilder();
2357                     qosUpdateBuilder.setQosId(new Uri(testQosId));
2358                     helper.writeValues(qosUpdateBuilder, updateToTestCase.inputValues);
2359                     Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2360                             qosIid, qosUpdateBuilder.build()));
2361                     qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2362
2363                     // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store,
2364                     // then repeat for OPERATIONAL data store
2365                     OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2366                             LogicalDatastoreType.CONFIGURATION);
2367                     QosEntries qosToConfig = getQos(new Uri(testQosId), updateToConfigurationOvsdbNodeAugmentation);
2368                     if (qosToConfig != null) {
2369                         List<T> updateToConfigurationValues =
2370                                 helper.readValues(qosToConfig);
2371                         assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
2372                     }
2373
2374                     qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2375                     OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2376                             LogicalDatastoreType.OPERATIONAL);
2377                     QosEntries qosToOper = getQos(new Uri(testQosId), updateToOperationalOvsdbNodeAugmentation);
2378                     if (qosToOper != null) {
2379                         List<T> updateToOperationalValues =
2380                                 helper.readValues(qosToOper);
2381                         assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
2382                     }
2383
2384                     // DELETE handled by TestQueue
2385                 }
2386             }
2387         }
2388     }
2389
2390     @Test
2391     public void testCRUDQosExternalIds() throws InterruptedException {
2392         testCRUDQos(new SouthboundQosExternalIdsBuilder(), "QosExternalIds",
2393                 new SouthboundQosExternalIdsHelper());
2394     }
2395
2396     @Test
2397     public void testCRUDQosOtherConfig() throws InterruptedException {
2398         testCRUDQos(new SouthboundQosOtherConfigBuilder(), "QosOtherConfig",
2399                 new SouthboundQosOtherConfigHelper());
2400     }
2401     @Test
2402     public void testCRUDQosQueues() throws InterruptedException {
2403         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2404         String testQosId = "testQosQueues";
2405
2406         // CREATE: and update the test queue with starting values.
2407         try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId),
2408                 SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null);
2409                 TestQueue testQueue1 = new TestQueue(connectionInfo, new Uri("queue1"), new Short("12"), null, null);
2410                 TestQueue testQueue2 = new TestQueue(connectionInfo, new Uri("queue2"), new Short("35"), null, null)) {
2411             QosEntriesBuilder qosBuilder = new QosEntriesBuilder();
2412             qosBuilder.setQosId(new Uri(testQosId));
2413             InstanceIdentifier<QosEntries> qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
2414                     .augmentation(OvsdbNodeAugmentation.class)
2415                     .child(QosEntries.class, qosBuilder.build().getKey());
2416             final NotifyingDataChangeListener qosOperationalListener =
2417                     new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid);
2418             qosOperationalListener.registerDataChangeListener();
2419
2420             // READ, UPDATE:  Read the UUIDs of the Queue rows and add them to the
2421             // configuration of the Qos row.
2422             OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2423                     LogicalDatastoreType.OPERATIONAL);
2424             Queues operQueue1 = getQueue(new Uri("queue1"), ovsdbNodeAugmentation);
2425             Assert.assertNotNull(operQueue1);
2426             Uuid queue1Uuid = new Uuid(operQueue1.getQueueUuid().getValue());
2427             Queues operQueue2 = getQueue(new Uri("queue2"), ovsdbNodeAugmentation);
2428             Assert.assertNotNull(operQueue2);
2429             Uuid queue2Uuid = new Uuid(operQueue2.getQueueUuid().getValue());
2430
2431             List<QueueList> queueList = new ArrayList<>();
2432             queueList.add(new QueueListBuilder().setQueueNumber(new Long("0"))
2433                     .setQueueUuid(queue1Uuid).build());
2434             queueList.add(new QueueListBuilder().setQueueNumber(new Long("1"))
2435                     .setQueueUuid(queue2Uuid).build());
2436             qosBuilder.setQueueList(queueList);
2437
2438             Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2439                     qosIid, qosBuilder.build()));
2440             qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2441
2442             // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store
2443             // assumption is that CONFIGURATION was updated if OPERATIONAL is correct
2444             ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2445                     LogicalDatastoreType.OPERATIONAL);
2446             QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
2447             Assert.assertNotNull(operQos);
2448             List<QueueList> operQueueList = operQos.getQueueList();
2449             Assert.assertNotNull(operQueueList);
2450             for (QueueList queueEntry : queueList) {
2451                 Assert.assertTrue(operQueueList.contains(queueEntry));
2452             }
2453
2454             // DELETE one queue from queue list and check that one remains
2455             KeyedInstanceIdentifier<QueueList, QueueListKey> qosQueueIid = qosIid
2456                         .child(QueueList.class, new QueueListKey(new Long("0")));
2457             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid));
2458             qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2459
2460             // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store
2461             // assumption is that CONFIGURATION was updated if OPERATIONAL is correct
2462             ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2463                     LogicalDatastoreType.OPERATIONAL);
2464             operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
2465             Assert.assertNotNull(operQos);
2466             operQueueList = operQos.getQueueList();
2467             Assert.assertNotNull(operQueueList);
2468             for (QueueList queueEntry : queueList) {
2469                 if (queueEntry.getQueueUuid().equals(queue2Uuid))
2470                     Assert.assertTrue(operQueueList.contains(queueEntry));
2471                 else if (queueEntry.getQueueUuid().equals(queue1Uuid)) {
2472                     Assert.assertFalse(operQueueList.contains(queueEntry));
2473                 } else {
2474                     Assert.assertTrue("Unknown queue entry in qos queue list", false);
2475                 }
2476             }
2477
2478             // DELETE  queue list and check that list is empty
2479             qosQueueIid = qosIid
2480                     .child(QueueList.class, new QueueListKey(new Long("1")));
2481             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid));
2482             qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
2483
2484             ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
2485                     LogicalDatastoreType.OPERATIONAL);
2486             operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
2487             Assert.assertNotNull(operQos);
2488             operQueueList = operQos.getQueueList();
2489             Assert.assertNotNull(operQueueList);
2490             Assert.assertTrue(operQueueList.isEmpty());
2491         }
2492     }
2493
2494     /**
2495      * <p>
2496      * Representation of a southbound test case. Each test case has a name, a list of input values and a list of
2497      * expected values. The input values are provided to the augmentation builder, and the expected values are checked
2498      * against the output of the resulting augmentation.
2499      * </p>
2500      * <p>
2501      * Instances of this class are immutable.
2502      * </p>
2503      *
2504      * @param <T> The type of data used for the test case.
2505      */
2506     private static final class SouthboundTestCase<T> {
2507         private final String name;
2508         private final List<T> inputValues;
2509         private final List<T> expectedValues;
2510
2511         /**
2512          * Creates an instance of a southbound test case.
2513          *
2514          * @param name The test case's name.
2515          * @param inputValues The input values (provided as input to the underlying augmentation builder).
2516          * @param expectedValues The expected values (checked against the output of the underlying augmentation).
2517          */
2518         public SouthboundTestCase(
2519                 final String name, final List<T> inputValues, final List<T> expectedValues) {
2520             this.name = name;
2521             this.inputValues = inputValues;
2522             this.expectedValues = expectedValues;
2523         }
2524     }
2525
2526     /**
2527      * Southbound test case builder.
2528      *
2529      * @param <T> The type of data used for the test case.
2530      */
2531     private static final class SouthboundTestCaseBuilder<T> {
2532         private String name;
2533         private List<T> inputValues;
2534         private List<T> expectedValues;
2535
2536         /**
2537          * Creates a builder. Builders may be reused, the generated immutable instances are independent of the
2538          * builders. There are no default values.
2539          */
2540         public SouthboundTestCaseBuilder() {
2541             // Nothing to do
2542         }
2543
2544         /**
2545          * Sets the test case's name.
2546          *
2547          * @param name The test case's name.
2548          * @return The builder.
2549          */
2550         public SouthboundTestCaseBuilder<T> name(final String name) {
2551             this.name = name;
2552             return this;
2553         }
2554
2555         /**
2556          * Sets the input values.
2557          *
2558          * @param inputValues The input values.
2559          * @return The builder.
2560          */
2561         @SafeVarargs
2562         public final SouthboundTestCaseBuilder<T> input(final T... inputValues) {
2563             this.inputValues = Lists.newArrayList(inputValues);
2564             return this;
2565         }
2566
2567         /**
2568          * Indicates that the provided input values should be expected as output values.
2569          *
2570          * @return The builder.
2571          */
2572         public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
2573             this.expectedValues = this.inputValues;
2574             return this;
2575         }
2576
2577         /**
2578          * Indicates that no output should be expected.
2579          *
2580          * @return The builder.
2581          */
2582         public SouthboundTestCaseBuilder<T> expectNoOutput() {
2583             this.expectedValues = null;
2584             return this;
2585         }
2586
2587         /**
2588          * Builds an immutable instance representing the test case.
2589          *
2590          * @return The test case.
2591          */
2592         @SuppressWarnings("unchecked")
2593         public SouthboundTestCase<T> build() {
2594             return new SouthboundTestCase<>(name, inputValues, expectedValues);
2595         }
2596     }
2597
2598     private abstract static class KeyValueBuilder<T> {
2599         private static final int COUNTER_START = 0;
2600         private int counter = COUNTER_START;
2601
2602         protected abstract Builder<T> builder();
2603
2604         protected abstract void setKey(Builder<T> builder, String key);
2605
2606         protected abstract void setValue(Builder<T> builder, String value);
2607
2608         protected abstract boolean isValueMandatory();
2609
2610         public final T build(final String testName, final String key, final String value) {
2611             final Builder<T> builder = builder();
2612             this.counter++;
2613             if (key != null) {
2614                 setKey(builder, String.format(FORMAT_STR, testName, key, this.counter));
2615             }
2616             if (value != null) {
2617                 setValue(builder, String.format(FORMAT_STR, testName, value, this.counter));
2618             }
2619             return builder.build();
2620         }
2621
2622         public final void reset() {
2623             this.counter = COUNTER_START;
2624         }
2625     }
2626
2627     private static final class SouthboundQueuesExternalIdsBuilder extends KeyValueBuilder<QueuesExternalIds> {
2628         @Override
2629         protected Builder<QueuesExternalIds> builder() {
2630             return new QueuesExternalIdsBuilder();
2631         }
2632
2633         @Override
2634         protected void setKey(Builder<QueuesExternalIds> builder, String key) {
2635             ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdKey(key);
2636         }
2637
2638         @Override
2639         protected void setValue(Builder<QueuesExternalIds> builder, String value) {
2640             ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdValue(value);
2641         }
2642
2643         @Override
2644         protected boolean isValueMandatory() {
2645             return true;
2646         }
2647     }
2648
2649     private static final class SouthboundQueuesOtherConfigBuilder extends KeyValueBuilder<QueuesOtherConfig> {
2650         @Override
2651         protected Builder<QueuesOtherConfig> builder() {
2652             return new QueuesOtherConfigBuilder();
2653         }
2654
2655         @Override
2656         protected void setKey(Builder<QueuesOtherConfig> builder, String key) {
2657             ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigKey(key);
2658         }
2659
2660         @Override
2661         protected void setValue(Builder<QueuesOtherConfig> builder, String value) {
2662             ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigValue(value);
2663         }
2664
2665         @Override
2666         protected boolean isValueMandatory() {
2667             return false;
2668         }
2669     }
2670
2671     private static final class SouthboundQosExternalIdsBuilder extends KeyValueBuilder<QosExternalIds> {
2672         @Override
2673         protected Builder<QosExternalIds> builder() {
2674             return new QosExternalIdsBuilder();
2675         }
2676
2677         @Override
2678         protected void setKey(Builder<QosExternalIds> builder, String key) {
2679             ((QosExternalIdsBuilder) builder).setQosExternalIdKey(key);
2680         }
2681
2682         @Override
2683         protected void setValue(Builder<QosExternalIds> builder, String value) {
2684             ((QosExternalIdsBuilder) builder).setQosExternalIdValue(value);
2685         }
2686
2687         @Override
2688         protected boolean isValueMandatory() {
2689             return true;
2690         }
2691     }
2692
2693     private static final class SouthboundQosOtherConfigBuilder extends KeyValueBuilder<QosOtherConfig> {
2694         @Override
2695         protected Builder<QosOtherConfig> builder() {
2696             return new QosOtherConfigBuilder();
2697         }
2698
2699         @Override
2700         protected void setKey(Builder<QosOtherConfig> builder, String key) {
2701             ((QosOtherConfigBuilder) builder).setOtherConfigKey(key);
2702         }
2703
2704         @Override
2705         protected void setValue(Builder<QosOtherConfig> builder, String value) {
2706             ((QosOtherConfigBuilder) builder).setOtherConfigValue(value);
2707         }
2708
2709         @Override
2710         protected boolean isValueMandatory() {
2711             return false;
2712         }
2713     }
2714
2715     private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder<PortExternalIds> {
2716         @Override
2717         protected Builder<PortExternalIds> builder() {
2718             return new PortExternalIdsBuilder();
2719         }
2720
2721         @Override
2722         protected void setKey(Builder<PortExternalIds> builder, String key) {
2723             ((PortExternalIdsBuilder) builder).setExternalIdKey(key);
2724         }
2725
2726         @Override
2727         protected void setValue(Builder<PortExternalIds> builder, String value) {
2728             ((PortExternalIdsBuilder) builder).setExternalIdValue(value);
2729         }
2730
2731         @Override
2732         protected boolean isValueMandatory() {
2733             return true;
2734         }
2735     }
2736
2737     private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder<InterfaceExternalIds> {
2738         @Override
2739         protected Builder<InterfaceExternalIds> builder() {
2740             return new InterfaceExternalIdsBuilder();
2741         }
2742
2743         @Override
2744         protected void setKey(Builder<InterfaceExternalIds> builder, String key) {
2745             ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key);
2746         }
2747
2748         @Override
2749         protected void setValue(Builder<InterfaceExternalIds> builder, String value) {
2750             ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value);
2751         }
2752
2753         @Override
2754         protected boolean isValueMandatory() {
2755             return true;
2756         }
2757     }
2758
2759     private static final class SouthboundInterfaceLldpBuilder extends KeyValueBuilder<InterfaceLldp> {
2760         @Override
2761         protected Builder<InterfaceLldp> builder() {
2762             return new InterfaceLldpBuilder();
2763         }
2764
2765         @Override
2766         protected void setKey(Builder<InterfaceLldp> builder, String key) {
2767             ((InterfaceLldpBuilder) builder).setLldpKey((key));
2768         }
2769
2770         @Override
2771         protected void setValue(Builder<InterfaceLldp> builder, String value) {
2772             ((InterfaceLldpBuilder) builder).setLldpValue(value);
2773         }
2774
2775         @Override
2776         protected boolean isValueMandatory() {
2777             return true;
2778         }
2779     }
2780
2781     private static final class SouthboundOptionsBuilder extends KeyValueBuilder<Options> {
2782         @Override
2783         protected Builder<Options> builder() {
2784             return new OptionsBuilder();
2785         }
2786
2787         @Override
2788         protected void setKey(Builder<Options> builder, String key) {
2789             ((OptionsBuilder) builder).setOption(key);
2790         }
2791
2792         @Override
2793         protected void setValue(Builder<Options> builder, String value) {
2794             ((OptionsBuilder) builder).setValue(value);
2795         }
2796
2797         @Override
2798         protected boolean isValueMandatory() {
2799             return false;
2800         }
2801     }
2802
2803     private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder<InterfaceOtherConfigs> {
2804         @Override
2805         protected Builder<InterfaceOtherConfigs> builder() {
2806             return new InterfaceOtherConfigsBuilder();
2807         }
2808
2809         @Override
2810         protected void setKey(Builder<InterfaceOtherConfigs> builder, String key) {
2811             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key);
2812         }
2813
2814         @Override
2815         protected void setValue(Builder<InterfaceOtherConfigs> builder, String value) {
2816             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value);
2817         }
2818
2819         @Override
2820         protected boolean isValueMandatory() {
2821             return false;
2822         }
2823     }
2824
2825     private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder<PortOtherConfigs> {
2826         @Override
2827         protected Builder<PortOtherConfigs> builder() {
2828             return new PortOtherConfigsBuilder();
2829         }
2830
2831         @Override
2832         protected void setKey(Builder<PortOtherConfigs> builder, String key) {
2833             ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key);
2834         }
2835
2836         @Override
2837         protected void setValue(Builder<PortOtherConfigs> builder, String value) {
2838             ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value);
2839         }
2840
2841         @Override
2842         protected boolean isValueMandatory() {
2843             return false;
2844         }
2845     }
2846
2847     private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder<BridgeOtherConfigs> {
2848         @Override
2849         protected Builder<BridgeOtherConfigs> builder() {
2850             return new BridgeOtherConfigsBuilder();
2851         }
2852
2853         @Override
2854         protected void setKey(Builder<BridgeOtherConfigs> builder, String key) {
2855             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key);
2856         }
2857
2858         @Override
2859         protected void setValue(Builder<BridgeOtherConfigs> builder, String value) {
2860             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value);
2861         }
2862
2863         @Override
2864         protected boolean isValueMandatory() {
2865             return false;
2866         }
2867     }
2868
2869     private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder<BridgeExternalIds> {
2870         @Override
2871         protected Builder<BridgeExternalIds> builder() {
2872             return new BridgeExternalIdsBuilder();
2873         }
2874
2875         @Override
2876         protected void setKey(Builder<BridgeExternalIds> builder, String key) {
2877             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key);
2878         }
2879
2880         @Override
2881         protected void setValue(Builder<BridgeExternalIds> builder, String value) {
2882             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
2883         }
2884
2885         @Override
2886         protected boolean isValueMandatory() {
2887             return true;
2888         }
2889     }
2890
2891     /*
2892      * Generates the test cases involved in testing key-value-based data.  See inline comments for descriptions of
2893      * the particular cases considered.
2894      */
2895     private static <T> List<SouthboundTestCase<T>> generateKeyValueTestCases(
2896             KeyValueBuilder<T> builder, String testName) {
2897         List<SouthboundTestCase<T>> testCases = new ArrayList<>();
2898
2899         final String GOOD_KEY = "GoodKey";
2900         final String GOOD_VALUE = "GoodValue";
2901         final String NO_VALUE_FOR_KEY = "NoValueForKey";
2902
2903         final String idKey = testName + "Key";
2904         final String idValue = testName + "Value";
2905
2906         // Test Case 1:  TestOne
2907         // Test Type:    Positive
2908         // Description:  Create a termination point with one value
2909         // Expected:     A port is created with the single value specified below
2910         final String testOneName = "TestOne" + testName;
2911         testCases.add(new SouthboundTestCaseBuilder<T>()
2912                 .name(testOneName)
2913                 .input(builder.build(testOneName, idKey, idValue))
2914                 .expectInputAsOutput()
2915                 .build());
2916         builder.reset();
2917
2918         // Test Case 2:  TestFive
2919         // Test Type:    Positive
2920         // Description:  Create a termination point with multiple (five) values
2921         // Expected:     A port is created with the five values specified below
2922         final String testFiveName = "TestFive" + testName;
2923         testCases.add(new SouthboundTestCaseBuilder<T>()
2924                 .name(testFiveName)
2925                 .input(
2926                         builder.build(testFiveName, idKey, idValue),
2927                         builder.build(testFiveName, idKey, idValue),
2928                         builder.build(testFiveName, idKey, idValue),
2929                         builder.build(testFiveName, idKey, idValue),
2930                         builder.build(testFiveName, idKey, idValue))
2931                 .expectInputAsOutput()
2932                 .build());
2933         builder.reset();
2934
2935         if (!builder.isValueMandatory()) {
2936             // Test Case 3:  TestOneGoodOneMalformedValue
2937             // Test Type:    Negative
2938             // Description:
2939             //     One perfectly fine input
2940             //        (TestOneGoodOneMalformedValue_GoodKey_1,
2941             //        TestOneGoodOneMalformedValue_GoodValue_1)
2942             //     and one malformed input which only has key specified
2943             //        (TestOneGoodOneMalformedValue_NoValueForKey_2,
2944             //        UNSPECIFIED)
2945             // Expected:     A port is created without any values
2946             final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName;
2947             testCases.add(new SouthboundTestCaseBuilder<T>()
2948                     .name(testOneGoodOneMalformedValueName)
2949                     .input(
2950                             builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE),
2951                             builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null))
2952                     .expectNoOutput()
2953                     .build());
2954             builder.reset();
2955         } else {
2956             LOG.info("generateKeyValueTestCases: skipping test case 3 for {}", builder.getClass().getSimpleName());
2957         }
2958
2959         return testCases;
2960     }
2961
2962     private static class PortExternalIdsSouthboundHelper implements SouthboundTerminationPointHelper<PortExternalIds> {
2963         @Override
2964         public void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<PortExternalIds> values) {
2965             builder.setPortExternalIds(values);
2966         }
2967
2968         @Override
2969         public List<PortExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
2970             return augmentation.getPortExternalIds();
2971         }
2972     }
2973
2974     private static class InterfaceExternalIdsSouthboundHelper implements
2975             SouthboundTerminationPointHelper<InterfaceExternalIds> {
2976         @Override
2977         public void writeValues(
2978                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceExternalIds> values) {
2979             builder.setInterfaceExternalIds(values);
2980         }
2981
2982         @Override
2983         public List<InterfaceExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
2984             return augmentation.getInterfaceExternalIds();
2985         }
2986     }
2987
2988     private static class InterfaceLldpSouthboundHelper implements
2989     SouthboundTerminationPointHelper<InterfaceLldp> {
2990         @Override
2991         public void writeValues(
2992                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceLldp> values) {
2993             builder.setInterfaceLldp(values);
2994         }
2995
2996         @Override
2997         public List<InterfaceLldp> readValues(OvsdbTerminationPointAugmentation augmentation) {
2998             return augmentation.getInterfaceLldp();
2999         }
3000     }
3001
3002     private static class OptionsSouthboundHelper implements SouthboundTerminationPointHelper<Options> {
3003         @Override
3004         public void writeValues(
3005                 OvsdbTerminationPointAugmentationBuilder builder, List<Options> values) {
3006             builder.setOptions(values);
3007         }
3008
3009         @Override
3010         public List<Options> readValues(OvsdbTerminationPointAugmentation augmentation) {
3011             return augmentation.getOptions();
3012         }
3013     }
3014
3015     private static class InterfaceOtherConfigsSouthboundHelper implements
3016             SouthboundTerminationPointHelper<InterfaceOtherConfigs> {
3017         @Override
3018         public void writeValues(
3019                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceOtherConfigs> values) {
3020             builder.setInterfaceOtherConfigs(values);
3021         }
3022
3023         @Override
3024         public List<InterfaceOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
3025             return augmentation.getInterfaceOtherConfigs();
3026         }
3027     }
3028
3029     private static class PortOtherConfigsSouthboundHelper implements
3030             SouthboundTerminationPointHelper<PortOtherConfigs> {
3031         @Override
3032         public void writeValues(
3033                 OvsdbTerminationPointAugmentationBuilder builder, List<PortOtherConfigs> values) {
3034             builder.setPortOtherConfigs(values);
3035         }
3036
3037         @Override
3038         public List<PortOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
3039             return augmentation.getPortOtherConfigs();
3040         }
3041     }
3042
3043     private static class BridgeExternalIdsSouthboundHelper implements SouthboundBridgeHelper<BridgeExternalIds> {
3044         @Override
3045         public void writeValues(
3046                 OvsdbBridgeAugmentationBuilder builder, List<BridgeExternalIds> values) {
3047             builder.setBridgeExternalIds(values);
3048         }
3049
3050         @Override
3051         public List<BridgeExternalIds> readValues(OvsdbBridgeAugmentation augmentation) {
3052             return augmentation.getBridgeExternalIds();
3053         }
3054     }
3055
3056     private static class BridgeOtherConfigsSouthboundHelper implements SouthboundBridgeHelper<BridgeOtherConfigs> {
3057         @Override
3058         public void writeValues(
3059                 OvsdbBridgeAugmentationBuilder builder, List<BridgeOtherConfigs> values) {
3060             builder.setBridgeOtherConfigs(values);
3061         }
3062
3063         @Override
3064         public List<BridgeOtherConfigs> readValues(OvsdbBridgeAugmentation augmentation) {
3065             return augmentation.getBridgeOtherConfigs();
3066         }
3067     }
3068 }