RYU多控制器小结

来源:互联网 发布:mac的airdrop在哪里 编辑:程序博客网 时间:2024/04/26 06:18

  • 一多控制器需要同步的信息
  • 二主从控制器工作
    • 1主控制器模式数据同步
    • 2主控制器模式功能执行
    • 3从控制器信息同步
    • 4主从控制器切换从控制器切换至主控制器
  • 三各普通模块主要代码说明
  • 四以后普通模块添加同步数据的方法
  • 五多控制器与单控制器模式的切换

一、多控制器需要同步的信息

  • 路由信息配置
    • 单播路由算法类型
    • 单播路由算法参数
    • 多播路由算法参数
  • ARP缓存表信息
  • 主机发现信息
  • 用于失效恢复的路由信息维护

二、主从控制器工作

由多控制器模块与zookeeper通信,获知当前控制器在zookeeper的角色(master or slave)。
本方案采用逻辑主从,即对于交换机而言每个控制器的角色都是EQUAL,但控制器依据自身的角色进行工作。

1、主控制器模式–数据同步

当zookeeper判断当前控制器为master时,多控制器模块向其他模块发送事件,通知其余模块当前控制器的角色。当packet_in模块得知当前为master时,开始处理交换机发送的packet_in消息;
路由管理模块、代理ARP模块以及主机管理模块发送EventCreateZnode事件至多控制器模块,由多控制器模块执行

  @set_ev_cls(multictrler_event.EventLocked)    def locked_handle(self, ev):        self.logger.info("this controllers is:%s", ev.role)        if ev.role is 'master':            self.send_event_to_observers(multictrler_event.EventCreateZnode("arp_table", ""))            self.send_event_to_observers(multictrler_event.EventWatchZnode("arp_table"))        elif ev.role is 'slave':            self.send_event_to_observers(multictrler_event.EventWatchZnode("arp_table"))

多控制器模块监听到EventCreateZnode、EventWatchZnode事件,并创建新节点,监听节点数据是否更新。

   @set_ev_cls(multictrler_event.EventWatchZnode, MAIN_DISPATCHER)    def handle_watch_znode(self, ev):        flag = ev.flag        watch_file = PATH + FILE_PATH + flag + ".json"        fp = open(watch_file, 'w')        fp.close()        path = DATA_PATH + "/" + flag        watch = Watcher(self, path, self.handle, self.role)        # greenle = gevent.spawn(watch._watcher)        # greenle.join()        hub.spawn(watch._watcher)

本方案使用zookeeper的get方法,总节点取数据赖判断节点的数据是否更新。

   def _watcher(self):    """    While the node that will watch do not exist, the function will create zhe node.    """    try:        node = zookeeper.get(self.handle, self.path, self._watcher_cb)    except zookeeper.NoNodeException:        self.handler.create_znode(self.path, '', [ZOO_OPEN_ACL_UNSAFE], 0)        node = zookeeper.get(self.handle, self.path, self._watcher_cb)    if node[0] != '':        flag = self.path[6:]        data = eval(node[0])        self.dataupdate(flag, data)

若zk节点的数据有更新,则多控制器模块将zk节点的数据同步至本地文件中。

 def dataupdate(self, flag, data):    """    If data in zookeeper node has changed, controller whether    master or slave will synchronize these data to local file.    :param flag: arp_table, host_info ect.    :param data: the data in zookeeper node    :return:    """    data_file = PATH + FILE_PATH + flag + ".json"    fp = open(data_file, 'w')    fp.truncate()    fp.close()    data = json.dumps(data)    self.logger.debug("Data Synchronization: Flag:%s  Data:%s" % (flag, data))    fp = open(data_file, 'w')    fp.write(data)    fp.close()    if self.role == MASTER:        return    self.handler.send_out_event(multictrler_event.EventDataRecord(flag))

数据同步的重点是要找到普通模块所需同步数据的入口,即需同步的变量发生改变时,通知多控制器模块更新。
本方案中以ARP缓存表为例,在代理arp模块处理完arp报文后,将学习到的arp信息写入proxyarp类的arptable变量之后,发起EventSetZnode事件,将更新之后的arptable信息交由多控制器模块写入zk的节点。

def add_to_arptable(self, msg):    """a interface to add new arp entry to ARPTable."""    arp_src_ip, eth_src = msg    hub.spawn(self.arp_table.update_entry, arp_src_ip, eth_src)    self.send_event_to_observers(multictrler_event.EventSetZnode(self.arp_table.to_json(), 'arp_table'))

2、主控制器模式–功能执行

若多控制器为master,则各模块按照正常的流程进行系统初始化以及交换机初始化。

3、从控制器–信息同步

 若多控制器发出slave信息,此控制器为从控制器,从控制器将不处理packet_in等信息,只处理路由发现等控制器与交换机之间非业务的事件。 处于多控制器统一性考虑,从控制器也将不处理web发送的除GET以外的请求,所以在REST API函数上添加装饰器,多web的请求进行筛选。

