OpenStack Nova 源碼分析


Nova 源碼分析

參考地址

https://www.processon.com/view/link/5ff434b51e08531de81d1ca0
    
https://jckling.github.io/2021/05/23/OpenStack/OpenStack%20Nova/
    
# 接口文檔    
https://docs.openstack.org/api-ref/compute/?expanded=list-images-detail

https://github.com/int32bit/openstack-workflow

Nova 文件結構

  • nova 目錄
accelerator/    # Cyborg 加速器
api/            # Nova API 服務
	__init__.py
    auth.py             # 身份認證中間件
    compute_req_id.py   # x-compute-request-id 中間件(oslo_middleware)
    metadata/           # Metadata API
    openstack/          # Nova v2.1 API
        __init__.py
        api_version_request.py  # 版本驗證
        auth.py                 # noauth 中間件
        common.py               # 信息查詢的工具函數
        compute/                # 每個 API 的入口點
        	from nova.api.openstack.compute.routes import APIRouterV21
        	routes.py			# 路由文件
        identity.py             # 驗證項目是否存在
        requestlog.py           # 請求日志中間件
        urlmap.py               # url 映射
        versioned_method.py     # 版本信息
        wsgi.py                 # WSGI 相關抽象類
        wsgi_app.py             # WSGI 應用程序初始化方法
    validation/         # 請求體驗證
    wsgi.py             # WSGI 原語(請求、應用、中間件、路由、加載器)
    
cmd/            # 各個 Nova 服務的入口程序
compute/        # Nova Compute 服務
conductor/      # Nova Conductor 服務 *** 處理需要協調的請求(構建/調整)、充當數據庫代理或處理對象轉換。***
conf/           # 所有的配置選項
console/        # nova-console 服務
db/             # 封裝數據庫操作
hacking/        # 編碼規范檢查
image/          # 封裝鏡像操作,Glance 接口抽象
keymgr/         # 密鑰管理器實現
locale/         # 國際化相關文件
network/        # nova-network 服務
notifications/  # 通知相關功能
objects/        # 封裝實體對象的 CURD 操作
pci/            # PCI/SR-IOV 支持
policies/       # 所有 Policy 的默認規則
privsep/        # oslo_privsep 相關
scheduler/      # Nova Scheduler 服務
servicegroup/   # 成員服務(membership),服務組
storage/        # Ceph 存儲支持
tests/          # 單元測試
virt/           # 支持的 hypervisor 驅動
volume/         # 封裝卷訪問接口,Cinder 接口抽象

# 文件
__init__.py
availability_zones.py   # 區域設置的工具函數
baserpc.py              # 基礎 RPC 客戶端/服務端實現
block_device.py         # 塊設備映射
cache_utils.py          # oslo_cache 封裝
config.py               # 解析命令行參數
context.py              # 貫穿 Nova 的所有請求的上下文
crypto.py               # 包裝標准加密數據元素
debugger.py             # pydev 調試
exception.py            # 基礎異常類
exception_wrapper.py    # 封裝異常類
filters.py              # 基礎過濾器
i18n.py                 # 集成 oslo_i18n
loadables.py            # 可加載類
manager.py              # 基礎 Manager 類
middleware.py           # 更新 oslo_middleware 的默認配置選項
monkey_patch.py         # eventlet 猴子補丁
policy.py               # 策略引擎
profiler.py             # 調用 OSProfiler
quota.py                # 每個項目的資源配額
rpc.py                  # RPC 操作相關的工具函數
safe_utils.py           # 不會導致循環導入的工具函數
service.py              # 通用節點基類,用於在主機上運行的所有工作者
service_auth.py         # 身份認證插件
test.py                 # 單元測試基礎類
utils.py                # 工具函數
version.py              # 版本號管理
weights.py              # 權重插件
wsgi.py                 # 管理 WSGI 應用的服務器類

組成部分

  • nova-api

    接受和響應用戶的計算 API 調用

  • nova-api-metadata

    接受來自實例的元數據請求

    Metadata service

  • nova-compute

    通過 hypervisor API 創建和終止虛擬機實例的守護進程。例如 KVM/QEMU 的 libvirt、VMware 的 VMwareAPI 。

    運行在它所管理的 hypervisor 機器上,管理與虛擬機管理程序和虛擬機的通信。

  • nova-scheduler

    從消息隊列中獲取虛擬機實例請求,並決定在哪個服務器上運行。

  • nova-conductor

    處理需要協調的請求(構建/調整)、充當數據庫代理或處理對象轉換。用於連接 nova-api、nova-scheduler、nova-compute 服務。

  • nova-novncproxy

    協調 nova-compute 服務和數據庫之間的交互。避免 nova-compute 直接訪問數據庫,為了提供更好的 API 兼容性。建議不要部署在 nova-compute 服務所在的節點上。

  • nova-spicehtml5proxy

    提供通過 SPICE 連接訪問運行實例的代理,支持基於瀏覽器的 HTML5 客戶端。

  • The queue

    在守護進程之間傳遞消息的中央消息隊列,通常使用 RabbitMQ 。

  • SQL database

    存儲雲基礎設施的大多數構建時和運行時狀態,包括:可用的實例類型、在使用的實例、可用的網絡、項目。

