private final TransactionInvoker txInvoker;
private final Map<ConnectionInfo,InstanceIdentifier<Node>> instanceIdentifiers =
new ConcurrentHashMap<>();
+ private final Map<InstanceIdentifier<Node>, OvsdbConnectionInstance> nodeIdVsConnectionInstance =
+ new ConcurrentHashMap<>();
private final Map<Entity, OvsdbConnectionInstance> entityConnectionMap =
new ConcurrentHashMap<>();
private final EntityOwnershipService entityOwnershipService;
// not be used as a candidate in Entity election (given that this instance is
// about to disconnect as well), if current owner get disconnected from
// OVSDB device.
- unregisterEntityForOwnership(ovsdbConnectionInstance);
-
- txInvoker.invoke(new OvsdbNodeRemoveCommand(ovsdbConnectionInstance, null, null));
-
+ if (ovsdbConnectionInstance.getHasDeviceOwnership()) {
+ LOG.info("Library disconnected {} this controller instance has ownership", key);
+ deleteOperNodeAndReleaseOwnership(ovsdbConnectionInstance);
+ } else {
+ LOG.info("Library disconnected {} this controller does not have ownership", key);
+ unregisterEntityForOwnership(ovsdbConnectionInstance);
+ }
removeConnectionInstance(key);
//Controller initiated connection can be terminated from switch side.
//So cleanup the instance identifier cache.
removeInstanceIdentifier(key);
+ nodeIdVsConnectionInstance.remove(ovsdbConnectionInstance.getInstanceIdentifier(),
+ ovsdbConnectionInstance);
stopBridgeConfigReconciliationIfActive(ovsdbConnectionInstance.getInstanceIdentifier());
retryConnection(ovsdbConnectionInstance.getInstanceIdentifier(),
ovsdbConnectionInstance.getOvsdbNodeAugmentation(),
LOG.trace("OvsdbConnectionManager: exit disconnected client: {}", client);
}
+ private void deleteOperNodeAndReleaseOwnership(final OvsdbConnectionInstance ovsdbConnectionInstance) {
+ ovsdbConnectionInstance.setHasDeviceOwnership(false);
+ final InstanceIdentifier nodeIid = ovsdbConnectionInstance.getInstanceIdentifier();
+ //remove the node from oper only if it has ownership
+ txInvoker.invoke(new OvsdbNodeRemoveCommand(ovsdbConnectionInstance, null, null) {
+
+ @Override
+ public void onSuccess() {
+ super.onSuccess();
+ LOG.debug("Successfully removed node {} from oper", nodeIid);
+ //Giveup the ownership only after cleanup is done
+ unregisterEntityForOwnership(ovsdbConnectionInstance);
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.debug("Failed to remove node {} from oper", nodeIid);
+ super.onFailure(throwable);
+ unregisterEntityForOwnership(ovsdbConnectionInstance);
+ }
+ });
+ }
+
public OvsdbClient connect(InstanceIdentifier<Node> iid,
OvsdbNodeAugmentation ovsdbNode) throws UnknownHostException, ConnectException {
LOG.info("Connecting to {}", SouthboundUtil.connectionInfoToString(ovsdbNode.getConnectionInfo()));
OvsdbConnectionInstance client = getConnectionInstance(ovsdbNode.getConnectionInfo());
if (client != null) {
// Unregister Cluster Onwership for ConnectionInfo
- unregisterEntityForOwnership(client);
+ deleteOperNodeAndReleaseOwnership(client);
client.disconnect();
}
public OvsdbConnectionInstance getConnectionInstance(InstanceIdentifier<Node> nodePath) {
+ if (nodeIdVsConnectionInstance.get(nodePath) != null) {
+ return nodeIdVsConnectionInstance.get(nodePath);
+ }
try {
ReadOnlyTransaction transaction = db.newReadOnlyTransaction();
CheckedFuture<Optional<Node>, ReadFailedException> nodeFuture = transaction.read(
}
private void registerEntityForOwnership(OvsdbConnectionInstance ovsdbConnectionInstance) {
+ putConnectionInstance(ovsdbConnectionInstance.getMDConnectionInfo(), ovsdbConnectionInstance);
Entity candidateEntity = getEntityFromConnectionInstance(ovsdbConnectionInstance);
+ if (entityConnectionMap.containsKey(candidateEntity)) {
+ LOG.error("Old connection still hanging for {}", candidateEntity);
+ disconnected(ovsdbConnectionInstance.getOvsdbClient());
+ //TODO do cleanup for old connection or stale check
+ }
+ nodeIdVsConnectionInstance.put((InstanceIdentifier<Node>) candidateEntity.getIdentifier(),
+ ovsdbConnectionInstance);
entityConnectionMap.put(candidateEntity, ovsdbConnectionInstance);
ovsdbConnectionInstance.setConnectedEntity(candidateEntity);
try {
ovsdbConnectionInstance.setDeviceOwnershipCandidateRegistration(registration);
LOG.info("OVSDB entity {} is registered for ownership.", candidateEntity);
- //If entity already has owner, it won't get notification from EntityOwnershipService
- //so cache the connection instances.
- Optional<EntityOwnershipState> ownershipStateOpt =
- entityOwnershipService.getOwnershipState(candidateEntity);
- if (ownershipStateOpt.isPresent()) {
- EntityOwnershipState ownershipState = ownershipStateOpt.get();
- if (ownershipState == EntityOwnershipState.OWNED_BY_OTHER) {
- LOG.info("OVSDB entity {} is already owned by other southbound plugin "
- + "instance, so *this* instance is NOT an OWNER of the device",
- ovsdbConnectionInstance.getConnectionInfo());
- putConnectionInstance(ovsdbConnectionInstance.getMDConnectionInfo(),ovsdbConnectionInstance);
- }
- }
} catch (CandidateAlreadyRegisteredException e) {
LOG.warn("OVSDB entity {} was already registered for ownership", candidateEntity, e);
}
-
+ //If entity already has owner, it won't get notification from EntityOwnershipService
+ Optional<EntityOwnershipState> ownershipStateOpt =
+ entityOwnershipService.getOwnershipState(candidateEntity);
+ if (ownershipStateOpt.isPresent()) {
+ EntityOwnershipState ownershipState = ownershipStateOpt.get();
+ if (ownershipState == EntityOwnershipState.OWNED_BY_OTHER) {
+ ovsdbConnectionInstance.setHasDeviceOwnership(false);
+ } else if (ownershipState == EntityOwnershipState.IS_OWNER) {
+ ovsdbConnectionInstance.setHasDeviceOwnership(true);
+ ovsdbConnectionInstance.registerCallbacks(instanceIdentifierCodec);
+ }
+ }
}
private void unregisterEntityForOwnership(OvsdbConnectionInstance ovsdbConnectionInstance) {
ovsdbConnectionInstance.closeDeviceOwnershipCandidateRegistration();
- entityConnectionMap.remove(ovsdbConnectionInstance.getConnectedEntity());
+ entityConnectionMap.remove(ovsdbConnectionInstance.getConnectedEntity(), ovsdbConnectionInstance);
}
private void retryConnection(final InstanceIdentifier<Node> iid, final OvsdbNodeAugmentation ovsdbNode,
private final InstanceIdentifierCodec instanceIdentifierCodec;
private final Map<UUID,Bridge> updatedBridgeRows;
private final Map<UUID, Bridge> oldBridgeRows;
+ private final List<InstanceIdentifier<Node>> updatedBridges = new ArrayList<>();
public OvsdbBridgeUpdateCommand(InstanceIdentifierCodec instanceIdentifierCodec, OvsdbConnectionInstance key,
TableUpdates updates, DatabaseSchema dbSchema) {
InstanceIdentifier<Node> bridgeIid = getInstanceIdentifier(bridge);
Node bridgeNode = buildBridgeNode(bridge);
transaction.merge(LogicalDatastoreType.OPERATIONAL, bridgeIid, bridgeNode);
- deleteEntries(transaction, protocolEntriesToRemove(bridgeIid,bridge));
+ updatedBridges.add(bridgeIid);
+ deleteEntries(transaction, protocolEntriesToRemove(bridgeIid, bridge));
deleteEntries(transaction, externalIdsToRemove(bridgeIid,bridge));
deleteEntries(transaction, bridgeOtherConfigsToRemove(bridgeIid,bridge));
}
NodeKey nodeKey = getInstanceIdentifier(bridge).firstKeyOf(Node.class);
return nodeKey.getNodeId();
}
+
+ public void onSuccess() {
+ for (InstanceIdentifier<Node> updatedBridge : updatedBridges) {
+ LOG.debug("Updated bridge {} in operational datastore", updatedBridge);
+ }
+ }
+
+ public void onFailure(Throwable throwable) {
+ for (InstanceIdentifier<Node> updatedBridge : updatedBridges) {
+ LOG.error("Failed to update bridge {} in operational datastore", updatedBridge);
+ }
+ }
}