这两天简单看了一下Floodlight的模块机制,大概了解了其插件的机制和流 程,编写了一个非常简单的模块,为大家分享一下
Floodlight加载和运行模块的原理
Floodlight的入口是net.floodlightcontroller.core.Main, 在这个类的main函数中,使用FloodlightModuleLoader加载所有的模块,然后再 调用net.floodlightcontroller.restserver.RestApiServer模块的run方法,启动 rest服务器,最后调用net.floodlightcontroller.core.internal.Controller模块的 run方法,启动网络控制器。
public static void main(String[] args) throws FloodlightModuleException {
...
FloodlightModuleLoader fml = new FloodlightModuleLoader();
IFloodlightModuleContext moduleContext = fml.loadModulesFromConfig(settings.getModuleFile());
IRestApiService restApi = moduleContext.getServiceImpl(IRestApiService.class);
restApi.run();
IFloodlightProviderService controller =
moduleContext.getServiceImpl(IFloodlightProviderService.class);
controller.run();
}
在加载模块的过程中,使用 FloodlightModuleLoader类的findAllModules方法寻找所有在$CLASSPATH路径中的
实现了 net.floodlightcontroller.core.module.IFloodlightModule接口的模块,然后用initModules 初始化这些模块,最后用
startupModules启动这些模块。
FloodlightModuleLoad.java:303
initModules(moduleSet);
startupModules(moduleSet);
以MemoryStorageSource类为例,它继承了 NoSqlStorageSource类,后者又继承了AbstractStorageSource类,而 AbstractStorageSource是实现了IFloodlightModule和 IStorageSourceService两个接口。
IFloodlightModule有一个init方法和一个startUp方法,所以MemoryStorageSource会分别实现这两个方法,并
在初始化和启动的时候被调用。
一个模块的简单实例
下面简单介绍如何新建一个模块的过程,以一个IDSController为例,现在 只实现定时打印日志的功能:
1 定义服务com.nsfocus.ids.IIntrusionDetectionService:
public interface IIntrusionDetectionService extends IFloodlightService {
}
2 新建一个实现IFloodlightModule接口的类com.nsfocus.ids.IDSController:
分别实现接口IFloodlightModule的 getModuleServices、getServiceImpls、getModuleDependencies等方法,这三个方法 主要用于初始化模块
系统运行 ServiceLoader.load(IFloodlightModule.class, cl)后会将IDSController加载到支持IFloodlightModule模块的列表中。
3 在配置文件中添加新模块:
在target\bin\floodlightdefault.properties添加:
net.floodlightcontroller.perfmon.PktInProcessingTime,\
net.floodlightcontroller.ui.web.StaticWebRoutable,\
com.nsfocus.ids.IDSController
net.floodlightcontroller.restserver.RestApiServer.port = 8080
这样新模块在加载时就被添加到集合configMods中
此外,要在bin\META-INF\services\net.floodlightcontroller.core.module.ISecurityControllerModule中添加一行
com.nsfocus.ids.IDSController
代码在运行到FloodlightModuleLoader.findAllModules的ServiceLoader.load方法时,会加载第二个文件中所列的所有模块,如果只在第一个文件中列出来,而没有在第二个文件中模块列出来的话,会抛出SecurityControllerModuleException的异常。所以一定要在两个文件中都添加该模块。
4 在IDSController中添加相应的功能
4.1 添加初始化代码
@Override
public void init(FloodlightModuleContext context) throws FloodlightModuleException {
threadPool = context.getServiceImpl(IThreadPoolService.class);
Map<String, String> configOptions = context.getConfigParams(this);
try {
String detectTimeout = configOptions.get("detecttimeout");
if (detectTimeout != null) {
DETECT_TASK_INTERVAL = Short.parseShort(detectTimeout);
}
} catch (NumberFormatException e) {
log.warn("Error parsing detecting timeout, " +
"using default of {} seconds",
DETECT_TASK_INTERVAL);
}
log.debug("NSFOCUS IDS controller initialized");
}
4.2 添加启动代码
@Override
public void startUp(FloodlightModuleContext context) {
log.debug("NSFOCUS IDS controller started");
ScheduledExecutorService ses = threadPool.getScheduledExecutor();
detectTask = new SingletonTask(ses, new Runnable() {
@Override
public void run() {
try {
detect();
detectTask.reschedule(DETECT_TASK_INTERVAL, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("Exception in IDS detector", e);
} finally {
}
}
});
detectTask.reschedule(DETECT_TASK_INTERVAL, TimeUnit.SECONDS);
}
public void detect(){
log.debug("Detecting...");
}
这样,floodlight在初始化时自动调用IDSController的 init方法,随后在启动时会自动调用IDSController的startUp方法,上面代码使用了定时器,实现定时触发的功能。
下面是部分
启动日志:
16:02:51.242 [main] DEBUG n.f.core.internal.Controller – OFListeners for PACKET_IN: linkdiscovery,topology,devicemanager,firewall,forwarding,
16:02:51.302 [main] INFO n.f.core.internal.Controller – Listening for switch connections on 0.0.0.0/0.0.0.0:6633
16:02:53.611 [debugserver-main] INFO n.f.jython.JythonServer – Starting DebugServer on port 6655
16:02:55.095 [pool-3-thread-15] DEBUG com.nsfocus.ids.IDSController – Detecting…
16:02:59.096 [pool-3-thread-11] DEBUG com.nsfocus.ids.IDSController – Detecting…
P.S. 其他成员变量声明为:
protected static Logger log = LoggerFactory.getLogger(IDSController.class);
protected SingletonTask detectTask;
protected int DETECT_TASK_INTERVAL = 2;
protected IThreadPoolService threadPool;