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