代碼分析

路由函數

  • 文件位置:nova/openstack/compute/router.py
##### 路由列表 ######

# 這是路由列表 配置了接口得路由信息 省略了部分
ROUTE_LIST = (
    # NOTE: This is a redirection from '' to '/'. The request to the '/v2.1'
    # or '/2.0' without the ending '/' will get a response with status code
    # '302' returned.
    ('', '/'),
    ('/', {
        'GET': [version_controller, 'show']
    }),
    ('/versions/{id}', {
        'GET': [version_controller, 'show']
    }),
    ('/images', {
        'GET': [images_controller, 'index']
    }),
    ('/images/detail', {
        'GET': [images_controller, 'detail'],
    }),
    ('/images/{id}', {
        'GET': [images_controller, 'show'],
        'DELETE': [images_controller, 'delete']
    }),
    ('/images/{image_id}/metadata', {
        'GET': [image_metadata_controller, 'index'],
        'POST': [image_metadata_controller, 'create'],
        'PUT': [image_metadata_controller, 'update_all']
    }),
    ('/images/{image_id}/metadata/{id}', {
        'GET': [image_metadata_controller, 'show'],
        'PUT': [image_metadata_controller, 'update'],
        'DELETE': [image_metadata_controller, 'delete']
    }),
    
   	# 查看和創建虛擬機接口  index create 都是 servers.ServersController 類中的綁定方法
    # 后續調用方法時 多半用 射的方法去調用的
    # 人話:get 訪問 http:localhost:port/servers 時,觸發 index servers.ServersController類中的函數
    #      port 訪問 http:localhost:port/servers 時, 觸發 create servers.ServersController類中的函數
    ('/servers', {
        'GET': [server_controller, 'index'],
        'POST': [server_controller, 'create']
    }),
    ('/servers/detail', {
        'GET': [server_controller, 'detail']
    }),
    ('/servers/{id}', {
        'GET': [server_controller, 'show'],
        'PUT': [server_controller, 'update'],
        'DELETE': [server_controller, 'delete']
    }),
    ('/servers/{id}/action', {
        'POST': [server_controller, 'action']
    }),
    ('/servers/{server_id}/consoles', {
        'GET': [consoles_controller, 'index'],
        'POST': [consoles_controller, 'create']
    }),
    ('/servers/{server_id}/consoles/{id}', {
        'GET': [consoles_controller, 'show'],
        'DELETE': [consoles_controller, 'delete']
    }),
    ('/servers/{server_id}/diagnostics', {
        'GET': [server_diagnostics_controller, 'index']
    }),
    ('/servers/{server_id}/ips', {
        'GET': [ips_controller, 'index']
    }),
    ('/servers/{server_id}/ips/{id}', {
        'GET': [ips_controller, 'show']
    }),
    ('/servers/{server_id}/metadata', {
        'GET': [server_metadata_controller, 'index'],
        'POST': [server_metadata_controller, 'create'],
        'PUT': [server_metadata_controller, 'update_all'],
    }),
    ('/servers/{server_id}/metadata/{id}', {
        'GET': [server_metadata_controller, 'show'],
        'PUT': [server_metadata_controller, 'update'],
        'DELETE': [server_metadata_controller, 'delete'],
    }),
    ('/servers/{server_id}/migrations', {
        'GET': [server_migrations_controller, 'index']
    }),
    ('/servers/{server_id}/migrations/{id}', {
        'GET': [server_migrations_controller, 'show'],
        'DELETE': [server_migrations_controller, 'delete']
    }),
    ('/servers/{server_id}/migrations/{id}/action', {
        'POST': [server_migrations_controller, 'action']
    }),
    ('/servers/{server_id}/os-instance-actions', {
        'GET': [instance_actions_controller, 'index']
    }),
    ('/servers/{server_id}/os-instance-actions/{id}', {
        'GET': [instance_actions_controller, 'show']
    }),
    ('/servers/{server_id}/os-interface', {
        'GET': [server_os_interface_controller, 'index'],
        'POST': [server_os_interface_controller, 'create']
    }),
    ('/servers/{server_id}/os-interface/{id}', {
        'GET': [server_os_interface_controller, 'show'],
        'DELETE': [server_os_interface_controller, 'delete']
    }),
    ('/servers/{server_id}/os-server-password', {
        'GET': [server_password_controller, 'index'],
        'DELETE': [server_password_controller, 'clear']
    }),
    ('/servers/{server_id}/os-virtual-interfaces', {
        'GET': [virtual_interfaces_controller, 'index']
    }),
    ('/servers/{server_id}/os-volume_attachments', {
        'GET': [server_volume_attachments_controller, 'index'],
        'POST': [server_volume_attachments_controller, 'create'],
    }),
    ('/servers/{server_id}/os-volume_attachments/{id}', {
        'GET': [server_volume_attachments_controller, 'show'],
        'PUT': [server_volume_attachments_controller, 'update'],
        'DELETE': [server_volume_attachments_controller, 'delete']
    }),
    ('/servers/{server_id}/remote-consoles', {
        'POST': [server_remote_consoles_controller, 'create']
    }),
    ('/servers/{server_id}/os-security-groups', {
        'GET': [server_security_groups_controller, 'index']
    }),
    ('/servers/{server_id}/tags', {
        'GET': [server_tags_controller, 'index'],
        'PUT': [server_tags_controller, 'update_all'],
        'DELETE': [server_tags_controller, 'delete_all'],
    }),
    ('/servers/{server_id}/tags/{id}', {
        'GET': [server_tags_controller, 'show'],
        'PUT': [server_tags_controller, 'update'],
        'DELETE': [server_tags_controller, 'delete']
    }),
    ('/servers/{server_id}/topology', {
        'GET': [server_topology_controller, 'index']
    }),
)
# 路由中的函數

