blob: 61dde3abd56bc7b4627bba2519d564df5d50d172 [file] [log] [blame]
package net.onrc.onos.ofcontroller.networkgraph;
import java.util.ArrayList;
import java.util.List;
import net.onrc.onos.datastore.RCObject;
import net.onrc.onos.datastore.RCObject.WriteOp;
import net.onrc.onos.datastore.topology.RCLink;
import net.onrc.onos.datastore.topology.RCPort;
import net.onrc.onos.datastore.topology.RCPort.STATUS;
import net.onrc.onos.datastore.topology.RCSwitch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The southbound interface to the network graph which allows clients to
* mutate the graph. This class will maintain the invariants of the network
* graph. The southbound discovery modules will use this interface to update
* the network graph as they learn about the state of the network.
*
* Modification to the Network Map by this module will:
* 1. Writes to Cluster-wide DataStore.
* 2. Update ONOS instance In-memory Network Map.
* 3. Send-out Notification. (TBD)
* (XXX: To update other instances In-memory Network Map,
* notification should be triggered here.
* But if we want to aggregate notification to minimize notification,
* It might be better for the caller to trigger notification.)
*
*/
public class NetworkGraphDatastore {
private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
/**
* Add a switch to the database.
*
* @param sw the switch to add.
* @return true on success, otherwise false.
*/
public boolean addSwitch(SwitchEvent sw) {
log.debug("Adding switch {}", sw);
ArrayList<WriteOp> groupOp = new ArrayList<>();
RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
// 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(WriteOp.ForceCreate(rcSwitch));
for (PortEvent portEvent : sw.getPorts()) {
RCPort rcPort = new RCPort(sw.getDpid(), portEvent.getNumber());
rcPort.setStatus(RCPort.STATUS.ACTIVE);
groupOp.add(WriteOp.ForceCreate(rcPort));
}
boolean failed = RCObject.multiWrite(groupOp);
if (failed) {
log.error("Adding Switch {} and its ports failed.", sw.getDpid());
for (WriteOp op : groupOp) {
log.debug("Operation:{} for {} - Result:{}", op.getOp(), 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.
* @return true on success, otherwise false.
*/
public boolean deactivateSwitch(SwitchEvent sw) {
log.debug("Deactivating switch {}", sw);
RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
List<WriteOp> groupOp = new ArrayList<>();
rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
groupOp.add(WriteOp.ForceCreate(rcSwitch));
for (PortEvent portEvent : sw.getPorts()) {
RCPort rcPort = new RCPort(sw.getDpid(), (long)portEvent.getNumber());
rcPort.setStatus(RCPort.STATUS.INACTIVE);
groupOp.add(WriteOp.ForceCreate(rcPort));
}
boolean failed = RCObject.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);
RCPort rcPort = new RCPort(port.getDpid(), port.getNumber());
rcPort.setStatus(RCPort.STATUS.ACTIVE);
rcPort.forceCreate();
// TODO add description into RCPort
//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);
RCPort rcPort = new RCPort(port.getDpid(), port.getNumber());
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);
RCLink rcLink = new RCLink(link.getSrc().getDpid(),
link.getSrc().getNumber(),
link.getDst().getDpid(),
link.getDst().getNumber());
// 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(RCLink.STATUS.ACTIVE);
rcLink.forceCreate();
return true; // Success
}
public boolean removeLink(LinkEvent linkEvent) {
log.debug("Removing link {}", linkEvent);
RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
rcLink.forceDelete();
return true;
}
/**
* Add a device to the database.
*
* @param device the device to add.
* @return true on success, otherwise false.
*/
public boolean addDevice(DeviceEvent device) {
// TODO implement
return false; // Failure: not implemented yet
}
/**
* Remove a device from the database.
*
* @param device the device to remove.
* @return true on success, otherwise false.
*/
public boolean removeDevice(DeviceEvent device) {
// TODO implement
return false; // Failure: not implemented yet
}
}