Neutron WSGI/HTTP API layer
0x00 前言
這章節會涵蓋 Neutron 內部的 HTTP API 和用來建立 Extensions 給 Neutron API 的一些 classes
以及透過 Python Web Server Gateway Interface (WSGI) 運作在網頁伺服器上的 python 應用程式介面
0x01 Startup
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/cmd/eventlet/server/init.py?branch=master&slice=13:33&lang=python'></script>
</body>
</html>
</WRAP>
<html><br/><br/><br/><br/><br/><br/><br/><br/></html>
在上一章節我們看到 setup.cgf 顯示了 neutron-server 的 entry point 為 neutron-server = neutron.cmd.eventlet.server:main
檔案為 neutron/neutron/cmd/eventlet/server/__init__.py
而在 main 中呼叫了 boot_server,將 _main_neutron_server 函式做為參數傳入
</WRAP>
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/server/init.py?branch=master&slice=19:41&lang=python'></script>
</body>
</html>
</WRAP>
<html><br/><br/><br/><br/><br/><br/><br/><br/></html>
在 /neutron/server/__init__.py 中
boot_server 函式會取讀取 neutron/common/config.py 裡的設定值,並將設定保存在 cfg.CONF 這個全域的資料結構中
在配置好初始化設定後會嘗試執行 server_func(),而這個 server_func() 就是上面檔案的 _main_neutron_server 函式
_main_neutron_server 函式會執行 eventlet_wsgi_server 去啟動 WSGI server
</WRAP>
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/conf/common.py?branch=master&slice=134:138&lang=python'></script>
</body>
</html>
</WRAP>
<html><br/><br/></html>
web_framework 預設值為 legacy,在我系統中這可以在 neutron/common/config.py 中看到
</WRAP>
不過 github 上的版本比較新,獨立出了 neutron/conf 資料夾,neutron/common/config.py 中部分東西放到 neutron/conf/common.py
然後 neutron/common/config.py 中改用 from neutron.conf import common as common_config
匯入
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/server/wsgi_eventlet.py?branch=master&slice=14:47&lang=python'></script>
</body>
</html>
</WRAP>
<html><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></html>
在 eventlet_wsgi_server 函式中第一行會嘗試取得一個 NeutronApiService 實例 (instance)
接著會產生 Eventlet GreenPool,執行 WSGI application 然後回應來自 client 的請求
</WRAP>
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/service.py?branch=master&slice=69:94&lang=python'></script>
</body>
</html>
</WRAP>
<html><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></html>
在 serve_wsgi 取得的參數 cls 其實就是上面丟進來的 NeutronApiService 類別
這邊會建立並啟動這個實例
</WRAP>
—-
=====0x02 WSGI Application=====
上面在建立 NeutronApiService instance 時,會執行 _run_wsgi 函式去建立 WSGI application
_run_wsgi 的觸發點是在上面 NeutronApiService 類別,這個類別繼承了 WsgiService 類別
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/service.py?branch=master&slice=49:66&lang=python'></script>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/neutron/service.py?branch=master&slice=288:302&lang=python'></script>
</body>
</html>
<html><br/><br/><br/><br/><br/><br/><br/><br/></html>
上面 NeutronApiService 類別因為繼承了 WsgiService 類別,在 87 行執行 service.start() 時觸發了 _run_wsgi
<html><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></html>
這邊則會執行 neutron/common/config.py 中的 load_paste_app
<html>
<style>
pre {
box-shadow: none;
}
table, td {
border: none;
}
</style>
<body>
<script type='text/javascript' src='gistfy-app.herokuapp.com/github/nike1000/neutron/
neutron/common/config.py?branch=master&slice=119:126&lang=python'></script>
</body>
</html>
</WRAP>
<html><br/><br/><br/><br/></html>
load_paste_app 會 parses /etc/neutron/api-paste.ini 這個檔案來載入一個 WSGI app
這邊看到的 wsgi 是 python 自己的 library,不是 neutron 特有的
</WRAP>
api-paste.ini 檔案定義了 WSGI applications 和 routes 路徑,使用的是 Python Paste INI file format
- /etc/neutron/api-paste.ini
[composite:neutron] use = egg:Paste#urlmap /: neutronversions /v2.0: neutronapi_v2_0 [composite:neutronapi_v2_0] use = call:neutron.auth:pipeline_factory noauth = cors request_id catch_errors extensions neutronapiapp_v2_0 keystone = cors request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0 [filter:request_id] paste.filter_factory = oslo_middleware:RequestId.factory [filter:catch_errors] paste.filter_factory = oslo_middleware:CatchErrors.factory [filter:cors] paste.filter_factory = oslo_middleware.cors:filter_factory oslo_config_project = neutron [filter:keystonecontext] paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory [filter:authtoken] paste.filter_factory = keystonemiddleware.auth_token:filter_factory [filter:extensions] paste.filter_factory = neutron.api.extensions:plugin_aware_extension_middleware_factory [app:neutronversions] paste.app_factory = neutron.api.versions:Versions.factory [app:neutronapiapp_v2_0] paste.app_factory = neutron.api.v2.router:APIRouter.factory
<html><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></html>
最後面可以看到 neutronapiapp_v2_0
APIRouter 類別可以將 Neutron resource (Ports, Networks, Subnets…) 對應到 URLs,並控制操作這些 resource
路徑為 neutron/api/v2/router.py
—-
=====0x03 參考資料=====
* OpenStack developer documentation:Neutron WSGI/HTTP API layer