neutron代碼解析之l3-agent的啟動

前言

每個 L3 Agent 運行在一個 network namespace 中哈肖,以 qrouter-<router-UUID>命名躬拢。網(wǎng)絡(luò)節(jié)點如果不支持 Linux namespace 的躲履,只能運行一個 Virtual Router。通過配置項use_namespaces = True開啟namespace估灿。本文只做單純的分析代碼崇呵,研究了neutron的l3-agent代碼(m版本),代碼路徑為/neutron/agent/l3/agent.py馅袁。主要的類是:

  • class L3PluginApi(object): l3-agent的rpc接口域慷,用于回復(fù)和查詢l3-plugin的。
  • class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,ha.AgentMixin,dvr.AgentMixin,manager.Manager): l3-agent實現(xiàn)類。

主要來說說L3NATAgent犹褒。該類在運行的時候抵窒,會啟動兩個周期任務(wù):

  • periodic_sync_routers_task:周期性獲取router列表,并將需要操作的router加入到隊列中叠骑;
  • _process_routers_loop:從上個任務(wù)中獲取隊列中的router李皇,并進行處理(增刪和更新)。
    接下來依次分析這兩個任務(wù)宙枷。

periodic_sync_routers_task

注意該類繼承了FWaaSL3AgentRpcCallback和Manager兩個類掉房。Manager類里有個方法periodic_tasks,運行的是父類的方法run_periodic_tasks

class Manager(periodic_task.PeriodicTasks):
       
    # Set RPC API version to 1.0 by default.
    target = oslo_messaging.Target(version='1.0')
          
    def periodic_tasks(self, context, raise_on_error=False):
        self.run_periodic_tasks(context, raise_on_error=raise_on_error)

在neutron/service.py里的類Service慰丛,啟動start的時候卓囚,會加載Manager的periodic_tasks方法,并設(shè)置周期時間:

class Service(n_rpc.Service):
       
    def start(self):
        self.manager.init_host()
        super(Service, self).start()
        if self.report_interval:
            pulse = loopingcall.FixedIntervalLoopingCall(self.report_state)
            pulse.start(interval=self.report_interval,initial_delay=self.report_interval)
            self.timers.append(pulse)
           
        if self.periodic_interval:
            if self.periodic_fuzzy_delay:
                initial_delay = random.randint(0, self.periodic_fuzzy_delay)
            else:
                initial_delay = None
          
            periodic = loopingcall.FixedIntervalLoopingCall(self.periodic_tasks)
            periodic.start(interval=self.periodic_interval,initial_delay=initial_delay)
            self.timers.append(periodic)
        self.manager.after_start()
            
    def periodic_tasks(self, raise_on_error=False):
        """Tasks to be run at a periodic interval."""
        ctxt = context.get_admin_context()
        self.manager.periodic_tasks(ctxt, raise_on_error=raise_on_error)

然后說回L3NATAgent類诅病,它定義了一個方法periodic_sync_routers_task哪亿,被@periodic_task.periodic_task(spacing=1, run_immediately=True)進行了裝飾,可以理解為間隔時間為1秒運行一次任務(wù)贤笆。periodic_task是oslo_service/periodic_task.py里的裝飾器方法蝇棉,用于將被裝飾的方法聲明為一個周期性任務(wù);而該文件里還有一個方法也就是上文提到的run_periodic_tasks芥永,用于運行所有的周期任務(wù):

    # NOTE(kevinbenton): this is set to 1 second because the actual interval
    # is controlled by a FixedIntervalLoopingCall in neutron/service.py that
    # is responsible for task execution.
    @periodic_task.periodic_task(spacing=1, run_immediately=True)
    def periodic_sync_routers_task(self, context):
    ...

        try:
            with self.namespaces_manager as ns_manager:
                self.fetch_and_sync_all_routers(context, ns_manager)

periodic_sync_routers_task執(zhí)行了一個任務(wù)fetch_and_sync_all_routers篡殷,即是通過l3-plugin RPC獲取到router列表,然后將需要進行操作的router加入到 _queue 中恤左。理解了這個贴唇,就能明白接下來的一個線程循環(huán)任務(wù) _process_routers_loop。

