Merge "Updating fix for bug 3989 based on discussion in OVSDB meeting"
[ovsdb.git] / integrationtest / src / test / java / org / opendaylight / ovsdb / integrationtest / plugin / OvsdbPluginIT.java
index 29c45c6648fc0f3e09443c91ae2c37e5e486af13..41582a7c6b4eba076c94cc6b3ec9df4af7e3cfcd 100644 (file)
@@ -15,34 +15,41 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperty;
 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
 
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.inject.Inject;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.sal.utils.ServiceHelper;
-import org.opendaylight.controller.sal.utils.Status;
+import org.junit.After;
+import org.junit.Ignore;
 import org.opendaylight.ovsdb.integrationtest.ConfigurationBundles;
 import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
 import org.opendaylight.ovsdb.lib.notation.Row;
-import org.opendaylight.ovsdb.plugin.Connection;
-import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
-import org.opendaylight.ovsdb.plugin.OvsdbConfigService;
-import org.opendaylight.ovsdb.plugin.StatusWithUuid;
+import org.opendaylight.ovsdb.plugin.api.Connection;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
+import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
+import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
+import org.opendaylight.ovsdb.plugin.api.Status;
+import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
@@ -52,15 +59,25 @@ import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
 
+import javax.inject.Inject;
+
+@Ignore
 @RunWith(PaxExam.class)
 public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
-    private Logger log = LoggerFactory.getLogger(OvsdbPluginIT.class);
+    private static final Logger LOG = LoggerFactory.getLogger(OvsdbPluginIT.class);
     @Inject
     private BundleContext bc;
-    private OvsdbConfigService ovsdbConfigService = null;
+    private OvsdbConfigurationService ovsdbConfigurationService = null;
+
+    @Inject
+    private OvsdbInventoryService ovsdbInventoryService;
+
     private Node node = null;
     private OvsdbClient client = null;
 
@@ -79,29 +96,14 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
             propagateSystemProperty("ovsdbserver.ipaddress"),
             propagateSystemProperty("ovsdbserver.port"),
 
+            ConfigurationBundles.mdsalBundles(),
             ConfigurationBundles.controllerBundles(),
             ConfigurationBundles.ovsdbLibraryBundles(),
             ConfigurationBundles.ovsdbDefaultSchemaBundles(),
-            mavenBundle("org.opendaylight.ovsdb", "plugin").versionAsInProject(),
-            junitBundles()
+            ConfigurationBundles.ovsdbPluginBundles()
         );
     }
 
-    private String stateToString(int state) {
-        switch (state) {
-        case Bundle.ACTIVE:
-            return "ACTIVE";
-        case Bundle.INSTALLED:
-            return "INSTALLED";
-        case Bundle.RESOLVED:
-            return "RESOLVED";
-        case Bundle.UNINSTALLED:
-            return "UNINSTALLED";
-        default:
-            return "Not CONVERTED";
-        }
-    }
-
     @Before
     public void areWeReady() throws InterruptedException {
         assertNotNull(bc);
@@ -110,13 +112,12 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
         for (Bundle element : b) {
             int state = element.getState();
             if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
-                log.info("Bundle:" + element.getSymbolicName() + " state:"
-                          + stateToString(state));
+                LOG.info("Bundle: {} state: {}", element.getSymbolicName(), stateToString(state));
                 debugit = true;
             }
         }
         if (debugit) {
-            log.debug("Do some debugging because some bundle is unresolved");
+            LOG.debug("Do some debugging because some bundle is unresolved");
         }
 
         assertFalse(debugit);
@@ -125,13 +126,14 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
         } catch (Exception e) {
             fail("Exception : "+e.getMessage());
         }
