xm migrate源碼分析

來源:互聯網
上載者:User
xm migrate源碼分析
xen動態遷移虛機的命令為:xm migrate --live <domain id> <destination machine>
遷移的原理

Xen live migration begins by sending a request, or reservation, to the target specifying the resources the migrating domain will need. If the target accepts the request, the source begins the iterative precopy phase of migration. During this step, Xen copies pages of memory over a TCP connection to the destination host. While this is happening, pages that change are marked as dirty and then recopied. The machine iterates this until only very frequently changed pages remain, at which point it begins the stop and copy phase. Now Xen stops the VM and copies over any pages that change too frequently to efficiently copy during the previous phase. In practice, our testing suggests that Xen usually reaches this point after four to eight iterations. Finally the VM starts executing on the new machine.

By default, Xen will iterate up to 29 times and stop if the number of dirty pages falls below a certain threshold. You can specify this threshold and the number of iterations at compile time, but the defaults should work fine.


xen動態遷移分為save和restore兩部分,先看save部分。tools/python/xen/xm/migrate.py

該函數主要是對輸入的命令作參數解析,然後跳轉到 server.xend.domain.migrate(dom, dst, opts.vals.live,
                                   opts.vals.port,
                                   opts.vals.node,
                                   opts.vals.ssl) -->XendDomain.domain_migrate()tools/python/xen/xend/XendDomain.pydomain_migrate(self, domid, dst, live=False, port=0, node=-1, ssl=None):1. Make sure vm existing and being running  dominfo = self.domain_lookup_nr(domid) # get a structure of XendDomainInfo
  if not dominfo:
      raise XendInvalidDomain(str(domid))
  if dominfo.getDomid() == DOM0_ID:
      raise XendError("Cannot migrate privileged domain %s" % domid)
  if dominfo._stateGet() != DOM_STATE_RUNNING:
      raise VMBadState("Domain is not running",
          POWER_STATE_NAMES[DOM_STATE_RUNNING],POWER_STATE_NAMES[dominfo._stateGet()])2. Notify all device about intention of migration     dominfo.testMigrateDevices(True, dst)   ---> XendDomainInfo.migrateDevice(n, c, network, dst, DEV_MIGRATE_TEST, self.getName())   ---> XendDomainInfo.getDeviceController(deviceClass).migrate(deviceConfig,

                                        network, dst, step, domName)

  ---> DevController.migrate()       由於xoptions.get_external_migration_tool()返回為空白,實際上什麼也不做,直接返回0       This function is called for 4 steps:         If step == 0: Check whether the device is ready to be migrated
                      or can at all be migrated; return a '-1' if
                      the device is NOT ready, a '0' otherwise. If it is
                      not ready ( = not possible to migrate this device),
                      migration will not take place.
           step == 1: Called immediately after step 0; migration
                      of the kernel has started;
           step == 2: Called after the suspend has been issued
                      to the domain and the domain is not scheduled anymore.
                      Synchronize with what was started in step 1, if necessary.
                      Now the device should initiate its transfer to the
                      given target. Since there might be more than just
                      one device initiating a migration, this step should
                      put the process performing the transfer into the
                      background and return immediately to achieve as much
                      concurrency as possible.
           step == 3: Synchronize with the migration of the device that
                      was initiated in step 2.
                      Make sure that the migration has finished and only
                      then return from the call.     這兒DEV_MIGRATE_TEST=0,即步驟03. For live migration, make sure there's memory free for enabling shadow mode   dominfo.checkLiveMigrateMemory()   --->XendDomainInfo.checkLiveMigrateMemory()       遷移需要的記憶體為:1MB per vcpu plus 4Kib/Mib of RAM       這些記憶體通過balloon.free(overhead_kb, self)獲得4. 如果使用--ssl選項,則建立SSL串連;否則,建立普通tcp串連5. 開始遷移   XendCheckpoint.save(sock.fileno(), dominfo, True, live, dst, node=node)   --->XendCheckpoint.save()tools/python/xen/xend/XendCheckPoint.py def save(fd, dominfo, network, live, dst, checkpoint=False, node=-1)    1. 首先發送SIGNATURE,即LinuxGuestRecord  2. 為了避免將虛機遷移到本機時虛機重名,將原虛機暫時重新命名為migrating-domain_name  3. 發送設定檔  4. 真正遷移是在 forkHelper(cmd, fd, saveInputHandler, False)中做的,即建立一個子進程來執行xc_save,而主進程繼續執行後面的步驟:     其中,cmd為 /usr/lib64/xen/bin/xc_save fd domid 0 0 str(int(live)|(int(hvm)<<2))     (xc_save的參數格式為 /usr/lib64/xen/bin/xc_save iofd domid maxit maxf flags)      def saveInputHandler(line, tochild):
            log.debug("In saveInputHandler %s", line)
            if line == "suspend":
                log.debug("Suspending %d ...", dominfo.getDomid())
                dominfo.shutdown('suspend')
                dominfo.waitForSuspend()
            if line in ('suspend', 'suspended'):
                dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP2,
                                       domain_name)
                log.info("Domain %d suspended.", dominfo.getDomid())
                dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
                                       domain_name)
                if hvm:
                    dominfo.image.saveDeviceModel()

            if line == "suspend":
                tochild.write("done\n")
                tochild.flush()
                log.debug('Written done')  5. 發送qemu裝置的狀態(即/var/lib/xen/qemu-save.7)  6. 由於傳入的checkpoint參數為True,將suspended的虛機resume  7. 最後,將重新命名的虛機改為原來的名字下面是restore部分tools/xen/xend/server/SrvDaemon.py

