X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=southbound%2Fsouthbound-it%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fovsdb%2Fsouthbound%2Fit%2FSouthboundIT.java;h=8104a551fe4caafa079ed728103286e7cf9e1325;hb=b280e0059271cf85d51d6ab241e6c135c2a81832;hp=410c19cd15890346113df6e9c6a1a62dc0ebb404;hpb=d382cb7d03de549f367b7584b78f50eb0854ee2e;p=ovsdb.git diff --git a/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java b/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java index 410c19cd1..6817bfa18 100644 --- a/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java +++ b/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java @@ -9,35 +9,54 @@ package org.opendaylight.ovsdb.southbound.it; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.maven; +import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties; +import static org.ops4j.pax.exam.CoreOptions.vmOption; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut; -import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features; - -import com.google.common.collect.ImmutableBiMap; -import com.google.common.collect.Lists; -import com.google.common.collect.ObjectArrays; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; +import javax.annotation.Nullable; import javax.inject.Inject; +import org.junit.After; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import org.junit.runner.RunWith; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase; +import org.opendaylight.ovsdb.lib.OvsdbClient; +import org.opendaylight.ovsdb.lib.notation.Version; +import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; import org.opendaylight.ovsdb.southbound.SouthboundProvider; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; +import org.opendaylight.ovsdb.southbound.SouthboundUtil; +import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; +import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase; @@ -51,15 +70,49 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.Mappings; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.MappingsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldpBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options; @@ -81,7 +134,10 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; @@ -89,11 +145,15 @@ import org.ops4j.pax.exam.karaf.options.LogLevelOption; import org.ops4j.pax.exam.options.MavenUrlReference; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; -import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + /** * Integration tests for southbound-impl * @@ -105,33 +165,155 @@ public class SouthboundIT extends AbstractMdsalTestBase { private static final String NETDEV_DP_TYPE = "netdev"; private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class); private static final int OVSDB_UPDATE_TIMEOUT = 1000; - private static DataBroker dataBroker = null; + private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000; + private static final String FORMAT_STR = "%s_%s_%d"; + private static final Version AUTOATTACH_FROM_VERSION = Version.fromString("7.11.2"); + private static final Version IF_INDEX_FROM_VERSION = Version.fromString("7.2.1"); private static String addressStr; - private static String portStr; + private static int portNumber; private static String connectionType; - private static String extrasStr; - private static Boolean setup = false; + private static boolean setup = false; private static MdsalUtils mdsalUtils = null; - //private static String extras = "false"; - private static final String NETVIRT = "org.opendaylight.ovsdb.openstack.net-virt"; - private static final String NETVIRTPROVIDERS = "org.opendaylight.ovsdb.openstack.net-virt-providers"; + private static Node ovsdbNode; + private static int testMethodsRemaining; + private static DataBroker dataBroker; + private static Version schemaVersion; + private static OvsdbClient ovsdbClient; + private static DatabaseSchema dbSchema; @Inject private BundleContext bundleContext; + private static final NotifyingDataChangeListener CONFIGURATION_LISTENER = + new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION); + private static final NotifyingDataChangeListener OPERATIONAL_LISTENER = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL); + + private static class NotifyingDataChangeListener implements DataChangeListener { + private final LogicalDatastoreType type; + private final Set> createdIids = new HashSet<>(); + private final Set> removedIids = new HashSet<>(); + private final Set> updatedIids = new HashSet<>(); + private final InstanceIdentifier iid; + private final int RETRY_WAIT = 100; + + private NotifyingDataChangeListener(LogicalDatastoreType type) { + this.type = type; + this.iid = null; + } + + private NotifyingDataChangeListener(LogicalDatastoreType type, InstanceIdentifier iid) { + this.type = type; + this.iid = iid; + } + + @Override + public void onDataChanged( + AsyncDataChangeEvent, DataObject> asyncDataChangeEvent) { + LOG.info("{} DataChanged: created {}", type, asyncDataChangeEvent.getCreatedData().keySet()); + LOG.info("{} DataChanged: removed {}", type, asyncDataChangeEvent.getRemovedPaths()); + LOG.info("{} DataChanged: updated {}", type, asyncDataChangeEvent.getUpdatedData().keySet()); + createdIids.addAll(asyncDataChangeEvent.getCreatedData().keySet()); + removedIids.addAll(asyncDataChangeEvent.getRemovedPaths()); + updatedIids.addAll(asyncDataChangeEvent.getUpdatedData().keySet()); + // Handled managed iids + for (DataObject obj : asyncDataChangeEvent.getCreatedData().values()) { + if (obj instanceof ManagedNodeEntry) { + ManagedNodeEntry managedNodeEntry = (ManagedNodeEntry) obj; + LOG.info("{} DataChanged: created managed {}", managedNodeEntry.getBridgeRef().getValue()); + createdIids.add(managedNodeEntry.getBridgeRef().getValue()); + } + } + synchronized(this) { + notifyAll(); + } + } + + public boolean isCreated(InstanceIdentifier iid) { + return createdIids.remove(iid); + } + + public boolean isRemoved(InstanceIdentifier iid) { + return removedIids.remove(iid); + } + + public boolean isUpdated(InstanceIdentifier iid) { + return updatedIids.remove(iid); + } + + public void clear() { + createdIids.clear(); + removedIids.clear(); + updatedIids.clear(); + } + + public void registerDataChangeListener() { + dataBroker.registerDataChangeListener(type, iid, this, AsyncDataBroker.DataChangeScope.SUBTREE); + } + + public void waitForCreation(long timeout) throws InterruptedException { + synchronized (this) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for {} DataChanged creation on {}", type, iid); + while (!isCreated(iid) && (System.currentTimeMillis() - _start) < timeout) { + wait(RETRY_WAIT); + } + LOG.info("Woke up, waited {}ms for creation of {}", (System.currentTimeMillis() - _start), iid); + } + } + + public void waitForDeletion(long timeout) throws InterruptedException { + synchronized (this) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for {} DataChanged deletion on {}", type, iid); + while (!isRemoved(iid) && (System.currentTimeMillis() - _start) < timeout) { + wait(RETRY_WAIT); + } + LOG.info("Woke up, waited {}ms for deletion of {}", (System.currentTimeMillis() - _start), iid); + } + } + + public void waitForUpdate(long timeout) throws InterruptedException { + synchronized (this) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for {} DataChanged update on {}", type, iid); + while (!isUpdated(iid) && (System.currentTimeMillis() - _start) < timeout) { + wait(RETRY_WAIT); + } + LOG.info("Woke up, waited {}ms for update of {}", (System.currentTimeMillis() - _start), iid); + } + } + + } + @Configuration public Option[] config() { - return super.config(); + Option[] options = super.config(); + Option[] propertyOptions = getPropertiesOptions(); + Option[] otherOptions = getOtherOptions(); + Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length]; + System.arraycopy(options, 0, combinedOptions, 0, options.length); + System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length); + System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length, + otherOptions.length); + return combinedOptions; } - @Override - public String getModuleName() { - return "southbound-impl"; + private Option[] getOtherOptions() { + return new Option[] { + vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"), + keepRuntimeFolder() + }; } @Override - public String getInstanceName() { - return "southbound-default"; + public String getKarafDistro() { + return maven() + .groupId("org.opendaylight.ovsdb") + .artifactId("southbound-karaf") + .versionAsInProject() + .type("zip") + .getURL(); } @Override @@ -146,8 +328,7 @@ public class SouthboundIT extends AbstractMdsalTestBase { @Override public String getFeatureName() { - //setExtras(); - return "odl-ovsdb-southbound-impl-ui"; + return "odl-ovsdb-southbound-test"; } protected String usage() { @@ -157,46 +338,15 @@ public class SouthboundIT extends AbstractMdsalTestBase { } @Override - public Option[] getFeaturesOptions(final boolean extras) { - if (extras == true) { - Option[] options = new Option[] { - features("mvn:org.opendaylight.ovsdb/features-ovsdb/1.1.0-SNAPSHOT/xml/features", - "odl-ovsdb-openstack-sb")}; - return options; - } else { - return new Option[]{}; - } - } - - @Override - public Option[] getLoggingOptions(final boolean extras) { - Option[] options = new Option[] { - /*editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG, - "log4j.logger.org.opendaylight.ovsdb", - LogLevelOption.LogLevel.DEBUG.name()),*/ - editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG, - "log4j.logger.org.opendaylight.ovsdb.southbound-impl", - LogLevelOption.LogLevel.DEBUG.name()) - }; - - if (extras == true) { - Option[] extraOptions = new Option[] { + public Option getLoggingOption() { + return composite( editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG, "log4j.logger.org.opendaylight.ovsdb", - LogLevelOption.LogLevel.DEBUG.name()), - editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG, - "log4j.logger.org.opendaylight.ovsdb.openstack.net-virt", - LogLevelOption.LogLevel.DEBUG.name()) - }; - options = ObjectArrays.concat(options, extraOptions, Option.class); - } - - options = ObjectArrays.concat(options, super.getLoggingOptions(extras), Option.class); - return options; + LogLevelOption.LogLevel.TRACE.name()), + super.getLoggingOption()); } - @Override - public Option[] getPropertiesOptions(final boolean extras) { + private Option[] getPropertiesOptions() { Properties props = new Properties(System.getProperties()); String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS, SouthboundITConstants.DEFAULT_SERVER_IPADDRESS); @@ -204,45 +354,36 @@ public class SouthboundIT extends AbstractMdsalTestBase { SouthboundITConstants.DEFAULT_SERVER_PORT); String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE, SouthboundITConstants.CONNECTION_TYPE_ACTIVE); - String extrasStr = props.getProperty(SouthboundITConstants.SERVER_EXTRAS, - SouthboundITConstants.DEFAULT_SERVER_EXTRAS); - LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}, extras= {}", - connectionType, addressStr, portStr, extrasStr); + LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}", + connectionType, addressStr, portStr); - Option[] options = new Option[] { + return new Option[] { + propagateSystemProperties( + SouthboundITConstants.SERVER_IPADDRESS, + SouthboundITConstants.SERVER_PORT, + SouthboundITConstants.CONNECTION_TYPE), editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES, SouthboundITConstants.SERVER_IPADDRESS, addressStr), editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES, SouthboundITConstants.SERVER_PORT, portStr), editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES, SouthboundITConstants.CONNECTION_TYPE, connectionType), - editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES, - SouthboundITConstants.SERVER_EXTRAS, extrasStr) }; - return options; - } - - - public boolean setExtras() { - Properties props = new Properties(System.getProperties()); - boolean extras = props.getProperty(SouthboundITConstants.SERVER_EXTRAS, - SouthboundITConstants.DEFAULT_SERVER_EXTRAS).equals("true"); - LOG.info("setExtras: {}", extras); - return extras; } @Before - public void setUp() throws InterruptedException { - if (setup == true) { - LOG.info("Skipping setUp, already initialized"); + @Override + public void setup() throws InterruptedException { + if (setup) { + LOG.info("Skipping setup, already initialized"); return; } try { super.setup(); } catch (Exception e) { - e.printStackTrace(); + LOG.warn("Failed to setup test", e); } //dataBroker = getSession().getSALService(DataBroker.class); Thread.sleep(3000); @@ -250,12 +391,16 @@ public class SouthboundIT extends AbstractMdsalTestBase { Assert.assertNotNull("db should not be null", dataBroker); addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS); - portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT); + String portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT); + try { + portNumber = Integer.parseInt(portStr); + } catch (NumberFormatException e) { + fail("Invalid port number " + portStr + System.lineSeparator() + usage()); + } connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE); - extrasStr = bundleContext.getProperty(SouthboundITConstants.SERVER_EXTRAS); - LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, extras= {}", - connectionType, addressStr, portStr, extrasStr); + LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}", + connectionType, addressStr, portNumber); if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) { if (addressStr == null) { fail(usage()); @@ -263,17 +408,64 @@ public class SouthboundIT extends AbstractMdsalTestBase { } mdsalUtils = new MdsalUtils(dataBroker); + final ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + final InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo); + dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + iid, CONFIGURATION_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE); + dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + iid, OPERATIONAL_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE); + + ovsdbNode = connectOvsdbNode(connectionInfo); + try { + ovsdbClient = SouthboundIntegrationTestUtils.getTestConnection(this); + assertNotNull("Invalid Client. Check connection params", ovsdbClient); + + dbSchema = ovsdbClient.getSchema(SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA).get(); + assertNotNull("Invalid dbSchema.", dbSchema); + schemaVersion = dbSchema.getVersion(); + LOG.info("{} schema version = {}", SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA, schemaVersion); + } catch (Exception e) { + fail("Error accessing schemaVersion in SouthboundIT setUp()." + usage()); + } + + // Let's count the test methods (we need to use this instead of @AfterClass on teardown() since the latter is + // useless with pax-exam) + for (Method method : getClass().getMethods()) { + boolean testMethod = false; + boolean ignoreMethod = false; + for (Annotation annotation : method.getAnnotations()) { + if (Test.class.equals(annotation.annotationType())) { + testMethod = true; + } + if (Ignore.class.equals(annotation.annotationType())) { + ignoreMethod = true; + } + } + if (testMethod && !ignoreMethod) { + testMethodsRemaining++; + } + } + LOG.info("{} test methods to run", testMethodsRemaining); + setup = true; + } - if (extrasStr.equals("true")) { - isBundleReady(bundleContext, NETVIRT); - isBundleReady(bundleContext, NETVIRTPROVIDERS); + @After + public void teardown() { + testMethodsRemaining--; + LOG.info("{} test methods remaining", testMethodsRemaining); + if (testMethodsRemaining == 0) { + try { + disconnectOvsdbNode(getConnectionInfo(addressStr, portNumber)); + } catch (InterruptedException e) { + LOG.warn("Interrupted while disconnecting", e); + } } } /** * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port - * 6640. This test will wait for incoming connections for {@link SouthboundITConstants.CONNECTION_INIT_TIMEOUT} ms. + * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms. * * @throws InterruptedException */ @@ -285,29 +477,23 @@ public class SouthboundIT extends AbstractMdsalTestBase { } } - private ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) { + private static ConnectionInfo getConnectionInfo(final String addressStr, final int portNumber) { InetAddress inetAddress = null; try { inetAddress = InetAddress.getByName(addressStr); } catch (UnknownHostException e) { - fail("Could not allocate InetAddress: " + e); + fail("Could not resolve " + addressStr + ": " + e); } IpAddress address = SouthboundMapper.createIpAddress(inetAddress); - PortNumber port = new PortNumber(Integer.parseInt(portStr)); + PortNumber port = new PortNumber(portNumber); - LOG.info("connectionInfo: {}", new ConnectionInfoBuilder() + final ConnectionInfo connectionInfo = new ConnectionInfoBuilder() .setRemoteIp(address) .setRemotePort(port) - .build()); - return new ConnectionInfoBuilder() - .setRemoteIp(address) - .setRemotePort(port) - .build(); - } - - private String connectionInfoToString(final ConnectionInfo connectionInfo) { - return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue(); + .build(); + LOG.info("connectionInfo: {}", connectionInfo); + return connectionInfo; } @Test @@ -339,129 +525,152 @@ public class SouthboundIT extends AbstractMdsalTestBase { topology); } - private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { - boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, - SouthboundMapper.createInstanceIdentifier(connectionInfo), - SouthboundMapper.createNode(connectionInfo)); - Thread.sleep(OVSDB_UPDATE_TIMEOUT); - return result; + private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { + final InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo); + Assert.assertTrue( + mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, SouthboundUtils.createNode(connectionInfo))); + waitForOperationalCreation(iid); + Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid); + Assert.assertNotNull(node); + LOG.info("Connected to {}", SouthboundUtils.connectionInfoToString(connectionInfo)); + return node; } - private Node getOvsdbNode(final ConnectionInfo connectionInfo) { - Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, - SouthboundMapper.createInstanceIdentifier(connectionInfo)); - return node; + private void waitForOperationalCreation(InstanceIdentifier iid) throws InterruptedException { + synchronized (OPERATIONAL_LISTENER) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for OPERATIONAL DataChanged creation on {}", iid); + while (!OPERATIONAL_LISTENER.isCreated( + iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) { + OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT); + } + LOG.info("Woke up, waited {} for creation of {}", (System.currentTimeMillis() - _start), iid); + } } - private boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { - boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, - SouthboundMapper.createInstanceIdentifier(connectionInfo)); - Thread.sleep(OVSDB_UPDATE_TIMEOUT); - return result; + private static void waitForOperationalDeletion(InstanceIdentifier iid) throws InterruptedException { + synchronized (OPERATIONAL_LISTENER) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for OPERATIONAL DataChanged deletion on {}", iid); + while (!OPERATIONAL_LISTENER.isRemoved( + iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) { + OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT); + } + LOG.info("Woke up, waited {} for deletion of {}", (System.currentTimeMillis() - _start), iid); + } } - private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { - Assert.assertTrue(addOvsdbNode(connectionInfo)); - Node node = getOvsdbNode(connectionInfo); - Assert.assertNotNull(node); - LOG.info("Connected to {}", connectionInfoToString(connectionInfo)); - return node; + private void waitForOperationalUpdate(InstanceIdentifier iid) throws InterruptedException { + synchronized (OPERATIONAL_LISTENER) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for OPERATIONAL DataChanged update on {}", iid); + while (!OPERATIONAL_LISTENER.isUpdated( + iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) { + OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT); + } + LOG.info("Woke up, waited {} for update of {}", (System.currentTimeMillis() - _start), iid); + } } - private boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { - Assert.assertTrue(deleteOvsdbNode(connectionInfo)); - Node node = getOvsdbNode(connectionInfo); + private static void disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { + final InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo); + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid)); + waitForOperationalDeletion(iid); + Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid); Assert.assertNull(node); - //Assume.assumeNotNull(node); // Using assumeNotNull because there is no assumeNull - LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo)); - return true; + LOG.info("Disconnected from {}", SouthboundUtils.connectionInfoToString(connectionInfo)); } @Test public void testAddDeleteOvsdbNode() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - Node ovsdbNode = connectOvsdbNode(connectionInfo); - Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); - //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo)); + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + // At this point we're connected, disconnect and reconnect (the connection will be removed at the very end) + disconnectOvsdbNode(connectionInfo); + connectOvsdbNode(connectionInfo); } @Test public void testDpdkSwitch() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - Node ovsdbNode = connectOvsdbNode(connectionInfo); + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); List datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class) .getDatapathTypeEntry(); if (datapathTypeEntries == null) { LOG.info("DPDK not supported on this node."); } else { - Class dpType = null; - String dpTypeStr = null; for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) { - dpType = dpTypeEntry.getDatapathType(); - dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType); + Class dpType = dpTypeEntry.getDatapathType(); + String dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType); LOG.info("dp type is {}", dpTypeStr); if (dpTypeStr.equals(NETDEV_DP_TYPE)) { LOG.info("Found a DPDK node; adding a corresponding netdev device"); - InstanceIdentifier bridgeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo, + InstanceIdentifier bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)); - NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid); - addBridge(connectionInfo, bridgeIid, SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null, - true, dpType); - - // Verify that the device is netdev - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - Assert.assertEquals(dpType, bridge.getDatapathType()); - - // Add dpdk port - final String TEST_PORT_NAME = "testDPDKPort"; - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericDpdkOvsdbTerminationPointAugmentationBuilder(TEST_PORT_NAME); - Assert.assertTrue(addTerminationPoint(bridgeNodeId, TEST_PORT_NAME, ovsdbTerminationBuilder)); - - // Verify that DPDK port was created - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, - terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - // Verify that each termination point has DPDK ifType - Class dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP - .get("dpdk"); - Class opPort = null; - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint - .getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(TEST_PORT_NAME)) { - opPort = ovsdbTerminationPointAugmentation - .getInterfaceType(); - Assert.assertEquals(dpdkIfType, opPort); + NodeId bridgeNodeId = SouthboundUtils.createManagedNodeId(bridgeIid); + try (TestBridge testBridge = new TestBridge(connectionInfo, bridgeIid, + SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null, true, dpType, null, null, + null)) { + // Verify that the device is netdev + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + Assert.assertEquals(dpType, bridge.getDatapathType()); + + // Add port for all dpdk interface types (dpdkvhost not supported in existing dpdk ovs) + List dpdkTypes = new ArrayList(); + dpdkTypes.add("dpdk"); + dpdkTypes.add("dpdkr"); + dpdkTypes.add("dpdkvhostuser"); + //dpdkTypes.add("dpdkvhost"); + + for (String dpdkType : dpdkTypes) { + String testPortname = "test"+dpdkType+"port"; + LOG.info("DPDK portname and type is {}, {}", testPortname, dpdkType); + Class dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP + .get(dpdkType); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationpointBuilder = + createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(testPortname, + dpdkIfType); + Assert.assertTrue( + addTerminationPoint(bridgeNodeId, testPortname, ovsdbTerminationpointBuilder)); + } + + // Verify that all DPDK ports are created + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, + terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + // Verify that each termination point has the specific DPDK ifType + for (String dpdkType : dpdkTypes) { + String testPortname = "test"+dpdkType+"port"; + Class dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP + .get(dpdkType); + List terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint + .getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(testPortname)) { + Class opPort = ovsdbTerminationPointAugmentation + .getInterfaceType(); + Assert.assertEquals(dpdkIfType, opPort); + } + } } } - Assert.assertTrue(deleteBridge(connectionInfo)); - break; } + break; } } - Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); } @Test public void testOvsdbNodeOvsVersion() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - Node ovsdbNode = connectOvsdbNode(connectionInfo); OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class); Assert.assertNotNull(ovsdbNodeAugmentation); assertNotNull(ovsdbNodeAugmentation.getOvsVersion()); - Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); - //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo)); } @Test public void testOpenVSwitchOtherConfig() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - Node ovsdbNode = connectOvsdbNode(connectionInfo); OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class); Assert.assertNotNull(ovsdbNodeAugmentation); List otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs(); @@ -477,22 +686,50 @@ public class SouthboundIT extends AbstractMdsalTestBase { } else { LOG.info("other_config is not present"); } - Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); - //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo)); } - private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder, + @Test + public void testOvsdbBridgeControllerInfo() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portNumber); + String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode); + assertNotNull("Failed to get controller target", controllerTarget); + List setControllerEntry = createControllerEntry(controllerTarget); + Uri setUri = new Uri(controllerTarget); + try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true, + SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, + setControllerEntry, null)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME, bridge); + Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(), + bridge.getControllerEntry()); + List getControllerEntries = bridge.getControllerEntry(); + for (ControllerEntry entry : getControllerEntries) { + if (entry.getTarget() != null) { + Assert.assertEquals(setUri.toString(), entry.getTarget().toString()); + } + } + } + } + + private List createControllerEntry(String controllerTarget) { + List controllerEntriesList = new ArrayList<>(); + controllerEntriesList.add(new ControllerEntryBuilder() + .setTarget(new Uri(controllerTarget)) + .build()); + return controllerEntriesList; + } + + private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder, final ConnectionInfo connectionInfo) { - InstanceIdentifier connectionNodePath = SouthboundMapper.createInstanceIdentifier(connectionInfo); + InstanceIdentifier connectionNodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo); ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath)); } - private List createMdsalProtocols() { - List protocolList = new ArrayList(); + private static List createMdsalProtocols() { + List protocolList = new ArrayList<>(); ImmutableBiMap> mapper = SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse(); - protocolList.add(new ProtocolEntryBuilder(). - setProtocol((Class) mapper.get("OpenFlow13")).build()); + protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build()); return protocolList; } @@ -518,9 +755,19 @@ public class SouthboundIT extends AbstractMdsalTestBase { return ovsdbTerminationBuilder; } + private OvsdbTerminationPointAugmentationBuilder createSpecificDpdkOvsdbTerminationPointAugmentationBuilder( + String testPortname,Class dpdkIfType) { + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + ovsdbTerminationBuilder.setName(testPortname); + ovsdbTerminationBuilder.setInterfaceType(dpdkIfType); + return ovsdbTerminationBuilder; + } + private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName, - final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder) - throws InterruptedException { + final OvsdbTerminationPointAugmentationBuilder + ovsdbTerminationPointAugmentationBuilder) + throws InterruptedException { InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId); NodeBuilder portNodeBuilder = new NodeBuilder(); @@ -538,595 +785,2334 @@ public class SouthboundIT extends AbstractMdsalTestBase { return result; } - /* - * base method for adding test bridges. Other helper methods used to create bridges should utilize this method. - * - * @param connectionInfo - * @param bridgeIid if passed null, one is created - * @param bridgeName cannot be null - * @param bridgeNodeId if passed null, one is created based on bridgeIid - * @param setProtocolEntries toggles whether default protocol entries are set for the bridge - * @param failMode toggles whether default fail mode is set for the bridge - * @param setManagedBy toggles whether to setManagedBy for the bridge - * @param dpType if passed null, this parameter is ignored - * @return success of bridge addition - * @throws InterruptedException - */ - private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier bridgeIid, - final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries, - final Class failMode, final boolean setManagedBy, - final Class dpType) throws InterruptedException { - - NodeBuilder bridgeNodeBuilder = new NodeBuilder(); - if (bridgeIid == null) { - bridgeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)); - } - if (bridgeNodeId == null) { - bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid); - } - bridgeNodeBuilder.setNodeId(bridgeNodeId); - OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder(); - ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName)); - if (setProtocolEntries) { - ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols()); - } - if (failMode != null) { + private static class TestBridge implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final String bridgeName; + + /** + * Creates a test bridge which can be automatically removed when no longer necessary. + * + * @param connectionInfo The connection information. + * @param bridgeIid The bridge identifier; if {@code null}, one is created based on {@code bridgeName}. + * @param bridgeName The bridge name; must be provided. + * @param bridgeNodeId The bridge node identifier; if {@code null}, one is created based on {@code bridgeIid}. + * @param setProtocolEntries {@code true} to set default protocol entries for the bridge. + * @param failMode The fail mode to set for the bridge. + * @param setManagedBy {@code true} to specify {@code setManagedBy} for the bridge. + * @param dpType The datapath type. + * @param externalIds The external identifiers if any. + * @param otherConfigs The other configuration items if any. + */ + public TestBridge(final ConnectionInfo connectionInfo, @Nullable InstanceIdentifier bridgeIid, + final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries, + final Class failMode, final boolean setManagedBy, + @Nullable final Class dpType, + @Nullable final List externalIds, + @Nullable final List controllerEntries, + @Nullable final List otherConfigs) { + this.connectionInfo = connectionInfo; + this.bridgeName = bridgeName; + NodeBuilder bridgeNodeBuilder = new NodeBuilder(); + if (bridgeIid == null) { + bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)); + } + if (bridgeNodeId == null) { + bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid); + } + bridgeNodeBuilder.setNodeId(bridgeNodeId); + OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder(); + ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName)); + if (setProtocolEntries) { + ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols()); + } ovsdbBridgeAugmentationBuilder.setFailMode(failMode); - } - if (setManagedBy) { - setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo); - } - if (dpType != null) { + if (setManagedBy) { + setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo); + } ovsdbBridgeAugmentationBuilder.setDatapathType(dpType); + ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds); + ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries); + ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs); + bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build()); + LOG.debug("Built with the intent to store bridge data {}", ovsdbBridgeAugmentationBuilder.toString()); + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build())); + try { + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for bridge creation (bridge {})", bridgeName, e); + } } - bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build()); - LOG.debug("Built with the intent to store bridge data {}", - ovsdbBridgeAugmentationBuilder.toString()); - boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, - bridgeIid, bridgeNodeBuilder.build()); - Thread.sleep(OVSDB_UPDATE_TIMEOUT); - return result; - } - - private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName) - throws InterruptedException { - return addBridge(connectionInfo, null, bridgeName, null, true, - SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null); - } + public TestBridge(final ConnectionInfo connectionInfo, final String bridgeName) { + this(connectionInfo, null, bridgeName, null, true, + SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null); + } - private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) { - InstanceIdentifier bridgeIid = - SouthboundMapper.createInstanceIdentifier(connectionInfo, - new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)); - Node bridgeNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid); - Assert.assertNotNull(bridgeNode); - OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class); - Assert.assertNotNull(ovsdbBridgeAugmentation); - return ovsdbBridgeAugmentation; + @Override + public void close() { + final InstanceIdentifier iid = + SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)); + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid)); + try { + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for bridge deletion (bridge {})", bridgeName, e); + } + } } - private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException { - boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, - SouthboundMapper.createInstanceIdentifier(connectionInfo, - new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))); - Thread.sleep(OVSDB_UPDATE_TIMEOUT); - return result; + private static class TestAutoAttach implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final Uri autoattachId; + private final Uri bridgeId; + + public TestAutoAttach (final ConnectionInfo connectionInfo, + final Uri autoattachId, + final Uri bridgeId, + @Nullable final String systemName, + @Nullable final String systemDescription, + @Nullable final List mappings, + @Nullable final List externalIds) { + this.connectionInfo = connectionInfo; + this.autoattachId = autoattachId; + this.bridgeId = bridgeId; + + Autoattach aaEntry = new AutoattachBuilder() + .setAutoattachId(autoattachId) + .setBridgeId(bridgeId) + .setSystemName(systemName) + .setSystemDescription(systemDescription) + .setMappings(mappings) + .setAutoattachExternalIds(externalIds) + .build(); + InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Autoattach.class, aaEntry.getKey()); + final NotifyingDataChangeListener aaOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid); + aaOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, aaEntry)); + try { + aaOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue {}", iid, e); + } + } + @Override + public void close() { + final InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Autoattach.class, new AutoattachKey(this.autoattachId)); + final NotifyingDataChangeListener aaOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid); + aaOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid)); + try { + aaOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", iid, e); + } + } } @Test - public void testAddDeleteBridge() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - Node ovsdbNode = connectOvsdbNode(connectionInfo); - - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - LOG.info("bridge: {}", bridge); + public void testCRUDAutoAttach() throws InterruptedException { + final boolean isOldSchema = schemaVersion.compareTo(AUTOATTACH_FROM_VERSION) < 0; - Assert.assertTrue(deleteBridge(connectionInfo)); - - Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); - //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo)); - } + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testAutoattachId = new String("testAutoattachEntry"); + String testSystemName = new String("testSystemName"); + String testSystemDescription = new String("testSystemDescription"); + String testAutoattachExternalKey = new String("testAutoattachExternalKey"); + String testAutoattachExternalValue = new String("testAutoattachExternalValue"); - private InstanceIdentifier getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) { - return SouthboundMapper.createInstanceIdentifier(connectionInfo, - bridge.getBridgeName()); - } + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); - @Test - public void testTerminationPointOfPort() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); + // CREATE: Create Autoattach table + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + String bridgeId = nodeId.getValue(); + try(TestAutoAttach testAutoattach = new TestAutoAttach(connectionInfo, new Uri(testAutoattachId), + new Uri(bridgeId), testSystemName, testSystemDescription, null, null)) { + // READ: Read md-sal operational datastore to see if the AutoAttach table was created + // and if Bridge table was updated with AutoAttach Uuid + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Autoattach operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId)); + + // skip tests after verifying that Autoattach doesn't break with unsupported schema + Assume.assumeFalse(isOldSchema); + + // FIXME: Remove once CRUD is supported + Assume.assumeFalse(operAa == null); + + Assert.assertNotNull(operAa); + Assert.assertEquals(testSystemName, operAa.getSystemName()); + bridge = getBridge(connectionInfo); + Uuid aaUuid = new Uuid(operAa.getAutoattachUuid().getValue()); + Assert.assertEquals(aaUuid, bridge.getAutoAttach()); + + // UPDATE: Update mappings column of AutoAttach table that was created + List mappings = ImmutableList.of(new MappingsBuilder().setMappingsKey(100L).setMappingsValue(200).build()); + Autoattach updatedAa = new AutoattachBuilder() + .setAutoattachId(new Uri(testAutoattachId)) + .setMappings(mappings) + .build(); + InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Autoattach.class, updatedAa.getKey()); + final NotifyingDataChangeListener aaOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid); + aaOperationalListener.registerDataChangeListener(); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa)); + aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // UPDATE: Update external_ids column of AutoAttach table that was created + List externalIds = new ArrayList<>(); + externalIds.add(new AutoattachExternalIdsBuilder() + .setAutoattachExternalIdKey(testAutoattachExternalKey) + .setAutoattachExternalIdValue(testAutoattachExternalValue) + .build()); + updatedAa = new AutoattachBuilder() + .setAutoattachId(new Uri(testAutoattachId)) + .setAutoattachExternalIds(externalIds) + .build(); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa)); + aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the updated AutoAttach table for latest mappings and external_ids column value + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId)); + Assert.assertNotNull(operAa); + List operMappingsList = operAa.getMappings(); + for (Mappings operMappings: operMappingsList) { + Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsKey(), operMappings.getMappingsKey()); + Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsValue(), operMappings.getMappingsValue()); + } + List operExternalIds = operAa.getAutoattachExternalIds(); + externalIds.add(new AutoattachExternalIdsBuilder() + .setAutoattachExternalIdKey(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY) + .setAutoattachExternalIdValue(operAa.getAutoattachId().getValue()) + .build()); + for (AutoattachExternalIds operExternalId : operExternalIds) { + Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdKey(), + operExternalId.getAutoattachExternalIdKey()); + Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdValue(), + operExternalId.getAutoattachExternalIdValue()); + } - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - LOG.info("bridge: {}", bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testOfPort"; - ovsdbTerminationBuilder.setName(portName); - Long ofPortExpected = new Long(45002); - ovsdbTerminationBuilder.setOfport(ofPortExpected); - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - Long ofPort = ovsdbTerminationPointAugmentation.getOfport(); - // if ephemeral port 45002 is in use, ofPort is set to 1 - Assert.assertTrue(ofPort.equals(ofPortExpected) || ofPort.equals(new Long(1))); - LOG.info("ofPort: {}", ofPort); + // DELETE: Delete AutoAttach table + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid)); + aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId)); + Assert.assertNull(operAa); + } catch (AssumptionViolatedException e) { + LOG.warn("Skipped test for Autoattach due to unsupported schema", e); + } catch (Exception e) { + fail("Unexpected exception in CRUD test for Autoattach table for schema:" + schemaVersion.toString() +". " + e); } } - Assert.assertTrue(deleteBridge(connectionInfo)); } - @Test - public void testTerminationPointOfPortRequest() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testOfPortRequest"; - ovsdbTerminationBuilder.setName(portName); - Long ofPortExpected = new Long(45008); - Integer ofPortRequestExpected = ofPortExpected.intValue(); - Long ofPortInput = new Long(45008); - ovsdbTerminationBuilder.setOfport(ofPortInput); - ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected); - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - Long ofPort = ovsdbTerminationPointAugmentation.getOfport(); - // if ephemeral port 45002 is in use, ofPort is set to 1 - Assert.assertTrue(ofPort.equals(ofPortExpected) || ofPort.equals(new Long(1))); - LOG.info("ofPort: {}", ofPort); - - Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest(); - Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected)); - LOG.info("ofPortRequest: {}", ofPortRequest); + private Autoattach getAutoAttach(OvsdbNodeAugmentation ovsdbNodeAugmentation, Uri uri) { + if (ovsdbNodeAugmentation.getAutoattach() != null + && !ovsdbNodeAugmentation.getAutoattach().isEmpty()) { + for (Autoattach aa : ovsdbNodeAugmentation.getAutoattach()) { + if (aa.getKey().getAutoattachId().equals(uri)) { + return aa; + } } } - Assert.assertTrue(deleteBridge(connectionInfo)); + return null; } - @Test - public void testTerminationPointPortExternalIds() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testPortExternalIds"; - ovsdbTerminationBuilder.setName(portName); - //setup - PortExternalIdsBuilder externalIdsBuilder1 = new PortExternalIdsBuilder(); - externalIdsBuilder1.setExternalIdKey("portExternalIdKey1"); - externalIdsBuilder1.setExternalIdValue("portExternalIdValue1"); - PortExternalIdsBuilder externalIdsBuilder2 = new PortExternalIdsBuilder(); - externalIdsBuilder2.setExternalIdKey("portExternalIdKey2"); - externalIdsBuilder2.setExternalIdValue("portExternalIdValue2"); - List portExternalIds = Lists.newArrayList(externalIdsBuilder1.build(), - externalIdsBuilder2.build()); - ovsdbTerminationBuilder.setPortExternalIds(portExternalIds); - - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - List actualPortExternalIds = ovsdbTerminationPointAugmentation.getPortExternalIds(); - Assert.assertTrue((portExternalIds.size() == actualPortExternalIds.size())); - for (PortExternalIds portExternalId : portExternalIds) { - Assert.assertTrue(actualPortExternalIds.contains(portExternalId)); - } + private static class TestQos implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final Uri qosId; + + /** + * Creates a test qos entry which can be automatically removed when no longer necessary. + * + * @param connectionInfo The connection information. + * @param qosId The Qos identifier. + * @param qosType The qos type. + * @param externalIds The external identifiers if any. + * @param otherConfigs The other configuration items if any. + */ + public TestQos(final ConnectionInfo connectionInfo, + final Uri qosId, + final Class qosType, + @Nullable final List externalIds, + @Nullable final List otherConfigs) { + this.connectionInfo = connectionInfo; + this.qosId = qosId; + + QosEntries qosEntry = new QosEntriesBuilder() + .setQosId(qosId) + .setQosType(qosType) + .setQosExternalIds(externalIds) + .setQosOtherConfig(otherConfigs) + .build(); + InstanceIdentifier qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, qosEntry.getKey()); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid); + qosOperationalListener.registerDataChangeListener(); + + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qeIid, qosEntry)); + + try { + qosOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue {}", qeIid, e); } + } - Assert.assertTrue(deleteBridge(connectionInfo)); - } - @Test - public void testTerminationPointInterfaceExternalIds() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testInterfaceExternalIds"; - ovsdbTerminationBuilder.setName(portName); - //setup - InterfaceExternalIdsBuilder externalIdsBuilder1 = new InterfaceExternalIdsBuilder(); - externalIdsBuilder1.setExternalIdKey("interfaceExternalIdKey1"); - externalIdsBuilder1.setExternalIdValue("interfaceExternalIdValue1"); - InterfaceExternalIdsBuilder externalIdsBuilder2 = new InterfaceExternalIdsBuilder(); - externalIdsBuilder2.setExternalIdKey("interfaceExternalIdKey2"); - externalIdsBuilder2.setExternalIdValue("interfaceExternalIdValue2"); - List interfaceExternalIds = Lists.newArrayList(externalIdsBuilder1.build(), - externalIdsBuilder2.build()); - ovsdbTerminationBuilder.setInterfaceExternalIds(interfaceExternalIds); - - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - List actualInterfaceExternalIds = ovsdbTerminationPointAugmentation. - getInterfaceExternalIds(); - Assert.assertTrue((interfaceExternalIds.size() == actualInterfaceExternalIds.size())); - for (InterfaceExternalIds interfaceExternalId : interfaceExternalIds) { - Assert.assertTrue(actualInterfaceExternalIds.contains(interfaceExternalId)); - } + @Override + public void close() { + final InstanceIdentifier qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, new QosEntriesKey(this.qosId)); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid); + qosOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qeIid)); + try { + qosOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", qeIid, e); } } - Assert.assertTrue(deleteBridge(connectionInfo)); } - @Test - public void testTerminationPointOptions() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testInterfaceOptions"; - ovsdbTerminationBuilder.setName(portName); - //setup - OptionsBuilder optionsBuilder1 = new OptionsBuilder(); - optionsBuilder1.setOption("option1"); - optionsBuilder1.setValue("optionValue1"); - OptionsBuilder optionsBuilder2 = new OptionsBuilder(); - optionsBuilder2.setOption("option2"); - optionsBuilder2.setValue("optionValue2"); - List options = Lists.newArrayList(optionsBuilder1.build(), - optionsBuilder2.build()); - ovsdbTerminationBuilder.setOptions(options); - - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - List actualOptions = ovsdbTerminationPointAugmentation. - getOptions(); - Assert.assertTrue((options.size() == actualOptions.size())); - for (Options option : options) { - Assert.assertTrue(actualOptions.contains(option)); - } + private static class TestQueue implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final Uri queueId; + + /** + * Creates a test queue entry which can be automatically removed when no longer necessary. + * + * @param connectionInfo The connection information. + * @param queueId The Queue identifier. + * @param queueDscp The queue dscp value. + * @param externalIds The external identifiers if any. + * @param otherConfigs The other configuration items if any. + */ + public TestQueue(final ConnectionInfo connectionInfo, + final Uri queueId, + final Short queueDscp, + @Nullable final List externalIds, + @Nullable final List otherConfigs) { + this.connectionInfo = connectionInfo; + this.queueId = queueId; + + Queues queue = new QueuesBuilder() + .setQueueId(queueId) + .setDscp(queueDscp) + .setQueuesExternalIds(externalIds) + .setQueuesOtherConfig(otherConfigs) + .build(); + InstanceIdentifier qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, queue.getKey()); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid); + queueOperationalListener.registerDataChangeListener(); + + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qIid, queue)); + + try { + queueOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue {}", queueId, e); } } - Assert.assertTrue(deleteBridge(connectionInfo)); - } - @Test - public void testTerminationPointInterfaceOtherConfigs() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testInterfaceOtherConfigs"; - ovsdbTerminationBuilder.setName(portName); - //setup - InterfaceOtherConfigsBuilder interfaceBuilder1 = new InterfaceOtherConfigsBuilder(); - interfaceBuilder1.setOtherConfigKey("interfaceOtherConfigsKey1"); - interfaceBuilder1.setOtherConfigValue("interfaceOtherConfigsValue1"); - InterfaceOtherConfigsBuilder interfaceBuilder2 = new InterfaceOtherConfigsBuilder(); - interfaceBuilder2.setOtherConfigKey("interfaceOtherConfigsKey2"); - interfaceBuilder2.setOtherConfigValue("interfaceOtherConfigsValue2"); - List interfaceOtherConfigs = Lists.newArrayList(interfaceBuilder1.build(), - interfaceBuilder2.build()); - ovsdbTerminationBuilder.setInterfaceOtherConfigs(interfaceOtherConfigs); - - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - Thread.sleep(1000); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - List actualInterfaceOtherConfigs = ovsdbTerminationPointAugmentation. - getInterfaceOtherConfigs(); - Assert.assertNotNull(actualInterfaceOtherConfigs); - Assert.assertNotNull(interfaceOtherConfigs); - Assert.assertTrue(interfaceOtherConfigs.size() == actualInterfaceOtherConfigs.size()); - for (InterfaceOtherConfigs interfaceOtherConfig : interfaceOtherConfigs) { - Assert.assertTrue(actualInterfaceOtherConfigs.contains(interfaceOtherConfig)); - } + @Override + public void close() { + InstanceIdentifier qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, new QueuesKey(this.queueId)); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid); + queueOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qIid)); + try { + queueOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue deletion (queue {})", queueId, e); } } - Assert.assertTrue(deleteBridge(connectionInfo)); } - @Test - public void testTerminationPointPortOtherConfigs() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testPortOtherConfigs"; - ovsdbTerminationBuilder.setName(portName); - //setup - PortOtherConfigsBuilder portBuilder1 = new PortOtherConfigsBuilder(); - portBuilder1.setOtherConfigKey("portOtherConfigsKey1"); - portBuilder1.setOtherConfigValue("portOtherConfigsValue1"); - PortOtherConfigsBuilder portBuilder2 = new PortOtherConfigsBuilder(); - portBuilder2.setOtherConfigKey("portOtherConfigsKey2"); - portBuilder2.setOtherConfigValue("portOtherConfigsValue2"); - List portOtherConfigs = Lists.newArrayList(portBuilder1.build(), - portBuilder2.build()); - ovsdbTerminationBuilder.setPortOtherConfigs(portOtherConfigs); - - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); - - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - List actualPortOtherConfigs = ovsdbTerminationPointAugmentation. - getPortOtherConfigs(); - Assert.assertTrue((portOtherConfigs.size() == actualPortOtherConfigs.size())); - for (PortOtherConfigs portOtherConfig : portOtherConfigs) { - Assert.assertTrue(actualPortOtherConfigs.contains(portOtherConfig)); - } - } - } - Assert.assertTrue(deleteBridge(connectionInfo)); + private OvsdbNodeAugmentation getOvsdbNode(ConnectionInfo connectionInfo, LogicalDatastoreType store) { + InstanceIdentifier nodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo); + Node node = mdsalUtils.read(store, nodeIid); + Assert.assertNotNull(node); + OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class); + Assert.assertNotNull(ovsdbNodeAugmentation); + return ovsdbNodeAugmentation; } - @Test - public void testTerminationPointVlan() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testTerminationPointVlanId"; - ovsdbTerminationBuilder.setName(portName); - //setup - Integer vlanId = new Integer(4000); - ovsdbTerminationBuilder.setVlanTag(new VlanId(vlanId)); + private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) { + return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); + } - Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); - InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); - Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); - Assert.assertNotNull(terminationPointNode); + /** + * Extract the store type data store contents for the particular bridge identified by + * bridgeName. + * + * @param connectionInfo the connection information + * @param bridgeName the bridge name + * @param store defined by the LogicalDatastoreType enumeration + * @return store type data store contents + */ + private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName, + LogicalDatastoreType store) { + Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store); + Assert.assertNotNull(bridgeNode); + OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class); + Assert.assertNotNull(ovsdbBridgeAugmentation); + return ovsdbBridgeAugmentation; + } - List terminationPoints = terminationPointNode.getTerminationPoint(); - for (TerminationPoint terminationPoint : terminationPoints) { - OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = - terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); - if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - //test - VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag(); - Assert.assertNotNull(actualVlanId); - Integer actualVlanIdInt = actualVlanId.getValue(); - Assert.assertTrue(actualVlanIdInt.equals(vlanId)); - } - } - Assert.assertTrue(deleteBridge(connectionInfo)); + /** + * extract the LogicalDataStoreType.OPERATIONAL type data store contents for the particular bridge + * identified by bridgeName + * + * @param connectionInfo the connection information + * @param bridgeName the bridge name + * @see SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType) + * @return LogicalDatastoreType.OPERATIONAL type data store contents + */ + private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) { + return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL); } - @Test - public void testTerminationPointVlanModes() throws InterruptedException { - VlanMode []vlanModes = VlanMode.values(); - for (VlanMode vlanMode : vlanModes) { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); - OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); - Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( - connectionInfo, bridge.getBridgeName())); - OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = - createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testTerminationPointVlanMode" + vlanMode.toString(); - ovsdbTerminationBuilder.setName(portName); - //setup - ovsdbTerminationBuilder.setVlanMode(vlanMode); + /** + * Extract the node contents from store type data store for the + * bridge identified by bridgeName + * + * @param connectionInfo the connection information + * @param bridgeName the bridge name + * @param store defined by the LogicalDatastoreType enumeration + * @return store type data store contents + */ + private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) { + InstanceIdentifier bridgeIid = + SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)); + return mdsalUtils.read(store, bridgeIid); + } + + /** + * Extract the node contents from LogicalDataStoreType.OPERATIONAL data store for the + * bridge identified by bridgeName + * + * @param connectionInfo the connection information + * @param bridgeName the bridge name + * @return LogicalDatastoreType.OPERATIONAL type data store contents + */ + private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) { + return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL); + } + + @Test + public void testAddDeleteBridge() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + LOG.info("bridge: {}", bridge); + } + } + + private InstanceIdentifier getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) { + return SouthboundUtils.createInstanceIdentifier(connectionInfo, bridge.getBridgeName()); + } + + /** + * Extracts the TerminationPointAugmentation for the index TerminationPoint + * on bridgeName + * + * @param connectionInfo the connection information + * @param bridgeName the bridge name + * @param store defined by the LogicalDatastoreType enumeration + * @param index the index we're interested in + * @return the augmentation (or {@code null} if none) + */ + private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation( + ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) { + + List tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint(); + if (tpList == null) { + return null; + } + return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class); + } + + @Test + public void testCRUDTerminationPointIfIndex() throws InterruptedException { + final boolean isOldSchema = schemaVersion.compareTo(IF_INDEX_FROM_VERSION) < 0; + Assume.assumeFalse(isOldSchema); + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // Test create ifIndex + try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME, null, true, + SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), + true, SouthboundMapper.createDatapathType("netdev"), null, null, null)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + LOG.info("bridge: {}", bridge); + NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testIfIndex"; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); Assert.assertNotNull(terminationPointNode); + // Test read ifIndex List terminationPoints = terminationPointNode.getTerminationPoint(); for (TerminationPoint terminationPoint : terminationPoints) { OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - //test - Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode)); + Long ifIndex = ovsdbTerminationPointAugmentation.getIfindex(); + Assert.assertNotNull(ifIndex); + LOG.info("ifIndex: {} for the port:{}", ifIndex, portName); } } - Assert.assertTrue(deleteBridge(connectionInfo)); } } - private ArrayList> generateVlanSets() { - ArrayList> vlanSets = new ArrayList>(); + @Test + public void testCRDTerminationPointOfPort() throws InterruptedException { + final Long OFPORT_EXPECTED = 45002L; + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); - Set emptySet = new HashSet(); - vlanSets.add(emptySet); + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + LOG.info("bridge: {}", bridge); + NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testOfPort"; + ovsdbTerminationBuilder.setName(portName); - Set singleSet = new HashSet(); - Integer single = new Integer(2222); - singleSet.add(single); - vlanSets.add(singleSet); + ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); - Set minMaxMiddleSet = new HashSet(); - Integer min = new Integer(0); - minMaxMiddleSet.add(min); - Integer max = new Integer(4095); - minMaxMiddleSet.add(max); - Integer minPlusOne = new Integer(min + 1); - minMaxMiddleSet.add(minPlusOne); - Integer maxMinusOne = new Integer(max - 1); - minMaxMiddleSet.add(maxMinusOne); - Integer middle = new Integer((max - min) / 2); - minMaxMiddleSet.add(middle); - vlanSets.add(minMaxMiddleSet); + // READ + List terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + Long ofPort = ovsdbTerminationPointAugmentation.getOfport(); + // if ephemeral port 45002 is in use, ofPort is set to 1 + Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L)); + LOG.info("ofPort: {}", ofPort); + } + } - return vlanSets; - } + // UPDATE- Not Applicable. From the OpenVSwitch Documentation: + // "A client should ideally set this column’s value in the same database transaction that it uses to create + // the interface." - private List buildTrunkList(Set trunkSet) { - List trunkList = Lists.newArrayList(); - for (Integer trunk : trunkSet) { - TrunksBuilder trunkBuilder = new TrunksBuilder(); - trunkBuilder.setTrunk(new VlanId(trunk)); - trunkList.add(trunkBuilder.build()); + // DELETE handled by TestBridge } - return trunkList; } @Test - public void testTerminationPointVlanTrunks() throws InterruptedException { - ArrayList> vlanSets = generateVlanSets(); - int testCase = 0; - for (Set vlanSet : vlanSets) { - ++testCase; - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); - Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)); + public void testCRDTerminationPointOfPortRequest() throws InterruptedException { + final Long OFPORT_EXPECTED = 45008L; + final Long OFPORT_INPUT = 45008L; + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); Assert.assertNotNull(bridge); - NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( connectionInfo, bridge.getBridgeName())); OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = createGenericOvsdbTerminationPointAugmentationBuilder(); - String portName = "testTerminationPointVlanTrunks" + testCase; + String portName = "testOfPortRequest"; ovsdbTerminationBuilder.setName(portName); - //setup - List trunks = buildTrunkList(vlanSet); - ovsdbTerminationBuilder.setTrunks(trunks); + Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue(); + ovsdbTerminationBuilder.setOfport(OFPORT_INPUT); + ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected); Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); Assert.assertNotNull(terminationPointNode); + // READ List terminationPoints = terminationPointNode.getTerminationPoint(); for (TerminationPoint terminationPoint : terminationPoints) { OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { - List actualTrunks = ovsdbTerminationPointAugmentation.getTrunks(); - for (Trunks trunk : trunks) { - Assert.assertTrue(actualTrunks.contains(trunk)); + Long ofPort = ovsdbTerminationPointAugmentation.getOfport(); + // if ephemeral port 45008 is in use, ofPort is set to 1 + Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L)); + LOG.info("ofPort: {}", ofPort); + + Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest(); + Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected)); + LOG.info("ofPortRequest: {}", ofPortRequest); + } + } + + // UPDATE- Not Applicable. From the OpenVSwitch documentation: + // "A client should ideally set this column’s value in the same database transaction that it uses to + // create the interface. " + + // DELETE handled by TestBridge + } + } + + private void assertExpectedExist(List expected, List test) { + if (expected != null && test != null) { + for (T exp : expected) { + Assert.assertTrue("The retrieved values don't contain " + exp, test.contains(exp)); + } + } + } + + private interface SouthboundTerminationPointHelper { + void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List values); + List readValues(OvsdbTerminationPointAugmentation augmentation); + } + + /* + * Tests the CRUD operations for Port external_ids. + * + * @see SouthboundIT.generatePortExternalIdsTestCases() for specific test case information + */ + private void testCRUDTerminationPoint( + KeyValueBuilder builder, String prefix, SouthboundTerminationPointHelper helper) + throws InterruptedException { + final int TERMINATION_POINT_TEST_INDEX = 0; + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // updateFromTestCases represent the original test case value. updateToTestCases represent the new value after + // the update has been performed. + List> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From"); + List> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To"); + + for (SouthboundTestCase updateFromTestCase : updateFromTestCases) { + for (SouthboundTestCase updateToTestCase : updateToTestCases) { + String testBridgeAndPortName = String.format("%s_%s", prefix, updateToTestCase.name); + + // CREATE: Create the test bridge + try (TestBridge testBridge = new TestBridge(connectionInfo, null, testBridgeAndPortName, null, true, + SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, + null)) { + NodeId testBridgeNodeId = SouthboundUtils.createManagedNodeId( + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(testBridgeAndPortName))); + OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + tpCreateAugmentationBuilder.setName(testBridgeAndPortName); + helper.writeValues(tpCreateAugmentationBuilder, updateFromTestCase.inputValues); + Assert.assertTrue( + addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder)); + + // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation = + getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName, + LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX); + if (updateFromConfigurationTerminationPointAugmentation != null) { + List updateFromConfigurationValues = + helper.readValues(updateFromConfigurationTerminationPointAugmentation); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues); + } + OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation = + getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName, + LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX); + if (updateFromOperationalTerminationPointAugmentation != null) { + List updateFromOperationalValues = + helper.readValues(updateFromOperationalTerminationPointAugmentation); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues); + } + + // UPDATE: update the values + testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId(); + OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder = + new OvsdbTerminationPointAugmentationBuilder(); + helper.writeValues(tpUpdateAugmentationBuilder, updateToTestCase.inputValues); + InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId); + NodeBuilder portUpdateNodeBuilder = new NodeBuilder(); + NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid); + portUpdateNodeBuilder.setNodeId(portUpdateNodeId); + TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder(); + tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName))); + tpUpdateBuilder.addAugmentation( + OvsdbTerminationPointAugmentation.class, + tpUpdateAugmentationBuilder.build()); + portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build())); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + portIid, portUpdateNodeBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + // READ: the test port and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation = + getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName, + LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX); + if (updateToConfigurationTerminationPointAugmentation != null) { + List updateToConfigurationValues = + helper.readValues(updateToConfigurationTerminationPointAugmentation); + assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues); + assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationValues); + } + OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation = + getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName, + LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX); + if (updateToOperationalTerminationPointAugmentation != null) { + List updateToOperationalValues = + helper.readValues(updateToOperationalTerminationPointAugmentation); + if (updateFromTestCase.expectedValues != null) { + assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues); + assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalValues); + } + } + + // DELETE handled by TestBridge + } + } + } + } + + /* + * Tests the CRUD operations for Port external_ids. + * + * @see SouthboundIT.generatePortExternalIdsTestCases() for specific test case information + */ + @Test + public void testCRUDTerminationPointPortExternalIds() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundPortExternalIdsBuilder(), "TPPortExternalIds", + new PortExternalIdsSouthboundHelper()); + } + + /* + * Tests the CRUD operations for Interface external_ids. + * + * @see SouthboundIT.generateInterfaceExternalIdsTestCases() for specific test case information + */ + @Test + public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundInterfaceExternalIdsBuilder(), "TPInterfaceExternalIds", + new InterfaceExternalIdsSouthboundHelper()); + } + + /* + * Tests the CRUD operations for Interface lldp. + * + * @see SouthboundIT.generateInterfaceLldpTestCases() for specific test case information + */ + @Test + public void testCRUDTerminationPointInterfaceLldp() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundInterfaceLldpBuilder(), "TPInterfaceLldp", + new InterfaceLldpSouthboundHelper()); + } + + /* + * Tests the CRUD operations for TerminationPoint options. + * + * @see SouthboundIT.generateTerminationPointOptions() for specific test case information + */ + @Test + public void testCRUDTerminationPointOptions() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundOptionsBuilder(), "TPOptions", new OptionsSouthboundHelper()); + } + + /* + * Tests the CRUD operations for Interface other_configs. + * + * @see SouthboundIT.generateInterfaceExternalIdsTestCases() for specific test case information + */ + @Test + public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundInterfaceOtherConfigsBuilder(), "TPInterfaceOtherConfigs", + new InterfaceOtherConfigsSouthboundHelper()); + } + + /* + * Tests the CRUD operations for Port other_configs. + * + * @see SouthboundIT.generatePortExternalIdsTestCases() for specific test case information + */ + @Test + public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundPortOtherConfigsBuilder(), "TPPortOtherConfigs", + new PortOtherConfigsSouthboundHelper()); + } + + @Test + public void testCRUDTerminationPoints() throws InterruptedException { + String port1 = "vx1"; + String port2 = "vxlanport"; + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + + // add and delete a single port + String portName = port1; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)); + portName = port1; + InstanceIdentifier nodePath = + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + + Assert.assertTrue("failed to delete port " + portName, + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath)); + LOG.info("shague: waiting for delete {}", portName); + Thread.sleep(1000); + TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath); + Assert.assertNull(terminationPoint); + + // add two ports, then delete them + portName = port1; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + terminationPointIid = getTpIid(connectionInfo, bridge); + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + portName = port2; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + terminationPointIid = getTpIid(connectionInfo, bridge); + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)); + portName = port1; + nodePath = + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + + Assert.assertTrue("failed to delete port " + portName, + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath)); + LOG.info("shague: waiting for delete {}", portName); + Thread.sleep(1000); + terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath); + Assert.assertNull(terminationPoint); + + portName = port2; + nodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + + Assert.assertTrue("failed to delete port " + portName, + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath)); + LOG.info("shague: waiting for delete {}", portName); + Thread.sleep(1000); + terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath); + Assert.assertNull(terminationPoint); + + // DELETE handled by TestBridge + } + } + + @Test + public void testCRUDTerminationPointVlan() throws InterruptedException { + final Integer CREATED_VLAN_ID = 4000; + final Integer UPDATED_VLAN_ID = 4001; + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testTerminationPointVlanId"; + ovsdbTerminationBuilder.setName(portName); + ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID)); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + // READ + List terminationPoints = terminationPointNode.getTerminationPoint(); + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation; + for (TerminationPoint terminationPoint : terminationPoints) { + ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation( + OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag(); + Assert.assertNotNull(actualVlanId); + Integer actualVlanIdInt = actualVlanId.getValue(); + Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt); + } + } + + // UPDATE + NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId(); + OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder = + new OvsdbTerminationPointAugmentationBuilder(); + tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID)); + InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId); + NodeBuilder portUpdateNodeBuilder = new NodeBuilder(); + NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid); + portUpdateNodeBuilder.setNodeId(portUpdateNodeId); + TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder(); + tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName))); + tpUpdateBuilder.addAugmentation( + OvsdbTerminationPointAugmentation.class, + tpUpdateAugmentationBuilder.build()); + tpUpdateBuilder.setTpId(new TpId(portName)); + portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build())); + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation( + OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag(); + Assert.assertNotNull(actualVlanId); + Integer actualVlanIdInt = actualVlanId.getValue(); + Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt); + } + } + + // DELETE handled by TestBridge + } + } + + @Test + public void testCRUDTerminationPointVlanModes() throws InterruptedException { + final VlanMode UPDATED_VLAN_MODE = VlanMode.Access; + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + VlanMode []vlanModes = VlanMode.values(); + for (VlanMode vlanMode : vlanModes) { + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testTerminationPointVlanMode" + vlanMode.toString(); + ovsdbTerminationBuilder.setName(portName); + ovsdbTerminationBuilder.setVlanMode(vlanMode); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + // READ + List terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + //test + Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode)); + } + } + + // UPDATE + NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId(); + OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder = + new OvsdbTerminationPointAugmentationBuilder(); + tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE); + InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId); + NodeBuilder portUpdateNodeBuilder = new NodeBuilder(); + NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid); + portUpdateNodeBuilder.setNodeId(portUpdateNodeId); + TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder(); + tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName))); + tpUpdateBuilder.addAugmentation( + OvsdbTerminationPointAugmentation.class, + tpUpdateAugmentationBuilder.build()); + tpUpdateBuilder.setTpId(new TpId(portName)); + portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build())); + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + //test + Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode()); + } + } + + // DELETE handled by TestBridge + } + } + } + + @SuppressWarnings("unchecked") + private List> generateVlanSets() { + int min = 0; + int max = 4095; + return Lists.newArrayList( + Collections.emptySet(), + Sets.newHashSet(2222), + Sets.newHashSet(min, max, min + 1, max - 1, (max - min) / 2)); + } + + private List buildTrunkList(Set trunkSet) { + List trunkList = Lists.newArrayList(); + for (Integer trunk : trunkSet) { + TrunksBuilder trunkBuilder = new TrunksBuilder(); + trunkBuilder.setTrunk(new VlanId(trunk)); + trunkList.add(trunkBuilder.build()); + } + return trunkList; + } + + @Test + public void testCRUDTerminationPointVlanTrunks() throws InterruptedException { + final List UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011)); + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + Iterable> vlanSets = generateVlanSets(); + int testCase = 0; + for (Set vlanSet : vlanSets) { + ++testCase; + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName()); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testTerminationPointVlanTrunks" + testCase; + ovsdbTerminationBuilder.setName(portName); + List trunks = buildTrunkList(vlanSet); + ovsdbTerminationBuilder.setTrunks(trunks); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + // READ + List terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + List actualTrunks = ovsdbTerminationPointAugmentation.getTrunks(); + for (Trunks trunk : trunks) { + Assert.assertTrue(actualTrunks.contains(trunk)); + } + } + } + + + // UPDATE + NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId(); + OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder = + new OvsdbTerminationPointAugmentationBuilder(); + tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS); + InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId); + NodeBuilder portUpdateNodeBuilder = new NodeBuilder(); + NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid); + portUpdateNodeBuilder.setNodeId(portUpdateNodeId); + TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder(); + tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName))); + tpUpdateBuilder.addAugmentation( + OvsdbTerminationPointAugmentation.class, + tpUpdateAugmentationBuilder.build()); + tpUpdateBuilder.setTpId(new TpId(portName)); + portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build())); + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + //test + Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks()); } } + + // DELETE handled by TestBridge } - Assert.assertTrue(deleteBridge(connectionInfo)); + } + } + + /* + * Tests setting and deleting qos field in a port. + */ + @Test + public void testCRUDTerminationPointQos() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testQosId = new String("testQosEntry"); + + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); + TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), + SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HFSC), null, null)) { + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + Uuid qosUuid = new Uuid(operQos.getQosUuid().getValue()); + + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName()); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testTerminationPointQos"; + ovsdbTerminationBuilder.setName(portName); + ovsdbTerminationBuilder.setQos(qosUuid); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + + // READ and check that qos uuid has been added to the port + InstanceIdentifier tpEntryIid = getTpIid(connectionInfo, bridge) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid); + Assert.assertNotNull(terminationPoint); + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + Assert.assertEquals(ovsdbTerminationPointAugmentation.getQos(), qosUuid); + + // UPDATE - remove the qos entry from the port + OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder = + new OvsdbTerminationPointAugmentationBuilder(); + tpUpdateAugmentationBuilder.setName(portName); + TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder(); + tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName))); + tpUpdateBuilder.addAugmentation( + OvsdbTerminationPointAugmentation.class, + tpUpdateAugmentationBuilder.build()); + tpUpdateBuilder.setTpId(new TpId(portName)); + + Assert.assertTrue( + mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpEntryIid, tpUpdateBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + // READ and verify that qos uuid has been removed from port + TerminationPoint terminationPointUpdate = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid); + Assert.assertNotNull(terminationPointUpdate); + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentationUpdate = + terminationPointUpdate.getAugmentation(OvsdbTerminationPointAugmentation.class); + Assert.assertNull(ovsdbTerminationPointAugmentationUpdate.getQos()); + + // DELETE handled by TestBridge } } @Test public void testGetOvsdbNodes() throws InterruptedException { - ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); InstanceIdentifier topologyPath = InstanceIdentifier .create(NetworkTopology.class) .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)); Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath); - Assert.assertEquals("There should only be one node in the topology", 1, topology.getNode().size()); - InstanceIdentifier expectedNodeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo); - Node node = topology.getNode().iterator().next(); + InstanceIdentifier expectedNodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo); NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId(); - Assert.assertEquals(expectedNodeId, node.getNodeId()); - Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); + Node foundNode = null; + Assert.assertNotNull("Expected to find topology: " + topologyPath, topology); + Assert.assertNotNull("Expected to find some nodes" + topology.getNode()); + LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode()); + for (Node node : topology.getNode()) { + if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) { + foundNode = node; + break; + } + } + Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode); } - /** - * isBundleReady is used to check if the requested bundle is Active + /* + * @see SouthboundIT.generateBridgeOtherConfigsTestCases() for specific test case information. */ - public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException { - boolean ready = false; - - while (!ready) { - int state = Bundle.UNINSTALLED; - Bundle[] bundles = bundleContext.getBundles(); - for (Bundle element : bundles) { - if (element.getSymbolicName().equals(bundleName)) { - state = element.getState(); - LOG.info(">>>>> bundle is ready {}", bundleName); - break; + @Test + public void testCRUDBridgeOtherConfigs() throws InterruptedException { + testCRUDBridge("BridgeOtherConfigs", new SouthboundBridgeOtherConfigsBuilder(), + new BridgeOtherConfigsSouthboundHelper()); + } + + private interface SouthboundBridgeHelper { + void writeValues(OvsdbBridgeAugmentationBuilder builder, List values); + List readValues(OvsdbBridgeAugmentation augmentation); + } + + private void testCRUDBridge(String prefix, KeyValueBuilder builder, SouthboundBridgeHelper helper) + throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + // updateFromTestCases represent the original test case value. updateToTestCases represent the new value after + // the update has been performed. + List> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From"); + List> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To"); + for (SouthboundTestCase updateFromTestCase : updateFromTestCases) { + for (SouthboundTestCase updateToTestCase : updateToTestCases) { + String testBridgeName = String.format("%s_%s", prefix, updateToTestCase.name); + + // CREATE: Create the test bridge + final OvsdbBridgeName ovsdbBridgeName = new OvsdbBridgeName(testBridgeName); + final InstanceIdentifier bridgeIid = + SouthboundUtils.createInstanceIdentifier(connectionInfo, ovsdbBridgeName); + final NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid); + final NodeBuilder bridgeCreateNodeBuilder = new NodeBuilder(); + bridgeCreateNodeBuilder.setNodeId(bridgeNodeId); + OvsdbBridgeAugmentationBuilder bridgeCreateAugmentationBuilder = new OvsdbBridgeAugmentationBuilder(); + bridgeCreateAugmentationBuilder.setBridgeName(ovsdbBridgeName); + bridgeCreateAugmentationBuilder.setProtocolEntry(createMdsalProtocols()); + bridgeCreateAugmentationBuilder.setFailMode( + SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure")); + setManagedBy(bridgeCreateAugmentationBuilder, connectionInfo); + helper.writeValues(bridgeCreateAugmentationBuilder, updateFromTestCase.inputValues); + bridgeCreateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, + bridgeCreateAugmentationBuilder.build()); + LOG.debug("Built with the intent to store bridge data {}", bridgeCreateAugmentationBuilder.toString()); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, + bridgeCreateNodeBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + List updateFromConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName, + LogicalDatastoreType.CONFIGURATION)); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationExternalIds); + List updateFromOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName)); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalExternalIds); + + // UPDATE: update the values + final OvsdbBridgeAugmentationBuilder bridgeUpdateAugmentationBuilder = + new OvsdbBridgeAugmentationBuilder(); + helper.writeValues(bridgeUpdateAugmentationBuilder, updateToTestCase.inputValues); + final NodeBuilder bridgeUpdateNodeBuilder = new NodeBuilder(); + final Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName); + bridgeUpdateNodeBuilder.setNodeId(bridgeNode.getNodeId()); + bridgeUpdateNodeBuilder.setKey(bridgeNode.getKey()); + bridgeUpdateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, + bridgeUpdateAugmentationBuilder.build()); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, + bridgeUpdateNodeBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + List updateToConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName, + LogicalDatastoreType.CONFIGURATION)); + assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationExternalIds); + assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationExternalIds); + List updateToOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName)); + if (updateFromTestCase.expectedValues != null) { + assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalExternalIds); + assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalExternalIds); } + + // DELETE + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, bridgeIid)); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); } - if (state != Bundle.ACTIVE) { - LOG.info(">>>>> bundle not ready {}", bundleName); - Thread.sleep(5000); - } else { - ready = true; + } + } + + /* + * @see SouthboundIT.generateBridgeExternalIdsTestCases() for specific test case information + */ + @Test + public void testCRUDBridgeExternalIds() throws InterruptedException { + testCRUDBridge("BridgeExternalIds", new SouthboundBridgeExternalIdsBuilder(), + new BridgeExternalIdsSouthboundHelper()); + } + + @Test + public void testAddDeleteQos() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + OvsdbNodeAugmentation ovsdbNodeAugmentation; + Uri qosUri = new Uri("QOS-ROW"); + List typeList = new ArrayList(); + typeList.add(SouthboundConstants.QOS_LINUX_HTB); + typeList.add(SouthboundConstants.QOS_LINUX_HFSC); + + for (String qosType : typeList) { + try (TestQos testQos = new TestQos(connectionInfo, qosUri, SouthboundMapper.createQosType(qosType), null, null)) { + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation); + Assert.assertNotNull(operQosHtb); } + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation); + Assert.assertNull(operQosHtb); + } + } + + @Test + public void testAddDeleteQueue() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + Uri queueUri = new Uri("QUEUE-A1"); + + try (TestQueue testQueue = new TestQueue(connectionInfo, queueUri, new Short("25"), null, null)) { + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue); + } + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation); + Assert.assertNull(operQueue); + } + + private static class SouthboundQueuesExternalIdsHelper implements SouthboundQueueHelper { + @Override + public void writeValues(QueuesBuilder builder, List values) { + builder.setQueuesExternalIds(values); + } + + @Override + public List readValues(Queues queue) { + return queue.getQueuesExternalIds(); + } + } + + private static class SouthboundQueuesOtherConfigHelper implements SouthboundQueueHelper { + @Override + public void writeValues(QueuesBuilder builder, List values) { + builder.setQueuesOtherConfig(values); + } + + @Override + public List readValues(Queues queue) { + return queue.getQueuesOtherConfig(); + } + } + + private interface SouthboundQueueHelper { + void writeValues(QueuesBuilder builder, List values); + List readValues(Queues queue); + } + + private Queues getQueue(Uri queueId, OvsdbNodeAugmentation node) { + for (Queues queue : node.getQueues()) { + if (queue.getKey().getQueueId().getValue().equals(queueId.getValue())) + return queue; + } + return null; + } + + private static class SouthboundQosExternalIdsHelper implements SouthboundQosHelper { + @Override + public void writeValues(QosEntriesBuilder builder, List values) { + builder.setQosExternalIds(values); + } + + @Override + public List readValues(QosEntries qos) { + return qos.getQosExternalIds(); + } + } + + private static class SouthboundQosOtherConfigHelper implements SouthboundQosHelper { + @Override + public void writeValues(QosEntriesBuilder builder, List values) { + builder.setQosOtherConfig(values); + } + + @Override + public List readValues(QosEntries qos) { + return qos.getQosOtherConfig(); + } + } + + private interface SouthboundQosHelper { + void writeValues(QosEntriesBuilder builder, List values); + List readValues(QosEntries qos); + } + + private QosEntries getQos(Uri qosId, OvsdbNodeAugmentation node) { + for (QosEntries qos : node.getQosEntries()) { + if (qos.getKey().getQosId().equals(qosId)) + return qos; + } + return null; + } + + private void testCRUDQueue( + KeyValueBuilder builder, String prefix, SouthboundQueueHelper helper) + throws InterruptedException { + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // updateFromTestCases represent the original test case value. updateToTestCases represent the new value after + // the update has been performed. + List> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From"); + List> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To"); + + for (SouthboundTestCase updateFromTestCase : updateFromTestCases) { + for (SouthboundTestCase updateToTestCase : updateToTestCases) { + String testQueueId = String.format("%s_%s", prefix, updateToTestCase.name); + + // CREATE: and update the test queue with starting values. + try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("45"), null, null)) { + QueuesBuilder queuesBuilder = new QueuesBuilder(); + queuesBuilder.setQueueId(new Uri(testQueueId)); + InstanceIdentifier queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, queuesBuilder.build().getKey()); + final NotifyingDataChangeListener queueConfigurationListener = + new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, queueIid); + queueConfigurationListener.registerDataChangeListener(); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid); + queueOperationalListener.registerDataChangeListener(); + + helper.writeValues(queuesBuilder, updateFromTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + queueIid, queuesBuilder.build())); + queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + Queues queueFromConfig = getQueue(new Uri(testQueueId), updateFromConfigurationOvsdbNodeAugmentation); + if (queueFromConfig != null) { + List updateFromConfigurationValues = + helper.readValues(queueFromConfig); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues); + } + + queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues queueFromOper = getQueue(new Uri(testQueueId), updateFromOperationalOvsdbNodeAugmentation); + if (queueFromOper != null) { + List updateFromOperationalValues = + helper.readValues(queueFromOper); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues); + } + + // UPDATE: update the values + QueuesBuilder queuesUpdateBuilder = new QueuesBuilder(); + queuesUpdateBuilder.setQueueId(new Uri(testQueueId)); + helper.writeValues(queuesUpdateBuilder, updateToTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + queueIid, queuesUpdateBuilder.build())); + queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + Queues queueToConfig = getQueue(new Uri(testQueueId), updateToConfigurationOvsdbNodeAugmentation); + if (queueToConfig != null) { + List updateToConfigurationValues = + helper.readValues(queueToConfig); + assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues); + } + + queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues queueToOper = getQueue(new Uri(testQueueId), updateToOperationalOvsdbNodeAugmentation); + if (queueToOper != null) { + List updateToOperationalValues = + helper.readValues(queueToOper); + assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues); + } + + // DELETE handled by TestQueue + } + } + } + } + + @Test + public void testCRUDQueueExternalIds() throws InterruptedException { + testCRUDQueue(new SouthboundQueuesExternalIdsBuilder(), "QueueExternalIds", + new SouthboundQueuesExternalIdsHelper()); + } + + @Test + public void testCRUDQueueOtherConfig() throws InterruptedException { + testCRUDQueue(new SouthboundQueuesOtherConfigBuilder(), "QueueOtherConfig", + new SouthboundQueuesOtherConfigHelper()); + } + + @Test + public void testCRUDQueueDscp() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testQueueId = "testQueueDscp"; + + // CREATE: and update the test queue with starting values. + try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("0"), null, null)) { + for (Short dscp = 1; dscp < 64; dscp++) { + QueuesBuilder queuesBuilder = new QueuesBuilder(); + queuesBuilder.setQueueId(new Uri(testQueueId)); + InstanceIdentifier queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, queuesBuilder.build().getKey()); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid); + queueOperationalListener.registerDataChangeListener(); + + queuesBuilder.setDscp(dscp); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + queueIid, queuesBuilder.build())); + queueOperationalListener.waitForUpdate(OVSDB_ROUNDTRIP_TIMEOUT); + + // READ: Read the test queue and ensure changes are propagated to the OPERATIONAL data store + // assumption is that CONFIGURATION was updated if OPERATIONAL is correct + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue = getQueue(new Uri(testQueueId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue); + Short operDscp = operQueue.getDscp(); + Assert.assertNotNull(operDscp); + Assert.assertEquals(dscp, operDscp); + } + + // DELETE handled by TestQueue + } + + } + + private void testCRUDQos( + KeyValueBuilder builder, String prefix, SouthboundQosHelper helper) + throws InterruptedException { + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // updateFromTestCases represent the original test case value. updateToTestCases represent the new value after + // the update has been performed. + List> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From"); + List> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To"); + + for (SouthboundTestCase updateFromTestCase : updateFromTestCases) { + for (SouthboundTestCase updateToTestCase : updateToTestCases) { + String testQosId = String.format("%s_%s", prefix, updateToTestCase.name); + + // CREATE: and update the test qos with starting values. + try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null)) { + QosEntriesBuilder qosBuilder = new QosEntriesBuilder(); + qosBuilder.setQosId(new Uri(testQosId)); + InstanceIdentifier qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, qosBuilder.build().getKey()); + final NotifyingDataChangeListener qosConfigurationListener = + new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, qosIid); + qosConfigurationListener.registerDataChangeListener(); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid); + qosOperationalListener.registerDataChangeListener(); + + helper.writeValues(qosBuilder, updateFromTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qosIid, qosBuilder.build())); + qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + QosEntries qosFromConfig = getQos(new Uri(testQosId), updateFromConfigurationOvsdbNodeAugmentation); + if (qosFromConfig != null) { + List updateFromConfigurationValues = + helper.readValues(qosFromConfig); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues); + } + + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries qosFromOper = getQos(new Uri(testQosId), updateFromOperationalOvsdbNodeAugmentation); + if (qosFromOper != null) { + List updateFromOperationalValues = + helper.readValues(qosFromOper); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues); + } + + // UPDATE: update the values + QosEntriesBuilder qosUpdateBuilder = new QosEntriesBuilder(); + qosUpdateBuilder.setQosId(new Uri(testQosId)); + helper.writeValues(qosUpdateBuilder, updateToTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qosIid, qosUpdateBuilder.build())); + qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + QosEntries qosToConfig = getQos(new Uri(testQosId), updateToConfigurationOvsdbNodeAugmentation); + if (qosToConfig != null) { + List updateToConfigurationValues = + helper.readValues(qosToConfig); + assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues); + } + + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries qosToOper = getQos(new Uri(testQosId), updateToOperationalOvsdbNodeAugmentation); + if (qosToOper != null) { + List updateToOperationalValues = + helper.readValues(qosToOper); + assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues); + } + + // DELETE handled by TestQueue + } + } + } + } + + @Test + public void testCRUDQosExternalIds() throws InterruptedException { + testCRUDQos(new SouthboundQosExternalIdsBuilder(), "QosExternalIds", + new SouthboundQosExternalIdsHelper()); + } + + @Test + public void testCRUDQosOtherConfig() throws InterruptedException { + testCRUDQos(new SouthboundQosOtherConfigBuilder(), "QosOtherConfig", + new SouthboundQosOtherConfigHelper()); + } + @Test + public void testCRUDQosQueues() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testQosId = "testQosQueues"; + + // CREATE: and update the test queue with starting values. + try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), + SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null); + TestQueue testQueue1 = new TestQueue(connectionInfo, new Uri("queue1"), new Short("12"), null, null); + TestQueue testQueue2 = new TestQueue(connectionInfo, new Uri("queue2"), new Short("35"), null, null)) { + QosEntriesBuilder qosBuilder = new QosEntriesBuilder(); + qosBuilder.setQosId(new Uri(testQosId)); + InstanceIdentifier qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, qosBuilder.build().getKey()); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid); + qosOperationalListener.registerDataChangeListener(); + + // READ, UPDATE: Read the UUIDs of the Queue rows and add them to the + // configuration of the Qos row. + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue1 = getQueue(new Uri("queue1"), ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue1); + Uuid queue1Uuid = new Uuid(operQueue1.getQueueUuid().getValue()); + Queues operQueue2 = getQueue(new Uri("queue2"), ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue2); + Uuid queue2Uuid = new Uuid(operQueue2.getQueueUuid().getValue()); + + List queueList = new ArrayList<>(); + queueList.add(new QueueListBuilder().setQueueNumber(new Long("0")) + .setQueueUuid(queue1Uuid).build()); + queueList.add(new QueueListBuilder().setQueueNumber(new Long("1")) + .setQueueUuid(queue2Uuid).build()); + qosBuilder.setQueueList(queueList); + + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qosIid, qosBuilder.build())); + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store + // assumption is that CONFIGURATION was updated if OPERATIONAL is correct + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + List operQueueList = operQos.getQueueList(); + Assert.assertNotNull(operQueueList); + for (QueueList queueEntry : queueList) { + Assert.assertTrue(isQueueInList(operQueueList, queueEntry)); + } + + // DELETE one queue from queue list and check that one remains + KeyedInstanceIdentifier qosQueueIid = qosIid + .child(QueueList.class, new QueueListKey(new Long("0"))); + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid)); + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store + // assumption is that CONFIGURATION was updated if OPERATIONAL is correct + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + operQueueList = operQos.getQueueList(); + Assert.assertNotNull(operQueueList); + for (QueueList queueEntry : queueList) { + if (queueEntry.getQueueUuid().equals(queue2Uuid)) { + Assert.assertTrue(isQueueInList(operQueueList, queueEntry)); + } else if (queueEntry.getQueueUuid().equals(queue1Uuid)) { + Assert.assertFalse(isQueueInList(operQueueList, queueEntry)); + } else { + Assert.assertTrue("Unknown queue entry in qos queue list", false); + } + } + + // DELETE queue list and check that list is empty + qosQueueIid = qosIid + .child(QueueList.class, new QueueListKey(new Long("1"))); + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid)); + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + operQueueList = operQos.getQueueList(); + Assert.assertNotNull(operQueueList); + Assert.assertTrue(operQueueList.isEmpty()); + } + } + + private Boolean isQueueInList(List queueList, QueueList queue) { + for (QueueList queueEntry : queueList) { + if (queueEntry.getQueueNumber().equals(queue.getQueueNumber()) + && queueEntry.getQueueUuid().equals(queue.getQueueUuid())) { + return true; + } + } + return false; + } + + /** + *

+ * Representation of a southbound test case. Each test case has a name, a list of input values and a list of + * expected values. The input values are provided to the augmentation builder, and the expected values are checked + * against the output of the resulting augmentation. + *

+ *

+ * Instances of this class are immutable. + *

+ * + * @param The type of data used for the test case. + */ + private static final class SouthboundTestCase { + private final String name; + private final List inputValues; + private final List expectedValues; + + /** + * Creates an instance of a southbound test case. + * + * @param name The test case's name. + * @param inputValues The input values (provided as input to the underlying augmentation builder). + * @param expectedValues The expected values (checked against the output of the underlying augmentation). + */ + public SouthboundTestCase( + final String name, final List inputValues, final List expectedValues) { + this.name = name; + this.inputValues = inputValues; + this.expectedValues = expectedValues; + } + } + + /** + * Southbound test case builder. + * + * @param The type of data used for the test case. + */ + private static final class SouthboundTestCaseBuilder { + private String name; + private List inputValues; + private List expectedValues; + + /** + * Creates a builder. Builders may be reused, the generated immutable instances are independent of the + * builders. There are no default values. + */ + public SouthboundTestCaseBuilder() { + // Nothing to do + } + + /** + * Sets the test case's name. + * + * @param name The test case's name. + * @return The builder. + */ + public SouthboundTestCaseBuilder name(final String name) { + this.name = name; + return this; + } + + /** + * Sets the input values. + * + * @param inputValues The input values. + * @return The builder. + */ + @SafeVarargs + public final SouthboundTestCaseBuilder input(final T... inputValues) { + this.inputValues = Lists.newArrayList(inputValues); + return this; + } + + /** + * Indicates that the provided input values should be expected as output values. + * + * @return The builder. + */ + public SouthboundTestCaseBuilder expectInputAsOutput() { + this.expectedValues = this.inputValues; + return this; + } + + /** + * Indicates that no output should be expected. + * + * @return The builder. + */ + public SouthboundTestCaseBuilder expectNoOutput() { + this.expectedValues = null; + return this; + } + + /** + * Builds an immutable instance representing the test case. + * + * @return The test case. + */ + @SuppressWarnings("unchecked") + public SouthboundTestCase build() { + return new SouthboundTestCase<>(name, inputValues, expectedValues); + } + } + + private abstract static class KeyValueBuilder { + private static final int COUNTER_START = 0; + private int counter = COUNTER_START; + + protected abstract Builder builder(); + + protected abstract void setKey(Builder builder, String key); + + protected abstract void setValue(Builder builder, String value); + + protected abstract boolean isValueMandatory(); + + public final T build(final String testName, final String key, final String value) { + final Builder builder = builder(); + this.counter++; + if (key != null) { + setKey(builder, String.format(FORMAT_STR, testName, key, this.counter)); + } + if (value != null) { + setValue(builder, String.format(FORMAT_STR, testName, value, this.counter)); + } + return builder.build(); + } + + public final void reset() { + this.counter = COUNTER_START; + } + } + + private static final class SouthboundQueuesExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QueuesExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundQueuesOtherConfigBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QueuesOtherConfigBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundQosExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QosExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QosExternalIdsBuilder) builder).setQosExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QosExternalIdsBuilder) builder).setQosExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundQosOtherConfigBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QosOtherConfigBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QosOtherConfigBuilder) builder).setOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QosOtherConfigBuilder) builder).setOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new PortExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((PortExternalIdsBuilder) builder).setExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((PortExternalIdsBuilder) builder).setExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new InterfaceExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundInterfaceLldpBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new InterfaceLldpBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((InterfaceLldpBuilder) builder).setLldpKey((key)); + } + + @Override + protected void setValue(Builder builder, String value) { + ((InterfaceLldpBuilder) builder).setLldpValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundOptionsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new OptionsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((OptionsBuilder) builder).setOption(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((OptionsBuilder) builder).setValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new InterfaceOtherConfigsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new PortOtherConfigsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new BridgeOtherConfigsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new BridgeExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + /* + * Generates the test cases involved in testing key-value-based data. See inline comments for descriptions of + * the particular cases considered. + */ + private static List> generateKeyValueTestCases( + KeyValueBuilder builder, String testName) { + List> testCases = new ArrayList<>(); + + final String GOOD_KEY = "GoodKey"; + final String GOOD_VALUE = "GoodValue"; + final String NO_VALUE_FOR_KEY = "NoValueForKey"; + + final String idKey = testName + "Key"; + final String idValue = testName + "Value"; + + // Test Case 1: TestOne + // Test Type: Positive + // Description: Create a termination point with one value + // Expected: A port is created with the single value specified below + final String testOneName = "TestOne" + testName; + testCases.add(new SouthboundTestCaseBuilder() + .name(testOneName) + .input(builder.build(testOneName, idKey, idValue)) + .expectInputAsOutput() + .build()); + builder.reset(); + + // Test Case 2: TestFive + // Test Type: Positive + // Description: Create a termination point with multiple (five) values + // Expected: A port is created with the five values specified below + final String testFiveName = "TestFive" + testName; + testCases.add(new SouthboundTestCaseBuilder() + .name(testFiveName) + .input( + builder.build(testFiveName, idKey, idValue), + builder.build(testFiveName, idKey, idValue), + builder.build(testFiveName, idKey, idValue), + builder.build(testFiveName, idKey, idValue), + builder.build(testFiveName, idKey, idValue)) + .expectInputAsOutput() + .build()); + builder.reset(); + + if (!builder.isValueMandatory()) { + // Test Case 3: TestOneGoodOneMalformedValue + // Test Type: Negative + // Description: + // One perfectly fine input + // (TestOneGoodOneMalformedValue_GoodKey_1, + // TestOneGoodOneMalformedValue_GoodValue_1) + // and one malformed input which only has key specified + // (TestOneGoodOneMalformedValue_NoValueForKey_2, + // UNSPECIFIED) + // Expected: A port is created without any values + final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName; + testCases.add(new SouthboundTestCaseBuilder() + .name(testOneGoodOneMalformedValueName) + .input( + builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE), + builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null)) + .expectNoOutput() + .build()); + builder.reset(); + } else { + LOG.info("generateKeyValueTestCases: skipping test case 3 for {}", builder.getClass().getSimpleName()); + } + + return testCases; + } + + private static class PortExternalIdsSouthboundHelper implements SouthboundTerminationPointHelper { + @Override + public void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setPortExternalIds(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getPortExternalIds(); + } + } + + private static class InterfaceExternalIdsSouthboundHelper implements + SouthboundTerminationPointHelper { + @Override + public void writeValues( + OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setInterfaceExternalIds(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getInterfaceExternalIds(); + } + } + + private static class InterfaceLldpSouthboundHelper implements + SouthboundTerminationPointHelper { + @Override + public void writeValues( + OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setInterfaceLldp(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getInterfaceLldp(); + } + } + + private static class OptionsSouthboundHelper implements SouthboundTerminationPointHelper { + @Override + public void writeValues( + OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setOptions(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getOptions(); + } + } + + private static class InterfaceOtherConfigsSouthboundHelper implements + SouthboundTerminationPointHelper { + @Override + public void writeValues( + OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setInterfaceOtherConfigs(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getInterfaceOtherConfigs(); + } + } + + private static class PortOtherConfigsSouthboundHelper implements + SouthboundTerminationPointHelper { + @Override + public void writeValues( + OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setPortOtherConfigs(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getPortOtherConfigs(); + } + } + + private static class BridgeExternalIdsSouthboundHelper implements SouthboundBridgeHelper { + @Override + public void writeValues( + OvsdbBridgeAugmentationBuilder builder, List values) { + builder.setBridgeExternalIds(values); + } + + @Override + public List readValues(OvsdbBridgeAugmentation augmentation) { + return augmentation.getBridgeExternalIds(); + } + } + + private static class BridgeOtherConfigsSouthboundHelper implements SouthboundBridgeHelper { + @Override + public void writeValues( + OvsdbBridgeAugmentationBuilder builder, List values) { + builder.setBridgeOtherConfigs(values); + } + + @Override + public List readValues(OvsdbBridgeAugmentation augmentation) { + return augmentation.getBridgeOtherConfigs(); } } -} \ No newline at end of file +}