装饰器函数如下:

class RoleCheck(object):    def __init__(self):        super(RoleCheck, self).__init__()    def app_role(self, func):        def wrapper(*args, **kwargs):            func_self = args[0]            req = args[1]            if req.method != 'GET':                if isinstance(func_self, OpenRainbowControllerBase):                    if func_self.inst.controller_role is not 'master':                        return Response(content_type='application/json',                                        body=ec2json(RAEC.MULTI_CONTROLLER_SLAVE),                                        status='404 Not found')            rval = func(*args, **kwargs)            return rval        return wrapperrole_check = RoleCheck()

4、主从控制器切换–从控制器切换至主控制器

 多控制器模块轮询查看当前控制器的角色是否改变,若已经从slave切换至master,则需及时同步信息,并接受网络中交换机发送的packet_in。

由于同步信息已同步至本地文件中,所以此时只需要从文件中读取信息即可。为确保模块功能明显,本方案中,将读取文件的工作交给多控制器模块。由各个需要同步的模块发出同步请求,多控制器读取文件,将文件信息发送给各普通模块,各模块依据信息格式将信息写入各普通模块的变量中。

三、各普通模块主要代码说明

     为实现多控制器,各普通模块不需要做出太多的改变,只需依据当前控制器的角色进行简单的操作即可。 主要包含两部分,一是当收到EventLocked事件时声明本模块需要同步的变量并告知多控制器模块,由多控制器模块去创建或监听zookeeper节点;                             二是当接受EventRoleChanged事件时,将本地文件写入内存。注: 由于更新本地文件时,多控制器模块会发送EventDataRecord事件,基于此可以实现实时同步数据到内存。但本方案未采用此方法。
@set_ev_cls(multictrler_event.EventLocked)def locked_handle(self, ev):    self.logger.info("this controllers is:%s", ev.role)    if ev.role is 'master':        self.send_event_to_observers(multictrler_event.EventCreateZnode("arp_table", ""))        self.send_event_to_observers(multictrler_event.EventWatchZnode("arp_table"))    elif ev.role is 'slave':        self.send_event_to_observers(multictrler_event.EventWatchZnode("arp_table"))@set_ev_cls(multictrler_event.EventRoleChanged)def role_change_handle(self, ev):    arp_table = multiple_controller_api.handle_synchronize_request(self, 'arp_table')    if len(arp_table) is 0:        return    arp_table = eval(arp_table)    for arp_info in arp_table:        ip = arp_info['ip']        arp_entry = arp_info['arp_entry']        self.arp_table.update_entry_with_entry(ip, arp_entry)    self.logger.info("SYN arp table info success!")

四、以后普通模块添加同步数据的方法

 1、在模块的_Event中声明EventCreateZnode、EventWatchZnode以及EventSetZnode事件; 2、添加EventRoleLocked事件处理函数:(代码如上); 3、添加EventRoleChanged事件处理函数并在函数中添加解析方法以及写入内存的代码。

五、多控制器与单控制器模式的切换

  多控制器是为保持网络的可靠性而诞生,但若不需要多控制器模式,或者当前服务器未安装zookeeper环境,则需当前控制器运行与单一控制器模式下。本方案使用配置文件参数设置赖判断单控制器还是多控制器模式。配置文件字段【MULTIPLE_CONTROLLERS】multiple_controllers_module

为False时,多控制器模块判断单为单控制器模式,否则为多控制器模式。
1、单控制器模式;
此时并不与zk进行通信,直接判断此控制器的角色为master,并且普通模块以master的角色进行工作。此模式下多控制器模块不发送EventRoleLocked事件,因此普通模块也将不会发起同步信息。
2、多控制器模式;略
3、配置文件cfg;
cfg为控制流图,支持多个模块使用同一配置文件。RYU中cfg的用法,在此记录一下:

from ryu import cfgCONF = cfg.CONFmultiple_controllers_cfg_group = cfg.OptGroup(    name='MULTIPLE_CONTROLLERS',    title='multiple controllers options')CONF.register_group(multiple_controllers_cfg_group)CONF.register_opts([    cfg.IntOpt('controller-id', default=1,  # seconds, should be larger than 1 second               help='the number of multiple controller'                    'should be larger than 1 second.'),    cfg.IntOpt('connection-timeout', default=10,  # seconds, should be larger than 1 second               help='the timeout of connection between zk_client and zk_server'                    'should be larger than 1 second.'),    cfg.IntOpt('check-controller-role', default=1,               help='the time of find the role of controller'),    cfg.BoolOpt('multiple-controllers-module', default=True,                help='controller working in multiple controllers or not.'),], multiple_controllers_cfg_group)
1 0
原创粉丝点击