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