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.ovsdb.utils.mdsal.node.NodeUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.ovsdb.utils.mdsal.node.NodeUtils;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
public class FlowCapableNodeDataChangeListener implements DataChangeListener, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeDataChangeListener.class);
private ListenerRegistration<DataChangeListener> registration;
+ private final Object nodeCacheLock = new Object();
private List<Node> nodeCache = Lists.newArrayList();
- private NetworkingProviderManager networkingProviderManager = null;
private PipelineOrchestrator pipelineOrchestrator = null;
private NodeCacheManager nodeCacheManager = null;
for (InstanceIdentifier instanceIdentifier : changes.getRemovedPaths()) {
DataObject originalDataObject = changes.getOriginalData().get(instanceIdentifier);
- LOG.info(">>>>> removed iiD: {} - dataObject {}", instanceIdentifier, originalDataObject);
- if (originalDataObject != null && originalDataObject instanceof Node){
+ if (originalDataObject instanceof Node) {
Node node = (Node) originalDataObject;
- notifyNodeRemoved(NodeUtils.getOpenFlowNode(node.getId().getValue()));
+ String openflowId = node.getId().getValue();
+ LOG.info(">>>>> removed iiD: {} - NodeKey: {}", instanceIdentifier, openflowId);
+ Node openFlowNode = NodeUtils.getOpenFlowNode(openflowId);
+ if (removeNodeFromCache(openFlowNode)) {
+ notifyNodeRemoved(openFlowNode);
+ }
}
}
LOG.info(">>>>> created iiD: {} - first: {} - NodeKey: {}",
iID, iID.firstIdentifierOf(Node.class), openflowId);
Node openFlowNode = NodeUtils.getOpenFlowNode(openflowId);
- if (nodeCache.contains(openFlowNode)) {
- notifyNodeUpdated(openFlowNode);
- } else {
+ if (addNodeToCache(openFlowNode)) {
notifyNodeCreated(openFlowNode);
+ } else {
+ notifyNodeUpdated(openFlowNode);
}
}
LOG.info(">>>>> updated iiD: {} - first: {} - NodeKey: {}",
iID, iID.firstIdentifierOf(Node.class), openflowId);
Node openFlowNode = NodeUtils.getOpenFlowNode(openflowId);
- if (nodeCache.contains(openFlowNode)) {
- notifyNodeUpdated(openFlowNode);
+ if (addNodeToCache(openFlowNode)) {
+ notifyNodeCreated(openFlowNode);
} else {
+ notifyNodeUpdated(openFlowNode);
+ }
+ }
+ }
+
+ public void notifyFlowCapableNodeEvent (String openFlowId, Action action) {
+ LOG.debug("Notification of flow capable node {}, action {}", openFlowId, action);
+ checkMemberInitialization();
+
+ Node openFlowNode = NodeUtils.getOpenFlowNode(openFlowId);
+ if (action == Action.DELETE) {
+ notifyNodeRemoved(openFlowNode);
+ } else {
+ if (addNodeToCache(openFlowNode)) {
notifyNodeCreated(openFlowNode);
+ } else {
+ notifyNodeUpdated(openFlowNode);
+ }
+ }
+ }
+
+ /**
+ * This method returns the true if node was added to the nodeCache. If param node
+ * is already in the cache, this method is expected to return false.
+ *
+ * @param openFlowNode the node to be added to the cache, if needed
+ * @return whether new node entry was added to cache
+ */
+ private Boolean addNodeToCache (Node openFlowNode) {
+ synchronized (nodeCacheLock) {
+ if (nodeCache.contains(openFlowNode)) {
+ return false;
}
+ return nodeCache.add(openFlowNode);
+ }
+ }
+
+ /**
+ * This method returns the true if node was removed from the nodeCache. If param node
+ * is not in the cache, this method is expected to return false.
+ *
+ * @param openFlowNode the node to be removed from the cache, if needed
+ * @return whether new node entry was removed from cache
+ */
+ private Boolean removeNodeFromCache (Node openFlowNode) {
+ synchronized (nodeCacheLock) {
+ return nodeCache.remove(openFlowNode);
}
}
private void notifyNodeUpdated (Node openFlowNode) {
final String openflowId = openFlowNode.getId().getValue();
- LOG.info("notifyNodeUpdated: Node {} from Controller's inventory Service", openflowId);
+ LOG.debug("notifyNodeUpdated: Node {} from Controller's inventory Service", openflowId);
// TODO: will do something amazing here, someday
}
final String openflowId = openFlowNode.getId().getValue();
LOG.info("notifyNodeCreated: Node {} from Controller's inventory Service", openflowId);
- nodeCache.add(openFlowNode);
-
if (pipelineOrchestrator != null) {
pipelineOrchestrator.enqueue(openflowId);
}
LOG.info("notifyNodeRemoved: Node {} from Controller's inventory Service",
openFlowNode.getId().getValue());
- nodeCache.remove(openFlowNode);
-
if (nodeCacheManager != null) {
nodeCacheManager.nodeRemoved(openFlowNode.getId().getValue());
}
}
- private void checkMemberInitialization() {
+ private void checkMemberInitialization () {
/**
* Obtain local ref to members, if needed. Having these local saves us from calling getGlobalInstance
* upon every event.
private static final short TABLE_0_DEFAULT_INGRESS = 0;
private static final short TABLE_1_ISOLATE_TENANT = 10;
private static final short TABLE_2_LOCAL_FORWARD = 20;
- private static final String OPENFLOW = "openflow:";
private static Long groupId = 1L;
private volatile ConfigurationService configurationService;
String bridgeName = configurationService.getExternalBridgeName();
String brUuid = this.getInternalBridgeUUID(node, bridgeName);
if (brUuid == null) {
- logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
+ // Note: it is okay for certain nodes to not have br-ex configured; not an error
+ logger.info("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
return 0L;
}
private void writeNormalRule(Long dpidLong) {
- String nodeName = OPENFLOW + dpidLong;
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
MatchBuilder matchBuilder = new MatchBuilder();
NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
InstructionBuilder ib,
Long dpidLong, Long port ,
List<Instruction> instructions) {
- NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
+ NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
logger.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
List<Action> actionList = Lists.newArrayList();
protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
Long dpidLong, Long port , List<Instruction> instructions) {
- NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
+ NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
logger.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
List<Action> actionList = Lists.newArrayList();
}
}
+ @Override
+ public void notifyFlowCapableNodeEvent(Long dpid, org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
+ mdsalConsumer.notifyFlowCapableNodeCreateEvent(Constants.OPENFLOW_NODE_PREFIX + dpid, action);
+ }
+
public static NodeBuilder createNodeBuilder(String nodeId) {
NodeBuilder builder = new NodeBuilder();
builder.setId(new NodeId(nodeId));
import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheListener;
import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
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.schema.openvswitch.Bridge;
import org.opendaylight.ovsdb.schema.openvswitch.Interface;
import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
import org.opendaylight.ovsdb.schema.openvswitch.Port;
+import org.opendaylight.ovsdb.utils.mdsal.node.StringConvertor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.slf4j.Logger;
} catch (Exception e) {
logger.error("Error fetching Interface Rows for node " + node, e);
}
+ } else if (tableName.equalsIgnoreCase(ovsdbConfigurationService.getTableName(node, Bridge.class))) {
+ logger.debug("Processing update of {}:{} node: {}, bridge uuid: {}, row: {}", tableName, action, node, uuid, row);
+ Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, row);
+ final Set<String> dpids = bridge.getDatapathIdColumn().getData();
+ if (dpids != null &&
+ (bridge.getName().equals(configurationService.getIntegrationBridgeName()) ||
+ bridge.getName().equals(configurationService.getExternalBridgeName()))) {
+ NetworkingProvider networkingProvider = networkingProviderManager.getProvider(node);
+ for (String dpid : dpids) {
+ networkingProvider.notifyFlowCapableNodeEvent(StringConvertor.dpidStringToLong(dpid), action);
+ }
+ }
}
}