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