blob: d2a9d31c1d3181f8c0b8c2d490fc4950d50e0be3 [file] [log] [blame]
package net.onrc.onos.core.registry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.onrc.onos.core.registry.web.RegistryWebRoutable;
import net.onrc.onos.core.util.IdBlock;
import net.onrc.onos.core.util.OnosInstanceId;
import org.apache.commons.lang3.NotImplementedException;
import org.projectfloodlight.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of a registry that doesn't rely on any external registry
* service. This is designed to be used only in single-node setups (e.g. for
* development). All registry data is stored in local memory.
*/
public class StandaloneRegistry implements IFloodlightModule,
IControllerRegistryService {
private static final Logger log = LoggerFactory.getLogger(StandaloneRegistry.class);
private IRestApiService restApi;
private OnosInstanceId onosInstanceId;
private Map<String, ControlChangeCallback> switchCallbacks;
private long blockTop;
private static final long BLOCK_SIZE = 0x1000000L;
//
// Unique ID generation state
//
private static AtomicLong nextUniqueId = new AtomicLong(0);
@Override
public void requestControl(long dpid, ControlChangeCallback cb)
throws RegistryException {
if (onosInstanceId == null) {
throw new IllegalStateException(
"Must register a controller before calling requestControl");
}
switchCallbacks.put(HexString.toHexString(dpid), cb);
log.debug("Control granted for {}", HexString.toHexString(dpid));
// Immediately grant request for control
if (cb != null) {
cb.controlChanged(dpid, true);
}
}
@Override
public void releaseControl(long dpid) {
ControlChangeCallback cb = switchCallbacks.remove(HexString.toHexString(dpid));
log.debug("Control released for {}", HexString.toHexString(dpid));
if (cb != null) {
cb.controlChanged(dpid, false);
}
}
@Override
public boolean hasControl(long dpid) {
return switchCallbacks.containsKey(HexString.toHexString(dpid));
}
@Override
public boolean isClusterLeader() {
return true;
}
@Override
public OnosInstanceId getOnosInstanceId() {
return onosInstanceId;
}
@Override
public void registerController(String controllerId)
throws RegistryException {
if (onosInstanceId != null) {
throw new RegistryException(
"Controller already registered with id " + onosInstanceId);
}
onosInstanceId = new OnosInstanceId(controllerId);
}
@Override
public Collection<String> getAllControllers() throws RegistryException {
if (onosInstanceId == null) {
return new ArrayList<String>();
}
return Collections.singletonList(onosInstanceId.toString());
}
@Override
public String getControllerForSwitch(long dpid) throws RegistryException {
return (switchCallbacks.get(HexString.toHexString(dpid)) == null)
? null : onosInstanceId.toString();
}
@Override
public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
Map<String, List<ControllerRegistryEntry>> switches =
new HashMap<String, List<ControllerRegistryEntry>>();
for (String strSwitch : switchCallbacks.keySet()) {
log.debug("Switch _{}", strSwitch);
List<ControllerRegistryEntry> list =
new ArrayList<ControllerRegistryEntry>();
list.add(new ControllerRegistryEntry(onosInstanceId.toString(), 0));
switches.put(strSwitch, list);
}
return switches;
}
@Override
public Collection<Long> getSwitchesControlledByController(
String controllerId) {
throw new NotImplementedException("Not yet implemented");
}
/**
* Returns a block of IDs which are unique and unused.
* Range of IDs is fixed size and is assigned incrementally as this method
* called.
*
* @return an IdBlock containing a set of unique IDs
*/
@Override
public IdBlock allocateUniqueIdBlock() {
synchronized (this) {
long blockHead = blockTop;
long blockTail = blockTop + BLOCK_SIZE;
IdBlock block = new IdBlock(blockHead, BLOCK_SIZE);
blockTop = blockTail;
return block;
}
}
/**
* Get a globally unique ID.
*
* @return a globally unique ID.
*/
@Override
public long getNextUniqueId() {
return nextUniqueId.incrementAndGet();
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IControllerRegistryService.class);
return l;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Map<Class<? extends IFloodlightService>, IFloodlightService> m =
new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
m.put(IControllerRegistryService.class, this);
return m;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
l.add(IRestApiService.class);
return l;
}
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
restApi = context.getServiceImpl(IRestApiService.class);
switchCallbacks = new HashMap<String, ControlChangeCallback>();
}
@Override
public void startUp(FloodlightModuleContext context) {
restApi.addRestletRoutable(new RegistryWebRoutable());
}
@Override
public IdBlock allocateUniqueIdBlock(long range) {
throw new UnsupportedOperationException("Not supported yet");
}
}