#### 路由中的函數調用此函數 
def _create_controller(main_controller, action_controller_list):
    # 相當於將 servers.ServersController 類初始化傳入 wsgi.Resource() 類中   
    controller = wsgi.Resource(main_controller())
    for ctl in action_controller_list:
    # 遍歷[ admin_actions.AdminActionsController,
    # admin_password.AdminPasswordController,
    # console_output.ConsoleOutputController,]         
        controller.register_actions(ctl()) 
    return controller


# func = functools.partial("函數名","參數","參數") 暫時理解為將函數換一個名字
# func() 不用傳參就會執行 partial 中的函數
# 以下代碼相當於 server_controller = functools.partial("函數名","參數","參數")
# 當 server_controller 加()被調用時 (成為server_controller())時執行 _create_controller 函數

##################################   注意:_create_controller ###################################################
##################################   注意:servers.ServersController ############################################
from nova.api.openstack.compute import servers
server_controller = functools.partial(_create_controller,
    servers.ServersController,
    [
        admin_actions.AdminActionsController,
        admin_password.AdminPasswordController,
        console_output.ConsoleOutputController,
        create_backup.CreateBackupController,
        deferred_delete.DeferredDeleteController,
        evacuate.EvacuateController,
        floating_ips.FloatingIPActionController,
        lock_server.LockServerController,
        migrate_server.MigrateServerController,
        multinic.MultinicController,
        pause_server.PauseServerController,
        remote_consoles.RemoteConsolesController,
        rescue.RescueController,
        security_groups.SecurityGroupActionController,
        shelve.ShelveController,
        suspend_server.SuspendServerController
    ]
)
class Resource(wsgi.Application):
    support_api_request_version = True

    def __init__(self, controller):
        self.controller = controller
        self.wsgi_actions = {}
        if controller:
            self.register_actions(controller)

    def register_actions(self, controller):
		# 查看 controller 對象中是否有 wsgi_actions 成員
        actions = getattr(controller, 'wsgi_actions', {})
        for key, method_name in actions.items():
            self.wsgi_actions[key] = getattr(controller, method_name)
##### 路由類 #####
###### 當此類被調用時 應該執行路由中相應的函數

# APIRouterV21 基於 ROUTE_LIST,使用 Routes 模塊作為 URL 映射的工具,將各個模塊所實現的 API 對應的 URL 注冊到 mapper 中,並把每個資源都封裝成 
# nova.api.openstack.wsgi.Resource 對象,當解析 URL 請求時,可以通過 URL 映射找到 API 對應的 Resource 對象。
class APIRouterV21(base_wsgi.Router):
    """Routes requests on the OpenStack API to the appropriate controller
    and method. The URL mapping based on the plain list `ROUTE_LIST` is built
    at here.
    	OpenStack API 的路由請求到 appropriate controller and method, 
    	在這里,基於 ROUTE_LIST 構建了URL映射;
    """
    def __init__(self, custom_routes=None):
        """:param custom_routes: the additional routes can be added by this
               parameter. This parameter is used to test on some fake routes
               primarily.
        """
        super(APIRouterV21, self).__init__(nova.api.openstack.ProjectMapper())

        if custom_routes is None:
            custom_routes = tuple()
        # 循環遍歷 ROUTE_LIST, 獲取路由字符串 和 請求方法的字典
        # ('/servers', {
        #  	  'GET': [server_controller, 'index'],
        # 	  'POST': [server_controller, 'create']
    	# }),
        for path, methods in ROUTE_LIST + custom_routes:
            # 判斷 methods 是否 str類 的對象
            if isinstance(methods, str):
                # 重定向
                self.map.redirect(path, methods)
                continue
            for method, controller_info in methods.items():  
                # methdos.items() 將字典同時返回 key value => 'GET': [server_controller, 'index']
                # 在此處執行 server_controller() -> _create_controller() -> controller() -> Resource()()
                controller = controller_info[0]()
                action = controller_info[1]
                self.map.create_route(path, method, controller, action)

    @classmethod
    def factory(cls, global_config, **local_config):
        """Simple paste factory, :class:`nova.wsgi.Router` doesn't have one."""
        return cls()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM