<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<pluginManagement>
);
}
+ public static Option ovsdbPluginBundles() {
+ return new DefaultCompositeOption(
+ mavenBundle("org.opendaylight.ovsdb", "plugin").versionAsInProject(),
+ mavenBundle("org.mockito", "mockito-all").versionAsInProject()
+ );
+ }
+
public static Option ovsdbDefaultSchemaBundles() {
return new DefaultCompositeOption(
mavenBundle("org.opendaylight.ovsdb", "schema.openvswitch").versionAsInProject(),
mavenBundle("org.opendaylight.controller", "connectionmanager").versionAsInProject(),
mavenBundle("org.opendaylight.controller", "connectionmanager.implementation").versionAsInProject(),
mavenBundle("org.opendaylight.controller", "forwardingrulesmanager").versionAsInProject(),
- mavenBundle("org.opendaylight.ovsdb", "plugin").versionAsInProject(),
mavenBundle("org.opendaylight.ovsdb", "openstack.net-virt").versionAsInProject()
);
}
ConfigurationBundles.controllerBundles(),
ConfigurationBundles.ovsdbLibraryBundles(),
ConfigurationBundles.ovsdbDefaultSchemaBundles(),
+ ConfigurationBundles.ovsdbPluginBundles(),
ConfigurationBundles.ovsdbNeutronBundles(),
junitBundles()
);
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 javax.inject.Inject;
+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.opendaylight.ovsdb.lib.notation.Row;
import org.opendaylight.ovsdb.plugin.Connection;
import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
+import org.opendaylight.ovsdb.plugin.InventoryServiceInternal;
import org.opendaylight.ovsdb.plugin.OvsdbConfigService;
+import org.opendaylight.ovsdb.plugin.OvsdbInventoryListener;
import org.opendaylight.ovsdb.plugin.StatusWithUuid;
import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+
+import org.mockito.Mockito;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
@Inject
private BundleContext bc;
private OvsdbConfigService ovsdbConfigService = null;
+
+ @Inject
+ private InventoryServiceInternal inventoryService;
+
private Node node = null;
private OvsdbClient client = null;
ConfigurationBundles.controllerBundles(),
ConfigurationBundles.ovsdbLibraryBundles(),
ConfigurationBundles.ovsdbDefaultSchemaBundles(),
- mavenBundle("org.opendaylight.ovsdb", "plugin").versionAsInProject(),
+ ConfigurationBundles.ovsdbPluginBundles(),
junitBundles()
);
}
this.endToEndApiTest(connection, null);
}
+ @Test
+ public void testInventoryListeners(){
+ 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);
+
+ Node newNode = Node.fromString("OVS:10.10.10.10:65342");
+
+ // Trigger event
+ inventoryService.notifyNodeAdded(newNode);
+
+ Mockito.verify(listenerA, Mockito.times(1)).nodeAdded(newNode);
+ Mockito.verify(listenerB, Mockito.times(1)).nodeAdded(newNode);
+
+ dm.remove(componentA);
+ dm.remove(componentB);
+
+ }
+
public void endToEndApiTest(Connection connection, String parentUuid) throws Exception {
// 1. Print Cache and Assert to make sure the bridge is not created yet.
printCache();
}
}
+ public class FakeListener implements OvsdbInventoryListener{
+
+ @Override
+ public void nodeAdded(Node node) {
+
+ }
+
+ @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) {
+
+ }
+ }
+
}
c.setInterface(INeutronPortAware.class.getName(), null);
c.add(createServiceDependency().setService(OvsdbConfigService.class).setRequired(true));
c.add(createServiceDependency().setService(IConnectionServiceInternal.class).setRequired(true));
- c.add(createServiceDependency().setService(INeutronNetworkCRUD.class).setRequired(true));
c.add(createServiceDependency().setService(OvsdbInventoryListener.class).setRequired(true));
}
import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.ovsdb.lib.notation.Row;
+import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
import org.opendaylight.ovsdb.plugin.OvsdbConfigService;
import org.opendaylight.ovsdb.plugin.OvsdbInventoryListener;
import org.opendaylight.ovsdb.schema.openvswitch.Interface;
+import org.opendaylight.ovsdb.schema.openvswitch.Port;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
for (Node node : nodes) {
List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
try {
- ConcurrentMap<String, Row> interfaces = this.ovsdbConfigService.getRows(node, ovsdbConfigService.getTableName(node, Interface.class));
- if (interfaces != null) {
- for (String intfUUID : interfaces.keySet()) {
- Interface intf = ovsdbConfigService.getTypedRow(node, Interface.class, interfaces.get(intfUUID));
- String intfType = intf.getTypeColumn().getData();
- if (intfType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intfType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
- /* delete tunnel ports on this node */
- logger.trace("Delete tunnel intf {}", intf);
- inventoryListener.rowRemoved(node, intf.getSchema().getName(), intfUUID,
- intf.getRow(), null);
- } else if (!phyIfName.isEmpty() && phyIfName.contains(intf.getName())) {
- logger.trace("Delete physical intf {}", intf);
- inventoryListener.rowRemoved(node, intf.getSchema().getName(), intfUUID,
- intf.getRow(), null);
+ ConcurrentMap<String, Row> ports =
+ this.ovsdbConfigService.getRows(node,
+ ovsdbConfigService.getTableName(node, Port.class));
+ if (ports != null) {
+ for (Row portRow : ports.values()) {
+ Port port = ovsdbConfigService.getTypedRow(node, Port.class, portRow);
+ for (UUID interfaceUuid : port.getInterfacesColumn().getData()) {
+ Interface interfaceRow = (Interface) ovsdbConfigService
+ .getRow(node,
+ ovsdbConfigService.getTableName(node, Interface.class),
+ interfaceUuid.toString());
+
+ String interfaceType = interfaceRow.getTypeColumn().getData();
+ if (interfaceType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
+ || interfaceType.equalsIgnoreCase(
+ NetworkHandler.NETWORK_TYPE_GRE)) {
+ /* delete tunnel ports on this node */
+ logger.trace("Delete tunnel interface {}", interfaceRow);
+ ovsdbConfigService.deleteRow(node,
+ ovsdbConfigService.getTableName(node, Port.class),
+ port.getUuid().toString());
+ break;
+ } else if (!phyIfName.isEmpty() && phyIfName.contains(interfaceRow.getName())) {
+ logger.trace("Delete physical interface {}", interfaceRow);
+ ovsdbConfigService.deleteRow(node,
+ ovsdbConfigService.getTableName(node, Port.class),
+ port.getUuid().toString());
+ break;
+ }
}
}
}
*/
package org.opendaylight.ovsdb.openstack.netvirt;
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.ovsdb.lib.notation.Row;
+import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
import org.opendaylight.ovsdb.plugin.OvsdbConfigService;
import org.opendaylight.ovsdb.plugin.OvsdbInventoryListener;
import org.opendaylight.ovsdb.schema.openvswitch.Interface;
+import org.opendaylight.ovsdb.schema.openvswitch.Port;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private volatile OvsdbConfigService ovsdbConfigService;
private volatile IConnectionServiceInternal connectionService;
- private volatile INeutronNetworkCRUD neutronNetworkCache;
private volatile OvsdbInventoryListener ovsdbInventoryListener;
/**
/**
* Invoked to take action after a port has been deleted.
*
- * @param port An instance of deleted Neutron Port object.
+ * @param neutronPort An instance of deleted Neutron Port object.
*/
@Override
- public void neutronPortDeleted(NeutronPort port) {
+ public void neutronPortDeleted(NeutronPort neutronPort) {
- int result = canDeletePort(port);
+ int result = canDeletePort(neutronPort);
if (result != HttpURLConnection.HTTP_OK) {
logger.error(" deletePort validation failed - result {} ", result);
return;
}
- NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
List<Node> nodes = connectionService.getNodes();
for (Node node : nodes) {
try {
- ConcurrentMap<String, Row> interfaces = this.ovsdbConfigService.getRows(node, ovsdbConfigService.getTableName(node, Interface.class));
- if (interfaces != null) {
- for (String intfUUID : interfaces.keySet()) {
- Interface intf = ovsdbConfigService.getTypedRow(node, Interface.class, interfaces.get(intfUUID));
- Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
- if (externalIds == null) {
- logger.trace("No external_ids seen in {}", intf);
- continue;
- }
- /* Compare Neutron port uuid */
- String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID);
- if (neutronPortId == null) {
- continue;
- }
- if (neutronPortId.equalsIgnoreCase(port.getPortUUID())) {
- logger.trace("neutronPortDeleted: Delete interface {}", intf.getName());
- ovsdbInventoryListener.rowRemoved(node, intf.getSchema().getName(), intfUUID,
- intf.getRow(), neutronNetwork);
- break;
+ ConcurrentMap<String, Row> portRows =
+ this.ovsdbConfigService.getRows(node,
+ ovsdbConfigService.getTableName(node, Port.class));
+ if (portRows != null) {
+ for (Row portRow : portRows.values()) {
+ Port port = ovsdbConfigService.getTypedRow(node, Port.class, portRow);
+ for (UUID interfaceUuid : port.getInterfacesColumn().getData()) {
+ Interface interfaceRow = (Interface) ovsdbConfigService
+ .getRow(node,
+ ovsdbConfigService.getTableName(node, Interface.class),
+ interfaceUuid.toString());
+
+ Map<String, String> externalIds = interfaceRow.getExternalIdsColumn().getData();
+
+ if (externalIds == null) {
+ logger.trace("No external_ids seen in {}", interfaceRow);
+ continue;
+ }
+
+ /* Compare Neutron port uuid */
+ String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) {
+ continue;
+ }
+
+ if (neutronPortId.equalsIgnoreCase(neutronPort.getPortUUID())) {
+ logger.trace("neutronPortDeleted: Delete interface {}", interfaceRow.getName());
+ ovsdbConfigService.deleteRow(node,
+ ovsdbConfigService.getTableName(node, Port.class),
+ port.getUuid().toString());
+ break;
+ }
}
}
}
}
logger.debug(" PORT delete successful for tenant-id - {}, " +
" network-id - {}, port-id - {}",
- port.getTenantID(), port.getNetworkUUID(),
- port.getID());
+ neutronPort.getTenantID(), neutronPort.getNetworkUUID(),
+ neutronPort.getID());
}
}
.setCallbacks("setPluginOutInventoryServices",
"unsetPluginOutInventoryServices")
.setRequired(true));
+ c.add(createServiceDependency()
+ .setService(OvsdbInventoryListener.class)
+ .setCallbacks("listenerAdded", "listenerRemoved"));
c.add(createServiceDependency()
.setService(OvsdbConfigService.class)
.setCallbacks("setConfigurationService", "unsetConfigurationService")
import org.opendaylight.ovsdb.lib.notation.Row;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+
+import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private ScheduledExecutorService executor;
private OvsdbConfigService configurationService;
+ private Set<OvsdbInventoryListener> ovsdbInventoryListeners = Sets.newCopyOnWriteArraySet();
+
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
dbCache.put(n, db);
}
- OvsdbInventoryListener inventoryListener = (OvsdbInventoryListener)ServiceHelper.getGlobalInstance(OvsdbInventoryListener.class, this);
for (String tableName : tableUpdates.getUpdates().keySet()) {
Map<String, Row> tCache = db.getTableCache(databaseName, tableName);
TableUpdate update = tableUpdates.getUpdates().get(tableName);
db.updateRow(databaseName, tableName, uuid.toString(), update.getNew(uuid));
if (isNewRow) {
this.handleOpenVSwitchSpecialCase(n, databaseName, tableName, uuid);
- if (inventoryListener != null) inventoryListener.rowAdded(n, tableName, uuid.toString(), update.getNew(uuid));
+ if (!ovsdbInventoryListeners.isEmpty()) {
+ for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
+ listener.rowAdded(n, tableName, uuid.toString(), update.getNew(uuid));
+ }
+ }
} else {
- if (inventoryListener != null) inventoryListener.rowUpdated(n, tableName, uuid.toString(), update.getOld(uuid), update.getNew(uuid));
+ if (!ovsdbInventoryListeners.isEmpty()) {
+ for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
+ listener.rowUpdated(n, tableName, uuid.toString(), update.getOld(uuid), update.getNew(uuid));
+ }
+ }
}
} else if (update.getOld(uuid) != null){
if (tCache != null) {
- if (inventoryListener != null) inventoryListener.rowRemoved(n, tableName, uuid.toString(), update.getOld(uuid), update.getNew(uuid));
+ if (!ovsdbInventoryListeners.isEmpty()) {
+ for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
+ listener.rowRemoved(n, tableName, uuid.toString(), update.getOld(uuid), update.getNew(uuid));
+ }
+ }
}
db.removeRow(databaseName, tableName, uuid.toString());
}
@Override
public void notifyNodeAdded(Node node) {
- OvsdbInventoryListener inventoryListener = (OvsdbInventoryListener)ServiceHelper.getGlobalInstance(OvsdbInventoryListener.class, this);
- if (inventoryListener != null) {
- inventoryListener.nodeAdded(node);
+ if (!ovsdbInventoryListeners.isEmpty()) {
+ for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
+ listener.nodeAdded(node);
+ }
}
}
@Override
public void removeNode(Node node) {
- OvsdbInventoryListener inventoryListener = (OvsdbInventoryListener)ServiceHelper.getGlobalInstance(OvsdbInventoryListener.class, this);
- if (inventoryListener != null) {
- inventoryListener.nodeRemoved(node);
+ if (!ovsdbInventoryListeners.isEmpty()) {
+ for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
+ listener.nodeRemoved(node);
+ }
}
for (IPluginOutInventoryService service : pluginOutInventoryServices) {
public Set<Node> getConfiguredNotConnectedNodes() {
return Collections.emptySet();
}
+
+ private void listenerAdded(OvsdbInventoryListener listener) {
+ this.ovsdbInventoryListeners.add(listener);
+ }
+
+ private void listenerRemoved(OvsdbInventoryListener listener) {
+ this.ovsdbInventoryListeners.remove(listener);
+ }
}