-        this.ovsdbConfigService = (OvsdbConfigService)ServiceHelper.getGlobalInstance(OvsdbConfigService.class, this);
+        this.ovsdbConfigurationService = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class, this);
     }
 
     @Test
     public void apiTests() throws Exception {
         Thread.sleep(5000);
-        IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+        OvsdbConnectionService
+                connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
 
         // Check for the ovsdb Connection as seen by the Plugin layer
         assertNotNull(connectionService.getNodes());
@@ -143,7 +145,7 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
         if (connectionInfo.getType().equals(OvsdbConnectionInfo.ConnectionType.PASSIVE)) {
             identifier = connectionInfo.getRemoteAddress().getHostAddress()+":"+connectionInfo.getRemotePort();
         }
-        assertEquals(Node.fromString("OVS|"+identifier), connectionService.getNodes().get(0));
+        assertEquals(node, connectionService.getNode("OVS|" + identifier));
         System.out.println("Nodes = "+ connectionService.getNodes());
         /*
          * Test sequence :
@@ -163,6 +165,122 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
         this.endToEndApiTest(connection, null);
     }
 
+    @Test
+    public void testInventoryListeners() throws UnknownHostException {
+        DependencyManager dm = new DependencyManager(bc);
+
+        OvsdbInventoryListener listenerA = Mockito.mock(FakeListener.class);
+        OvsdbInventoryListener listenerB = Mockito.mock(FakeListener.class);
+
+        Component componentA = dm.createComponent();
+        componentA.setInterface(OvsdbInventoryListener.class.getName(), null);
+        componentA.setImplementation(listenerA);
+        dm.add(componentA);
+
+        Component componentB = dm.createComponent();
+        componentB.setInterface(OvsdbInventoryListener.class.getName(), null);
+        componentB.setImplementation(listenerB);
+        dm.add(componentB);
+
+        NodeId nodeId = new NodeId("OVS|10.10.10.10:65342");
+        NodeKey nodeKey = new NodeKey(nodeId);
+        node = new NodeBuilder()
+                .setId(nodeId)
+                .setKey(nodeKey)
+                .build();
+        InetAddress address = InetAddress.getByName("10.10.10.10");
+        int port = 65342;
+
+        // Trigger event
+        ovsdbInventoryService.notifyNodeAdded(node, address, port);
+
+        Mockito.verify(listenerA, Mockito.times(1)).nodeAdded(node, address, port);
+        Mockito.verify(listenerB, Mockito.times(1)).nodeAdded(node, address, port);
+
+        dm.remove(componentA);
+        dm.remove(componentB);
+
+    }
+
+    @Test
+    public void testSetOFControllers() throws Exception {
+        Thread.sleep(5000);
+        OvsdbConnectionService
+                connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
+
+        // 1. Check for the ovsdb Connection as seen by the Plugin layer
+        assertNotNull(connectionService.getNodes());
+        assertTrue(connectionService.getNodes().size() > 0);
+        Node node = connectionService.getNodes().get(0);
+        Connection connection = connectionService.getConnection(node);
+        assertNotNull(connection);
+
+        // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
+        final StatusWithUuid status = insertBridge(connection, getOpenVSwitchTableUUID(connection));
+        assertTrue(status.isSuccess());
+
+        // Thread.sleep(3000);  // wait for _real_ controller to be added to bridge... or not (see below **)
+
+        // 3. Test against bug 960: Add same controller multiple times and make sure we do not end up with duplicates.
+        ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
+        ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
+        ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
+        ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
+
+        Row bridgeRow = ovsdbConfigurationService.getRow(node,
+                                                  ovsdbConfigurationService.getTableName(node, Bridge.class),
+                                                  status.getUuid().toString());
+        assertNotNull(bridgeRow);
+        Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
+        assertTrue(bridge.getUuid().equals(status.getUuid()));
+
+        final int currControllersSize = bridge.getControllerColumn().getData().size();
+
+        LOG.debug("Bridge has {} controllers", currControllersSize);
+
+        // ** Note: we assert against 2 or less -- instead of 1 -- to account for the _real_ controller's connection
+        assertTrue( "Too few controllers added to bridge object. Is this bug 960?", currControllersSize >= 1 );
+        assertTrue( "Too many controllers added to bridge object. Is this bug 960?", currControllersSize <= 2 );
+
+        // Removal of bridge created in this test is done via tearDown(). It is done that way, so cleanup is ran
+        // even if test fails.
+    }
+
+    @After
+    public void tearDown() throws InterruptedException {
+        Thread.sleep(5000);
+        OvsdbConnectionService
+                connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
+
+        if (connectionService.getNodes() == null) {
+            return;  // no nodes: noop
+        }
+
+        int bridgesRemoved = 0;
+        List<Node> nodes = connectionService.getNodes();
+        for (Node node : nodes) {
+            Map<String, Row> bridgeRows =
+                    ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
+            if (bridgeRows == null) {
+                continue;
+            }
+            for (Row bridgeRow : bridgeRows.values()) {
+                Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
+                LOG.trace("Test clean up removing Bridge {}", bridge.getUuid());
+                Status delStatus = ovsdbConfigurationService.deleteRow(node,
+                                                                bridge.getSchema().getName(),
+                                                                bridge.getUuid().toString());
+                assertTrue(delStatus.isSuccess());
+                bridgesRemoved++;
+            }
+        }
+
+        if (bridgesRemoved > 0) {
+            LOG.debug("Test clean up removed {} bridges", bridgesRemoved);
+            Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
+        }
+    }
+
     public void endToEndApiTest(Connection connection, String parentUuid) throws Exception {
         // 1. Print Cache and Assert to make sure the bridge is not created yet.
         printCache();
@@ -176,18 +294,18 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
         // 3. Assert to make sure the bridge is created with a valid Uuid.
         printCache();
         Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
-        Row bridgeRow = ovsdbConfigService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
+        Row bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
         assertNotNull(bridgeRow);
         bridge = connection.getClient().getTypedRowWrapper(Bridge.class, bridgeRow);
         assertEquals(bridge.getUuid(), status.getUuid());
 
         // 4. Delete the bridge & Assert to make sure the return status is success.
-        Status delStatus = ovsdbConfigService.deleteRow(node, bridge.getSchema().getName(), status.getUuid().toString());
+        Status delStatus = ovsdbConfigurationService.deleteRow(node, bridge.getSchema().getName(), status.getUuid().toString());
         assertTrue(delStatus.isSuccess());
         Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
 
         // 5. Assert to make sure the bridge is deleted
-        bridgeRow = ovsdbConfigService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
+        bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
         assertNull(bridgeRow);
     }
 
@@ -196,25 +314,55 @@ public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
         bridge.setName("br_test1");
         bridge.setStatus(ImmutableMap.of("key", "value"));
         bridge.setFloodVlans(Sets.newHashSet(34L));
-        return ovsdbConfigService.insertRow(node, bridge.getSchema().getName(), parentUuid, bridge.getRow());
+        return ovsdbConfigurationService.insertRow(node, bridge.getSchema().getName(), parentUuid, bridge.getRow());
     }
 
     public String getOpenVSwitchTableUUID(Connection connection) throws Exception {
         OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
-        ConcurrentMap<String, Row> row = ovsdbConfigService.getRows(node, openVSwitch.getSchema().getName());
-        if (row == null || row.size() == 0) return null;
+        ConcurrentMap<String, Row> row = ovsdbConfigurationService.getRows(node, openVSwitch.getSchema().getName());
+        if (row == null || row.size() == 0) {
+            return null;
+        }
         return (String)row.keySet().toArray()[0];
     }
 
     public void printCache() throws Exception {
-        List<String> tables = ovsdbConfigService.getTables(node);
+        List<String> tables = ovsdbConfigurationService.getTables(node);
         System.out.println("Tables = "+tables);
         assertNotNull(tables);
         for (String table : tables) {
             System.out.println("Table "+table);
-            ConcurrentMap<String,Row> row = ovsdbConfigService.getRows(node, table);
+            ConcurrentMap<String,Row> row = ovsdbConfigurationService.getRows(node, table);
             System.out.println(row);
         }
     }
 
+    public class FakeListener implements OvsdbInventoryListener {
+
+        @Override
+        public void nodeAdded(Node node, InetAddress address, int port) {
+
+        }
+
+        @Override
+        public void nodeRemoved(Node node) {
+
+        }
+
+        @Override
+        public void rowAdded(Node node, String tableName, String uuid, Row row) {
+
+        }
+
+        @Override
+        public void rowUpdated(Node node, String tableName, String uuid, Row old, Row row) {
+
+        }
+
+        @Override
+        public void rowRemoved(Node node, String tableName, String uuid, Row row, Object context) {
+
+        }
+    }
+
 }