1. 程式人生 > >OpenStack中nova元件建立虛擬機器的原始碼流程

OpenStack中nova元件建立虛擬機器的原始碼流程

此處以OpenStack mitaka版本為例,實際最新的Ocata版本也差不多,以建立一個虛擬機器為例來分析nova原始碼中執行流程,該流程有助於二次開發,閱讀原始碼前最好先熟悉一下pastedeploy、webob、stevedore等openstack中的核心庫,以及rpc訊息通訊機制。
安裝完OpenStack後,所有的原始碼在/usr/lib//usr/lib/python2.7/site-packages/目錄下,nova伺服器端原始碼在nova目錄中,客戶端原始碼在novaclient目錄中,動態載入nova外掛的對映檔案在nova-XXXX-info目錄中的entry_points.txt檔案中。
客戶端:
novaclient在初始化的過程會把/nova/v2/下所有的xxxxManager類載入進來,並通過_construct_http_client()構造一個HTTPClient物件,用來發送url請求,每個xxxxManger類都直接或間接繼承了base.ManagerWithFind類,xxxxManager類中的方法主要用來構造url格式、請求引數、請求方法。客戶端建立虛擬機器的請求對應在/novaclient/v2/servers.py中的_boot()方法,該方法呼叫了基類Manager中的_create()方法。
伺服器端:
nova在接收到客戶端的請求後,會通過pastedeploy載入/etc/nova/api-paste.ini配置檔案來完成url的對映、認證、請求等,配置檔案中包含了四類部件app(應用程式)、filter(過濾器)、pipeline(管道)、composite(複合體)。

[composite:openstack_compute_api_v21]
use = call:nova.api.auth:pipeline_factory_v21
noauth2 = cors compute_req_id faultwrap sizelimit noauth2 osapi_compute_app_v21
/v2: openstack_compute_api_v21_legacy_v2_compatible
/v2.1: openstack_compute_api_v21

根據客戶端請求的版本,此處是v2.1,繼續進入openstack_compute_api_v21這個管道體。

[composite:openstack_compute_api_v21]
use = call:nova.api.auth:pipeline_factory_v21
noauth2 = cors compute_req_id faultwrap sizelimit noauth2 osapi_compute_app_v21
keystone = cors compute_req_id faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v21

首先,通過pipeline_factory_v21()方法選擇認證策略,預設配置檔案/etc/nova/nova.conf中的認證策略auth_strategy為keystone。然後,會進入keystone管道體,前面一系列cors compute_req_id faultwrap sizelimit authtoken keystonecontext為過濾器,auth_token是OpenStack中各個元件互動時來完成安全認證的,其呼叫的核心方法為/keystonemiddleware/auth_token中的_do_fetch_token(),osapi_compute_app_v21為具體的應用,nova主要的功能都在該應用中實現。

[app:osapi_compute_app_v21]
paste.app_factory=nova.api.openstack.compute:APIRouterV21.factory

該應用程式呼叫了APIRouterV21類對應的工廠方法factory(),該方法在其父類/nova/api/openstack/APIRouterV21中實現,其建立了一個APIRouterV21()例項,其初始化方法通過如下程式碼完成外掛的動態載入。

self.api_extension_manager = stevedore.enabled.EnabledExtensionManager(
            namespace=self.api_extension_namespace(),
            check_func=_check_load_extension,
            invoke_on_load=True,
            invoke_kwds={"extension_info": self.loaded_extension_info})

其中,通過mapper = ProjectMapper()完成所有外掛的url對映,_register_controllers()方法將所有外掛對應XXXXController類中的方法進行註冊,指定mapper所對應的具體action動作。以建立虛擬機器為例,其將會呼叫/nova/api/openstack/compute/servers.py中的create()方法,該方法呼叫了/nova/compute/api.py中的create()方法,該方法中會檢測使用者許可權,並呼叫了_create_instance()方法,該方法中完成虛擬機器建立的準備工作。其後,呼叫了/nova/conductor/api.py中的build_instances()方法,該方法通過/nova/conductor/rpcapi.py中的build_instances()方法傳送建立虛擬機器的rpc訊息。

cctxt.cast(context, 'build_instances', **kw)

隨後,會執行manager.py中的build_instances()方法,該方法會通過_schedule_instances()方法完成虛擬機器的排程,其中也涉及到rpc訊息通訊,呼叫的核心方法在filter_scheduler.py中的select_destinations(),此處不展開說明了,build_instances()呼叫了/nova/compute/rpcapi.py中的build_and_instance()方法傳送rpc訊息,請求建立虛擬機器。

cctxt.cast(ctxt, 'build_and_run_instance', instance=instance,
                image=image, request_spec=request_spec,
                filter_properties=filter_properties,
                admin_password=admin_password,
                injected_files=injected_files,
                requested_networks=requested_networks,
                security_groups=security_groups,
                block_device_mapping=block_device_mapping, node=node,
                limits=limits)

最終,/nova/compute/manager.py中的build_and_run_instance()方法會完成虛擬機器的建立,其呼叫的核心方法為driver.spawn(),具體的driver由/etc/nova/nova.conf中的compute_driver指定。