blob: 815958fdd1c2b8de9fb1d79401405ee114de1e56 [file] [log] [blame]
package net.onrc.onos.core.topology;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.onrc.onos.core.datastore.DataStoreClient;
import net.onrc.onos.core.datastore.IKVClient;
import net.onrc.onos.core.datastore.topology.KVDevice;
import net.onrc.onos.core.datastore.topology.KVLink;
import net.onrc.onos.core.datastore.topology.KVPort;
import net.onrc.onos.core.datastore.topology.KVPort.STATUS;
import net.onrc.onos.core.datastore.topology.KVSwitch;
import net.onrc.onos.core.datastore.utils.KVObject;
import net.onrc.onos.core.datastore.utils.KVObject.WriteOp;
import net.onrc.onos.core.util.SwitchPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contains methods which write topology events into the key-value data store.
*/
public class TopologyDatastore {
private static final Logger log = LoggerFactory.getLogger(TopologyDatastore.class);
/**
* Add a switch to the database.
*
* @param sw the switch to add.
* @param portEvents the corresponding switch ports to add.
* @return true on success, otherwise false.
*/
public boolean addSwitch(SwitchEvent sw,
Collection<PortEvent> portEvents) {
log.debug("Adding switch {}", sw);
ArrayList<WriteOp> groupOp = new ArrayList<>();
KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);
IKVClient client = DataStoreClient.getClient();
// XXX Is ForceCreating Switch on DB OK here?
// If ForceCreating, who ever is calling this method needs
// to assure that DPID is unique cluster-wide, etc.
groupOp.add(rcSwitch.forceCreateOp(client));
for (PortEvent portEvent : portEvents) {
KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getPortNumber());
rcPort.setStatus(KVPort.STATUS.ACTIVE);
groupOp.add(rcPort.forceCreateOp(client));
}
boolean failed = KVObject.multiWrite(groupOp);
if (failed) {
log.error("Adding Switch {} and its ports failed.", sw.getDpid());
for (WriteOp op : groupOp) {
log.debug("Operation:{} for {} - Result:{}", op.getOperation(), op.getObject(), op.getStatus());
// If we changed the operation from ForceCreate to
// Conditional operation (Create/Update) then we should retry here.
}
}
return !failed;
}
/**
* Update a switch as inactive in the database.
*
* @param sw the switch to update.
* @param portEvents the corresponding switch ports to update.
* @return true on success, otherwise false.
*/
public boolean deactivateSwitch(SwitchEvent sw,
Collection<PortEvent> portEvents) {
log.debug("Deactivating switch {}", sw);
KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
IKVClient client = DataStoreClient.getClient();
List<WriteOp> groupOp = new ArrayList<>();
rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);
groupOp.add(rcSwitch.forceCreateOp(client));
for (PortEvent portEvent : portEvents) {
KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getPortNumber());
rcPort.setStatus(KVPort.STATUS.INACTIVE);
groupOp.add(rcPort.forceCreateOp(client));
}
boolean failed = KVObject.multiWrite(groupOp);
return !failed;
}
/**
* Add a port to the database.
*
* @param port the port to add.
* @return true on success, otherwise false.
*/
public boolean addPort(PortEvent port) {
log.debug("Adding port {}", port);
KVPort rcPort = new KVPort(port.getDpid(), port.getPortNumber());
rcPort.setStatus(KVPort.STATUS.ACTIVE);
rcPort.forceCreate();
// TODO add description into KVPort
//rcPort.setDescription(port.getDescription());
return true;
}
/**
* Update a port as inactive in the database.
*
* @param port the port to update.
* @return true on success, otherwise false.
*/
public boolean deactivatePort(PortEvent port) {
log.debug("Deactivating port {}", port);
KVPort rcPort = new KVPort(port.getDpid(), port.getPortNumber());
rcPort.setStatus(STATUS.INACTIVE);
rcPort.forceCreate();
return true;
}
/**
* Add a link to the database.
*
* @param link the link to add.
* @return true on success, otherwise false.
*/
public boolean addLink(LinkEvent link) {
log.debug("Adding link {}", link);
KVLink rcLink = new KVLink(link.getSrc().getDpid(),
link.getSrc().getPortNumber(),
link.getDst().getDpid(),
link.getDst().getPortNumber());
// XXX This method is called only by discovery,
// which means what we are trying to write currently is the truth
// so we can force write here
//
// TODO: We need to check for errors
rcLink.setStatus(KVLink.STATUS.ACTIVE);
rcLink.forceCreate();
return true; // Success
}
public boolean removeLink(LinkEvent linkEvent) {
log.debug("Removing link {}", linkEvent);
KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getPortNumber(),
linkEvent.getDst().getDpid(), linkEvent.getDst().getPortNumber());
rcLink.forceDelete();
return true;
}
/**
* Add a device to the database.
*
* @param device the device to add.
* @return true on success, otherwise false.
*/
public boolean addHost(HostEvent device) {
log.debug("Adding host into DB. mac {}", device.getMac());
KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
for (SwitchPort sp : device.getAttachmentPoints()) {
byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getPortNumber());
rcDevice.addPortId(portId);
}
rcDevice.forceCreate();
return true;
}
/**
* Remove a device from the database.
*
* @param device the device to remove.
* @return true on success, otherwise false.
*/
public boolean removeHost(HostEvent device) {
log.debug("Removing host into DB. mac {}", device.getMac());
KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
rcDevice.forceDelete();
return true;
}
}