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