xend在啟動的時候會開啟8002連接埠的監聽:
Daemon()-->run()-->relocate.listenRelocation()-->tcp.TCPListener(RelocationProtocol, port, interface = interface, hosts_allow = hosts_allow)
相應的參數在xend設定檔中設定:(xend-relocation-server yes)(xend-relocation-port 8002)(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$')建立串連後的處理由RelocationProtocol完成,其中最重要的函數為op_receive:     def op_receive(self, name, _):
        if self.transport:
            self.send_reply(["ready", name])
            try:
                 XendDomain.instance().domain_restore_fd(
                    self.transport.sock.fileno(), relocating=True)

            except:
                self.send_error()
                self.close()
        else:
            log.error(name + ": no transport")
            raise XendError(name + ": no transport") 而XendDomain.domain_restore_fd()是通過 XendCheckpoint.restore(self, fd, paused=paused, relocating=relocating)來完成的。tools/python/xen/xend/XendCheckPoint.py def restore(xd, fd, dominfo = None, paused = False, relocating = False):    1. 首先接收並驗證SIGNATURE  2. 接收設定檔  3. 確保本機上沒有與要遷移的虛機同名或同UUID的虛機  4. 根據接收的設定檔建立XendDomainInfo結構:          dominfo = xd.restore_(vmconfig)-->XendDomainInfo.restore(config)  5. 如果原虛機設定了node_to_cpu,則綁定vcpu到相應的pcpu  6. 建立image並分配記憶體(shadow_memory + memory_dynamic_max)     restore_image = image.create(dominfo, dominfo.info)     balloon.free(memory + shadow, dominfo)  7. 真正遷移是在forkHelper(cmd, fd, handler.handler, True)中做的,即建立一個子進程來執行xc_restore,而主進程繼續執行後面的步驟:
     其中,cmd為:     cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),

                        fd, dominfo.getDomid(),
                        store_port, console_port, int(is_hvm), pae, apic])
     (xc_save的參數格式為/usr/lib64/xen/bin/xc_restore iofd domid store_evtchn console_evtchn hvm pae apic
      def handler(self, line, _):

        m = re.match(r"^(store-mfn) (\d+)$", line)
        if m:
            self.store_mfn = int(m.group(2))
        else:
            m = re.match(r"^(console-mfn) (\d+)$", line)
            if m:
                self.console_mfn = int(m.group(2))
  5. 接收qemu裝置的狀態 (即/var/lib/xen/qemu-save.7)  6. 設定虛機cpuid,並建立虛機:
        restore_image.setCpuid()
        os.read(fd, 1)           # Wait for source to close connection
        dominfo.completeRestore(handler.store_mfn, handler.console_mfn):

        self._introduceDomain()        self.image = image.create(self, self.info)        if self.image:            self.image.createDeviceModel(True)        self._storeDomDetails()        self._registerWatches()        self.refreshShutdown()

  7. 最後,啟動虛機:
     dominfo.waitForDevices()     dominfo.unpause()
xc_save和xc_restore的源碼 暫時還沒有仔細看。
參考:http://wiki.prgmr.com/mediawiki/index.php/Chapter_9:_Xen_Migration

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.