_process_routers_loop

在l3-agent開始啟動過程after_start中飞袋,還會啟動一個線程來循環(huán)執(zhí)行一個任務(wù)_process_routers_loop

    def after_start(self):
        # Note: the FWaaS' vArmourL3NATAgent is a subclass of L3NATAgent. It
        # calls this method here. So Removing this after_start() would break
        # vArmourL3NATAgent. We need to find out whether vArmourL3NATAgent
        # can have L3NATAgentWithStateReport as its base class instead of
        # L3NATAgent.
        eventlet.spawn_n(self._process_routers_loop)
        LOG.info(_LI("L3 agent started"))
    def _process_routers_loop(self):
        LOG.debug("Starting _process_routers_loop")
        pool = eventlet.GreenPool(size=8)
        while True:
            pool.spawn_n(self._process_router_update)

再來看看方法_process_router_update戳气,方法一開始就會通過_queue.each_update_to_next_router從上一個任務(wù)的隊列里獲取需要進行操作的router信息。然后會針對不通的action巧鸭,進行一些處理瓶您,真正進行router操作的是_process_router_if_compatible:

    def _process_router_update(self):
        for rp, update in self._queue.each_update_to_next_router():
            LOG.debug("Starting router update for %s, action %s, priority %s",
                      update.id, update.action, update.priority)
            if update.action == queue.PD_UPDATE:
                self.pd.process_prefix_update()
                LOG.debug("Finished a router update for %s", update.id)
                continue
            router = update.router
            ......
            try:
                self._process_router_if_compatible(router)
            ......
      
            LOG.debug("Finished a router update for %s", update.id)
            rp.fetched_and_processed(update.timestamp)

_process_router_if_compatible方法的主要實現(xiàn),在最后:

    def _process_router_if_compatible(self, router):
        ......
        if router['id'] not in self.router_info:
            self._process_added_router(router)
        else:
            self._process_updated_router(router)

_process_updated_router為例:

    def _process_updated_router(self, router):
        ri = self.router_info[router['id']]
        ri.router = router
        registry.notify(resources.ROUTER, events.BEFORE_UPDATE,self, router=ri)
        ri.process(self)
        registry.notify(resources.ROUTER, events.AFTER_UPDATE, self, router=ri)

針對router的所有操作都在neutron/agent/l3/router_info.py中的方法process里纲仍。具體細節(jié)在這里就不做分析了呀袱,包括對external-port,internal-port和floating ip的一系列處理郑叠。

個人分析夜赵,歡迎指正,若轉(zhuǎn)載請注明出處
歡迎訪問我的主頁

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乡革,一起剝皮案震驚了整個濱河市寇僧,隨后出現(xiàn)的幾起案子摊腋,更是在濱河造成了極大的恐慌,老刑警劉巖嘁傀,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兴蒸,死亡現(xiàn)場離奇詭異,居然都是意外死亡细办,警方通過查閱死者的電腦和手機橙凳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笑撞,“玉大人岛啸,你說我怎么就攤上這事≤罘剩” “怎么了值戳?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長炉爆。 經(jīng)常有香客問我,道長卧晓,這世上最難降的妖魔是什么芬首? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮逼裆,結(jié)果婚禮上郁稍,老公的妹妹穿的比我還像新娘。我一直安慰自己胜宇,他們只是感情好耀怜,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桐愉,像睡著了一般财破。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上从诲,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天左痢,我揣著相機與錄音,去河邊找鬼系洛。 笑死俊性,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的描扯。 我是一名探鬼主播定页,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绽诚!你這毒婦竟也來了典徊?” 一聲冷哼從身側(cè)響起杭煎,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宫峦,沒想到半個月后岔帽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡导绷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年犀勒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妥曲。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡贾费,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出檐盟,到底是詐尸還是另有隱情褂萧,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布葵萎,位于F島的核電站导犹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏羡忘。R本人自食惡果不足惜谎痢,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卷雕。 院中可真熱鬧节猿,春花似錦、人聲如沸漫雕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浸间。三九已至太雨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魁蒜,已是汗流浹背躺彬。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留梅惯,地道東北人宪拥。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像铣减,于是被迫代替她去往敵國和親她君。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容