import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.MoreExecutors;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.UnknownHostException;
}
@Override
+ @SuppressFBWarnings("REC_CATCH_EXCEPTION")
@SuppressWarnings("checkstyle:IllegalCatch")
public void disconnected(final OvsdbClient client) {
alreadyProcessedClients.remove(client);
// HWVTEP device.
if (hwvtepConnectionInstance.getHasDeviceOwnership()) {
unregisterEntityForOwnership(hwvtepConnectionInstance);
+ LOG.info("Client disconnected from the Leader. Delete the Hvtep Node {} ",
+ hwvtepConnectionInstance.getInstanceIdentifier());
txInvoker.invoke(new HwvtepGlobalRemoveCommand(hwvtepConnectionInstance, null, null));
} else {
unregisterEntityForOwnership(hwvtepConnectionInstance);
+ LOG.info("Client disconnected from the Follower. Not deleteing the Hvtep Node {} ",
+ hwvtepConnectionInstance.getInstanceIdentifier());
+
//Do not delete if client disconnected from follower HwvtepGlobalRemoveCommand
}
// In such cases, we will see if the hwvtepConnectionInstance has same externalClient.
if (hwvtepConnectionInstance != null) {
if (hwvtepConnectionInstance.hasOvsdbClient(externalClient)) {
- LOG.warn("HWVTEP Connection Instance {} already exists for client {}", key, externalClient);
+ LOG.info("HWVTEP Connection Instance {} already exists for client {}", key, externalClient);
return hwvtepConnectionInstance;
}
- LOG.warn("HWVTEP Connection Instance {} being replaced with client {}", key, externalClient);
+ LOG.info("HWVTEP Connection Instance {} being replaced with client {}", key, externalClient);
hwvtepConnectionInstance.disconnect();
// Unregister Cluster Ownership for ConnectionInfo
PhysicalSwitchAugmentation switchNode = node.augmentation(PhysicalSwitchAugmentation.class);
if (hwvtepGlobal != null) {
if (hwvtepGlobal.getConnectionInfo() != null) {
+ LOG.debug("Get the ConnectionInfo from HwvtepGlobal {}", hwvtepGlobal.getConnectionInfo());
return getConnectionInstance(hwvtepGlobal.getConnectionInfo());
} else {
//TODO: Case of user configured connection for now
}
}
else if (switchNode != null) {
+ LOG.debug("Get the ConnectionInfo from PhysicalSwitch");
return getConnectionInstance(switchNode);
} else {
LOG.warn("This is not a node that gives any hint how to find its OVSDB Manager: {}",node);
}
InstanceIdentifier<Node> globalNodeIid = HwvtepSouthboundUtil.getGlobalNodeIid(nodeIid);
if (globalNodeIid != null) {
+ LOG.debug("Get the ConnectionInfo from HwvtepGlobal : {}", globalNodeIid);
return nodeIidVsConnectionInstance.get(globalNodeIid);
}
return null;
Entity candidateEntity = getEntityFromConnectionInstance(hwvtepConnectionInstance);
if (entityConnectionMap.get(candidateEntity) != null) {
InstanceIdentifier<Node> iid = hwvtepConnectionInstance.getInstanceIdentifier();
+ LOG.info("Calling disconnect before processing new connection for {}", candidateEntity);
disconnected(entityConnectionMap.get(candidateEntity).getOvsdbClient());
hwvtepConnectionInstance.setInstanceIdentifier(iid);
putConnectionInstance(hwvtepConnectionInstance.getInstanceIdentifier(), hwvtepConnectionInstance);
} else {
globalRow = null;
}
- LOG.trace("Fetched global {} from hardware_vtep schema", globalRow);
+ LOG.info("Fetched global {} from hardware_vtep schema", globalRow);
return globalRow;
}
iid = HwvtepSouthboundMapper.getInstanceIdentifier(hwvtepGlobalRow);
/* Let's set the iid now */
hwvtepConnectionInstance.setInstanceIdentifier(iid);
- LOG.info("InstanceIdentifier {} generated for device "
+ LOG.trace("InstanceIdentifier {} generated for device "
+ "connection {}",iid, hwvtepConnectionInstance.getConnectionInfo());
controllerTxHistory.putIfAbsent(iid,
new TransactionHistory(TRANSACTION_HISTORY_CAPACITY, TRANSACTION_HISTORY_WATERMARK));
// If entity has no owner, clean up the operational data store (it's possible because owner controller
// might went down abruptly and didn't get a chance to clean up the operational data store.
if (!ownershipChange.getState().hasOwner()) {
- LOG.debug("{} has no owner, cleaning up the operational data store", ownershipChange.getEntity());
+ LOG.info("{} has no owner, cleaning up the operational data store", ownershipChange.getEntity());
// Below code might look weird but it's required. We want to give first opportunity to the
// previous owner of the device to clean up the operational data store if there is no owner now.
// That way we will avoid lot of nasty md-sal exceptions because of concurrent delete.
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.mdsal.binding.api.DataObjectModification;
import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.ovsdb.hwvtepsouthbound.transact.HwvtepOperationalState;
import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommandAggregator;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
updateData(changes);
disconnect(changes);
- /*
- for (DataTreeModification<Node> change : changes) {
- final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
- final DataObjectModification<Node> mod = change.getRootNode();
- switch (mod.getModificationType()) {
- case DELETE:
- LOG.trace("Data deleted: {}", mod.getDataBefore());
- //disconnect(mod);
- break;
- case SUBTREE_MODIFIED:
- LOG.trace("Data modified: {} to {}", mod.getDataBefore(),mod.getDataAfter());
- updateConnections(mod);
- break;
- case WRITE:
- if (mod.getDataBefore() == null) {
- LOG.trace("Data added: {}", mod.getDataAfter());
- connect(mod.getDataAfter());
- } else {
- LOG.trace("Data modified: {} to {}", mod.getDataBefore(),mod.getDataAfter());
- updateConnections(mod);
- }
- break;
- default:
- throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
- }
- }
- */
+
+ disconnectViaCli(changes);
}
private void connect(Collection<DataTreeModification<Node>> changes) {
LOG.trace("Connection Change Map: {}", result);
return result;
}
+
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ private void disconnectViaCli(Collection<DataTreeModification<Node>> changes) {
+ for (DataTreeModification<Node> change : changes) {
+ String nodeId = change.getRootPath().getRootIdentifier().firstKeyOf(Node.class).getNodeId().getValue();
+ if (!nodeId.contains("/disconnect")) {
+ continue;
+ }
+ int reconcileIndex = nodeId.indexOf("/disconnect");
+ String globalNodeId = nodeId.substring(0, reconcileIndex);
+ InstanceIdentifier<Node> globalNodeIid = change.getRootPath()
+ .getRootIdentifier().firstIdentifierOf(Topology.class)
+ .child(Node.class, new NodeKey(new NodeId(globalNodeId)));
+ HwvtepConnectionInstance connectionInstance = hcm.getConnectionInstanceFromNodeIid(globalNodeIid);
+ if (connectionInstance != null) {
+ LOG.error("Disconnecting from controller {}", nodeId);
+ new Thread(() -> {
+ ReadWriteTransaction tx = db.newReadWriteTransaction();
+ tx.delete(LogicalDatastoreType.CONFIGURATION, change.getRootPath().getRootIdentifier());
+ try {
+ tx.commit().get();
+ } catch (ExecutionException | InterruptedException e) {
+ LOG.error("Failed to delete the node {}", change.getRootPath().getRootIdentifier());
+ }
+ }).start();
+ try {
+ connectionInstance.disconnect();
+ } catch (Exception e) {
+ LOG.debug("Failed to disconnect");
+ }
+ }
+ }
+ }
}
if (deviceData != null) {
uuid = deviceData.getUuid();
data = deviceData.getData();
+ LOG.trace("Uuid already present for the key going in transit {}", key);
}
HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
new DeviceData(key, uuid, data, DeviceDataStatus.IN_TRANSIT));
--- /dev/null
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.ovsdb.hwvtepsouthbound;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@Command(scope = "hwvtep", name = "disconnect", description = "Disconnect a node")
+public class HwvtepDisconnectCliCmd extends OsgiCommandSupport {
+
+ private DataBroker dataBroker;
+
+ @Option(name = "-nodeid", description = "Node Id",
+ required = false, multiValued = false)
+ String nodeid;
+
+ public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri("hwvtep:1"));
+
+ public void setDataBroker(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ @SuppressFBWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
+ protected Object doExecute() throws Exception {
+ ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+ tx.put(LogicalDatastoreType.CONFIGURATION, getIid(),
+ new NodeBuilder().setNodeId(new NodeId(new Uri(nodeid + "/disconnect"))).build());
+ tx.commit().get();
+ session.getConsole().println("Successfully disconnected " + nodeid);
+ return "";
+ }
+
+ private InstanceIdentifier<Node> getIid() {
+ NodeId nodeId = new NodeId(new Uri(nodeid + "/disconnect"));
+ NodeKey nodeKey = new NodeKey(nodeId);
+ TopologyKey topoKey = new TopologyKey(HWVTEP_TOPOLOGY_ID);
+ return InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, topoKey)
+ .child(Node.class, nodeKey)
+ .build();
+ }
+}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
.getValue();
UUID lsUUID = getLsUuid(lsIid);
if (lsUUID == null) {
- LOG.warn("Could not find uuid for ls key {}", lsIid);
+ LOG.warn("Could not find uuid for ls key {}", getNodeKeyStr(lsIid));
return null;
}
}
}
+ protected <T extends DataObject> String getNodeKeyStr(InstanceIdentifier<T> iid) {
+ return iid.firstKeyOf(Node.class).getNodeId().getValue() + "." + getLsKeyStr(iid);
+ }
+
+ protected <T extends DataObject> String getLsKeyStr(InstanceIdentifier<T> iid) {
+ return ((InstanceIdentifier<LogicalSwitches>)iid).firstKeyOf(LogicalSwitches.class)
+ .getHwvtepNodeName().getValue();
+ }
+
public UUID getLsUuid(InstanceIdentifier lsIid) {
UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
if (lsUUID == null) {
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class AbstractTransactCommand<T extends Identifiable<I>, I extends Identifier<T>,
+public abstract class AbstractTransactCommand<T extends Identifiable<I> & DataObject, I extends Identifier<T>,
A extends Augmentation<Node>> implements TransactCommand<T> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractTransactCommand.class);
inTransitDependencies.put(classType, Lists.newArrayList(key));
}
}
- LOG.info("Update received for key: {} txId: {}", key, getOperationalState().getTransactionId());
+ LOG.info("Update received for key: {} txId: {}", getNodeKeyStr(key), getOperationalState().getTransactionId());
if (HwvtepSouthboundUtil.isEmptyMap(confingDependencies)
&& HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
doDeviceTransaction(transaction, nodeIid, data, key, extraData);
clone.onSuccess(transaction);
}
};
- LOG.info("Update Adding to op wait queue for key: {} txId: {}", key, transactionId);
+ LOG.info("Update Adding to op wait queue for key: {} txId: {}", getNodeKeyStr(key), transactionId);
addJobToQueue(opWaitingJob);
return;
}
final InstanceIdentifier key) {
HwvtepDeviceInfo.DeviceData deviceData = getDeviceOpData(cls, key);
if (deviceData == null) {
- LOG.debug("Could not find data for key {}", key);
+ LOG.debug("Could not find data for key {}", getNodeKeyStr(key));
java.util.Optional<TypedBaseTable> optional =
getTableReader().getHwvtepTableEntryUUID(cls, key, null);
if (optional.isPresent()) {
- LOG.debug("Found the data for key from device {} ", key);
+ LOG.debug("Found the data for key from device {} ", getNodeKeyStr(key));
getDeviceInfo().updateDeviceOperData(cls, key, optional.get().getUuid(), optional.get());
return getDeviceOpData(cls, key);
} else {
- LOG.info("Could not Find the data for key from device {} ", key);
+ LOG.info("Could not Find the data for key from device {} ", getNodeKeyStr(key));
}
}
return deviceData;
}
- protected String getKeyStr(final InstanceIdentifier iid) {
- return iid.toString();
- }
-
public <K extends Identifiable> void addJobToQueue(final DependentJob<K> job) {
hwvtepOperationalState.getDeviceInfo().putKeyInDependencyQueue(job.getKey());
hwvtepOperationalState.getDeviceInfo().addJobToQueue(job);
public HwvtepOperationalState newOperState() {
return new HwvtepOperationalState(getConnectionInstance());
}
+
+ protected String getNodeKeyStr(InstanceIdentifier<T> iid) {
+ return getClassType().getTypeName() + "."
+ + iid.firstKeyOf(Node.class).getNodeId().getValue() + "." + getKeyStr(iid);
+ }
+
+ protected String getKeyStr(InstanceIdentifier<T> iid) {
+ return iid.toString();
+ }
+
+ protected String getLsKeyStr(InstanceIdentifier iid) {
+ return ((InstanceIdentifier<LogicalSwitches>)iid).firstKeyOf(LogicalSwitches.class)
+ .getHwvtepNodeName().getValue();
+ }
}
getDeviceInfo().clearLogicalSwitchRefs(mdsalUpdate.getKey());
}
}
+
+ @Override
+ protected String getKeyStr(InstanceIdentifier<LogicalSwitches> iid) {
+ return iid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
+ }
}
return true;
}
+ @Override
+ protected String getKeyStr(InstanceIdentifier<LogicalSwitches> iid) {
+ return iid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
+ }
}
protected boolean areEqual(final LogicalSwitches sw1, final LogicalSwitches sw2) {
return sw1.key().equals(sw2.key()) && Objects.equals(sw1.getTunnelKey(), sw2.getTunnelKey());
}
+
+ @Override
+ protected String getKeyStr(InstanceIdentifier<LogicalSwitches> iid) {
+ return iid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
+ }
}
protected boolean isDeleteCmd() {
return true;
}
+
+ @Override
+ protected String getKeyStr(InstanceIdentifier<LocalMcastMacs> iid) {
+ return getLsKeyStr(iid.firstKeyOf(LocalMcastMacs.class).getLogicalSwitchRef().getValue());
+ }
}
protected Map<LocalMcastMacsKey, LocalMcastMacs> getData(final HwvtepGlobalAugmentation augmentation) {
return augmentation.getLocalMcastMacs();
}
+
+ @Override
+ protected String getKeyStr(InstanceIdentifier<LocalMcastMacs> iid) {
+ return getLsKeyStr(iid.firstKeyOf(LocalMcastMacs.class).getLogicalSwitchRef().getValue());
+ }
}
return true;
}
+ @Override
+ protected String getKeyStr(InstanceIdentifier<RemoteMcastMacs> iid) {
+ return getLsKeyStr(iid.firstKeyOf(RemoteMcastMacs.class).getLogicalSwitchRef().getValue());
+ }
}
}
}
+ @Override
+ protected String getKeyStr(InstanceIdentifier<RemoteMcastMacs> iid) {
+ return getLsKeyStr(iid.firstKeyOf(RemoteMcastMacs.class).getLogicalSwitchRef().getValue());
+ }
}
LOG.warn("Port not present in opdata store {}", key);
} else {
if (deviceData.getData() == null || !(deviceData.getData() instanceof PhysicalPort)) {
- LOG.error("Failed to get the device data for port {}", key);
+ LOG.error("Failed to get the device data for port {}", getKeyStr(key));
}
Map<Long, UUID> bindingMap = setVlanBindings(nodeIid, physicalPort, data, key, transaction);
PhysicalPort tp = (PhysicalPort) deviceData.getData();
return true;
}
+ @Override
+ protected String getKeyStr(InstanceIdentifier<RemoteUcastMacs> iid) {
+ return getLsKeyStr(iid.firstKeyOf(RemoteUcastMacs.class).getLogicalSwitchRef().getValue());
+ }
}
addToUpdates(macKey, remoteUcastMac);
} else {
LOG.warn("Unable to update remoteUcastMacs {} because uuid not found in the operational store txId: {}",
- macKey, getOperationalState().getTransactionId());
+ getNodeKeyStr(macKey) , getOperationalState().getTransactionId());
}
return;
}
(InstanceIdentifier<LogicalSwitches>) mac.getLogicalSwitchRef().getValue(), macIid, mac);
}
}
+
+ @Override
+ protected String getKeyStr(InstanceIdentifier<RemoteUcastMacs> iid) {
+ return getLsKeyStr(iid.firstKeyOf(RemoteUcastMacs.class).getLogicalSwitchRef().getValue());
+ }
}
<argument ref="hwvtepSouthboundProvider" />
</action>
</command>
+ <command>
+ <action class="org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDisconnectCliCmd">
+ <property name="dataBroker" ref="dataBroker" />
+ </action>
+ </command>
</command-bundle>
</blueprint>