Openstack novaソース解析-Nova API実行プロセス(novaclientからAction)
目次ディレクトリ Nova API Nova APIの実行プロセス novaclient Commandsを標準のHTTP要求 に変換 PasteDeployは、HTTP要求を特定のWSDIアプリケーション にルーティングする. Routesは、HTTP要求を特定の操作関数にルーティングし、 を実行する.
Nova API
Nova APIは、novaclientとNovaサービス間の中間層として、Novaコンポーネントサービスにアクセスし、使用する唯一の方法である.Nova APIは、高い安定性を保証する必要があるため、これらのAPIの名前と返されるデータ構造は簡単に変更できません.
Nova APIのディレクトリ構造:
ec 2|metadata|openstackの3つのディレクトリは、Novaが提供する3種類のAPIサービス(EC 2 API/openstack API/Metadata API)にそれぞれ対応している.ここでOpenstack APIはv 2/v 3/v 2を含む.1 nova/api/openstack/compute/パスの下にソースコードが格納されている3つのバージョン.Openstac APIの場合、各APIは1つのリソースに対応します.v 2バージョンのコアリソースはnova/api/openstack/compute/パスの下に保存され、いくつかのimagesが含まれています.py/servers.pyなどのリソースは,すべてのリソースがAPIサービス起動時にロードされる.
Nova APIの実行プロセス
1.novaclient Commandsを標準のHTTP要求に変換
一般的なOpenstackユーザおよび管理者は、簡易なOpenstack Commandsを実行することによってOpenstackを管理および使用することができる.しかし、Openstack ServicesのAPIはこのような命令を認識しないため、APIの外層にはnovaclientの再変換メカニズムが必要であることに注意してください.
Devstackを使用して配備する場合、novaclientはデフォルトでローカルにインストールされ、インストールディレクトリは
Openstack Commandsを実行して何が起こったの?(
EXAMPLE:(以下のOutputを見やすいように処理しました)
NOTE 1:Openstack Cammandsを使用する場合は通常2回リクエストを送信します.初回リクエスト(http://200.21.18.2:5000/v2.0/tokens)はkeystone取得許可tokenに送信され、X-Auth-Tokenフィールドに入力されます. は、1回目のリクエストで取得したtokenに基づいて、2回目のリクエスト(http://200.21.18.2:8774/v2.1/servers/detail)Novaサービスに仮想マシンのリストを取得します.
NOTE 2:このリクエストがRestful APIを直接使用して発行された場合,我々は最後の処理を行うだけでよい.例えば上記の4回目のリクエスト:
次は最後のResponseのJSONデータ(Openstack serviceの応答データはJSONデータ構造で返される)であり、そこからDEBUGの根拠として有用な情報を得ることができる.
2.PasteDeploy HTTP要求を特定のWSDIアプリケーションにルーティングする
まず、Openstackはnova-apiサービスを起動する際に、Novaプロファイルnovaに従う.confのコンフィギュレーション項目
api-paste.iniプロファイルは、異なるタイプのcomposite sectionを定義します.EG. Step1. この要求はOpenstackAPIタイプであるため、[composite:osapi_compute]によって傍受され、 Step2. Step3. keystone/noauth 2の2つのPipelineのパラメータリストには、最後のパラメータを除いてfilter sectionがあり、最後のパラメータはapp section(Application)に対応しています.このpipelineのすべてのfilterが実行されると、アプリケーション
したがって、HTTP要求をどのWSGIアプリケーションにルーティングかは、プロファイルapi-pasteによって決まる.iniが決めた.さらに、Openstack Projectは、それぞれ異なるPasteプロファイル、すなわち、それぞれ異なるWSGI SereverとWSGIアプリケーションを持っていることに注意してください.
3.RoutesはHTTP要求を特定の操作関数にルーティングして実行する
Openstackでは、各リソースがnovaにカプセル化する.api.openstack.wsgi.Resourceオブジェクトは、WSGIアプリケーションに対応しており、リソースの独立性を保証します.以上、HTTPリクエストを処理するApplicationを決定しましたが、このHTTPリクエストがApplicationの具体的な操作関数を実行したいかを決定する必要があります.これをサポートするには、Routes ModuleのMapperオブジェクトが必要です.
Routes Module:主に受信したHTTP URL要求の接尾辞Path(EG./servers/detail)を特定の操作関数にマッピングするために用いられる.その実現原理は、mapperオブジェクトを作成し、そのオブジェクトの
Routeモジュールにより,1つのHTTP要求のURLを対応するリソースのAction(リソース操作の方法)にマッピングすることができる.
Nova API
Nova APIは、novaclientとNovaサービス間の中間層として、Novaコンポーネントサービスにアクセスし、使用する唯一の方法である.Nova APIは、高い安定性を保証する必要があるため、これらのAPIの名前と返されるデータ構造は簡単に変更できません.
Nova APIのディレクトリ構造:
.
|-- ec2
|-- metadata
|-- openstack
| |-- __init__.py
| |-- api_version_request.py
| |-- auth.py
| |-- common.py
| |-- compute
| |-- extensions.py
| |-- rest_api_version_history.rst
| |-- urlmap.py
| |-- urlmap.pyc
| |-- versioned_method.py
| |-- wsgi.py
|-- opts.py
|-- sizelimit.py
|-- validation
| |-- __init__.py
| |-- parameter_types.py
| |-- validators.py
|-- validator.py
ec 2|metadata|openstackの3つのディレクトリは、Novaが提供する3種類のAPIサービス(EC 2 API/openstack API/Metadata API)にそれぞれ対応している.ここでOpenstack APIはv 2/v 3/v 2を含む.1 nova/api/openstack/compute/パスの下にソースコードが格納されている3つのバージョン.Openstac APIの場合、各APIは1つのリソースに対応します.v 2バージョンのコアリソースはnova/api/openstack/compute/パスの下に保存され、いくつかのimagesが含まれています.py/servers.pyなどのリソースは,すべてのリソースがAPIサービス起動時にロードされる.
Nova APIの実行プロセス
1.novaclient Commandsを標準のHTTP要求に変換
一般的なOpenstackユーザおよび管理者は、簡易なOpenstack Commandsを実行することによってOpenstackを管理および使用することができる.しかし、Openstack ServicesのAPIはこのような命令を認識しないため、APIの外層にはnovaclientの再変換メカニズムが必要であることに注意してください.
Devstackを使用して配備する場合、novaclientはデフォルトでローカルにインストールされ、インストールディレクトリは
/usr/local/lib/python2.7/dist-packages/novaclient
である、このディレクトリの下のshellを設定することができる.pyファイルのDEFAULT_OS_COMPUTE_API_VERSION
オプションを使用してnovacliientのバージョンを変更します.AS BELOW: DEFAULT_OS_COMPUTE_API_VERSION = '2.latest'
Openstack Commandsを実行して何が起こったの?(
nova list
を例とする)1.nova list
命令2を実行する.この命令はshell.pyキャプチャ3.shell.pyは、必要なHeader/Clontext等の情報とnova list
の操作要求内容とを組み合わせてカプセル化し、標準的なHTTP要求4を形成する.HTTPリクエストはnova-apiによって傍受取得される.Nova-apiはWSDI仕様の流れに従ってHTTP要求の配布、ルーティング、実行、応答の操作を完了する.EXAMPLE:(以下のOutputを見やすいように処理しました)
fanguiju@jmilkfan:~/devstack$ nova --debug list # --debug :
×××××××××××××××××××××××××××××××××××××××××××××××# 1.GET http://200.21.18.2:5000/v2.0 keystone v2.0 version
DEBUG (session:198) REQ: curl -g -i -X GET http://200.21.18.2:5000/v2.0 -H "Accept: application/json" -H "User-Agent: python-keystoneclient"
INFO (connectionpool:207) Starting new HTTP connection (1): 200.21.18.2
DEBUG (connectionpool:387) "GET /v2.0 HTTP/1.1" 200 337
DEBUG (session:216) RESP: [200] Content-Length: 337 Vary: X-Auth-Token Keep-Alive: timeout=5, max=100 Server: Apache/2.4.7 (Ubuntu) Connection: Keep-Alive Date: Thu, 04 Aug 2016 03:31:34 GMT Content-Type: application/json x-openstack-request-id: req-39b02ac4-7cce-441b-bc25-140e75ab4e2e
RESP BODY: {
"version": {
"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{
"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{
"href": "http://200.21.18.2:5000/v2.0/", "rel": "self"}, {
"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}
××××××××××××××××××××××××××××××××××××××××××××××××# 1. End
××××××××××××××××××××××××××××××××××××××××××××××××# 2. POST /v2.0/tokens HTTP/1.1 tokens
# : token Keystone , Output , Output
DEBUG (v2:86) Making authentication request to http://200.21.18.2:5000/v2.0/tokens
DEBUG (connectionpool:387) "POST /v2.0/tokens HTTP/1.1" 200 2844
DEBUG (session:198) REQ: curl -g -i -X GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}ac4acef5a9f5a568af553beb59ff5d99f1928849"
INFO (connectionpool:207) Starting new HTTP connection (1): 200.21.18.2
DEBUG (connectionpool:387) "GET /v2.1/6c4e4d58cb9d4451b36e774b348e8813 HTTP/1.1" 404 52
DEBUG (session:216) RESP: [404] Date: Thu, 04 Aug 2016 03:31:34 GMT Connection: keep-alive Content-Type: text/plain; charset=UTF-8 Content-Length: 52 X-Compute-Request-Id: req-c1edb651-a398-4f02-a580-920bec9f1252
RESP BODY: 404 Not Found
The resource could not be found.
# ( Mapper)
××××××××××××××××××××××××××××××××××××××××××××××××# 2. End
××××××××××××××××××××××××××××# 3. GET http://200.21.18.2:8774/v2.1/ tokens ; Nova v2.1 version
DEBUG (session:198) REQ: curl -g -i -X GET http://200.21.18.2:8774/v2.1/ -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}ac4acef5a9f5a568af553beb59ff5d99f1928849"
DEBUG (connectionpool:387) "GET /v2.1/ HTTP/1.1" 200 385
DEBUG (session:216) RESP: [200] Content-Length: 385 X-Compute-Request-Id: req-f4056355-11f5-4064-9ac9-5dfe1e722655 Vary: X-OpenStack-Nova-API-Version Connection: keep-alive X-Openstack-Nova-Api-Version: 2.1 Date: Thu, 04 Aug 2016 03:31:34 GMT Content-Type: application/json
RESP BODY: {
"version": {
"status": "CURRENT", "updated": "2013-07-23T11:33:21Z", "links": [{
"href": "http://200.21.18.2:8774/v2.1/", "rel": "self"}, {
"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}], "min_version": "2.1", "version": "2.12", "media-types": [{
"base": "application/json", "type": "application/vnd.openstack.compute+json;version=2.1"}], "id": "v2.1"}}
××××××××××××××××××××××××××××××××××××××××××××××××# 3. End
×××××××××××××××××# 4. GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/detail
DEBUG (session:198) REQ: curl -g -i -X GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/detail -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-OpenStack-Nova-API-Version: 2.6" -H "X-Auth-Token: {SHA1}ac4acef5a9f5a568af553beb59ff5d99f1928849"
DEBUG (connectionpool:387) "GET /v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/detail HTTP/1.1" 200 1975
DEBUG (session:216) RESP: [200] Content-Length: 1975 X-Compute-Request-Id: req-1089b520-09b5-4c37-b57a-04123d30504f Vary: X-OpenStack-Nova-API-Version Connection: keep-alive X-Openstack-Nova-Api-Version: 2.6 Date: Thu, 04 Aug 2016 03:31:35 GMT Content-Type: application/json
RESP BODY: {
"servers": [{
"status": "ACTIVE", "OS-EXT-SRV-ATTR:ramdisk_id": "", "updated": "2016-08-02T07:45:56Z", "hostId": "7e4e4bc79676933ebc8359ea7e954050084589d5805a1e50e009de48", "OS-EXT-SRV-ATTR:host": "fanguiju", "addresses": {
"private": [{
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:5f:bf:b2", "version": 4, "addr": "10.0.0.2", "OS-EXT-IPS:type": "fixed"}]}, "links": [{
"href": "http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/42da5d12-a470-4193-8410-0209c04f333a", "rel": "self"}, {
"href": "http://200.21.18.2:8774/6c4e4d58cb9d4451b36e774b348e8813/servers/42da5d12-a470-4193-8410-0209c04f333a", "rel": "bookmark"}], "key_name": null, "image": {
"id": "f76a9eb1-e976-4d50-9185-e7b256d14c40", "links": [{
"href": "http://200.21.18.2:8774/6c4e4d58cb9d4451b36e774b348e8813/images/f76a9eb1-e976-4d50-9185-e7b256d14c40", "rel": "bookmark"}]}, "OS-EXT-SRV-ATTR:user_data": null, "OS-EXT-STS:task_state": null, "OS-EXT-STS:vm_state": "active", "OS-EXT-SRV-ATTR:instance_name": "instance-00000001", "OS-EXT-SRV-ATTR:root_device_name": "/dev/vda", "OS-SRV-USG:launched_at": "2016-08-02T07:26:16.000000", "OS-EXT-SRV-ATTR:hypervisor_hostname": "fanguiju", "flavor": {
"id": "84", "links": [{
"href": "http://200.21.18.2:8774/6c4e4d58cb9d4451b36e774b348e8813/flavors/84", "rel": "bookmark"}]}, "id": "42da5d12-a470-4193-8410-0209c04f333a", "security_groups": [{
"name": "default"}], "OS-SRV-USG:terminated_at": null, "OS-EXT-SRV-ATTR:kernel_id": "", "OS-EXT-AZ:availability_zone": "nova", "user_id": "135b2cb86962401c82044fd4ca9daae4", "name": "TestVMwareInterface", "OS-EXT-SRV-ATTR:launch_index": 0, "created": "2016-08-02T07:25:49Z", "tenant_id": "6c4e4d58cb9d4451b36e774b348e8813", "OS-DCF:diskConfig": "AUTO", "os-extended-volumes:volumes_attached": [], "accessIPv4": "", "accessIPv6": "", "OS-EXT-SRV-ATTR:reservation_id": "r-kud9zm9w", "OS-EXT-SRV-ATTR:hostname": "testvmwareinterface", "progress": 0, "OS-EXT-STS:power_state": 0, "config_drive": "True", "metadata": {}}]}
+--------------------------------------+---------------------+--------+------------+-------------+------------------+
| ID | Name | Status | Task State | Power State | Networks |
+--------------------------------------+---------------------+--------+------------+-------------+------------------+
| 42da5d12-a470-4193-8410-0209c04f333a | TestVMwareInterface | ACTIVE | - | NOSTATE | private=10.0.0.2 |
+--------------------------------------+---------------------+--------+------------+-------------+------------------+
*******************************************# 4. END
NOTE 1:Openstack Cammandsを使用する場合は通常2回リクエストを送信します.
NOTE 2:このリクエストがRestful APIを直接使用して発行された場合,我々は最後の処理を行うだけでよい.例えば上記の4回目のリクエスト:
GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/detail
さらに,上記のOutputから,curl命令を直接用いてHTTP要求を送信することも可能であることが分かる.次は最後のResponseのJSONデータ(Openstack serviceの応答データはJSONデータ構造で返される)であり、そこからDEBUGの根拠として有用な情報を得ることができる.
{
"servers": [
{
"status": "ACTIVE",
"OS-EXT-SRV-ATTR:ramdisk_id": "",
"updated": "2016-08-02T07:45:56Z",
"hostId": "7e4e4bc79676933ebc8359ea7e954050084589d5805a1e50e009de48",
"OS-EXT-SRV-ATTR:host": "fanguiju",
"addresses": {
"private": [
{
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:5f:bf:b2",
"version": 4,
"addr": "10.0.0.2",
"OS-EXT-IPS:type": "fixed"
}
]
},
"links": [
{
"href": "http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/42da5d12-a470-4193-8410-0209c04f333a",
"rel": "self"
},
{
"href": "http://200.21.18.2:8774/6c4e4d58cb9d4451b36e774b348e8813/servers/42da5d12-a470-4193-8410-0209c04f333a",
"rel": "bookmark"
}
],
"key_name": null,
"image": {
"id": "f76a9eb1-e976-4d50-9185-e7b256d14c40", #Image ID
"links": [
{
"href": "http://200.21.18.2:8774/6c4e4d58cb9d4451b36e774b348e8813/images/f76a9eb1-e976-4d50-9185-e7b256d14c40",
"rel": "bookmark"
}
]
},
"OS-EXT-SRV-ATTR:user_data": null,
"OS-EXT-STS:task_state": null,
"OS-EXT-STS:vm_state": "active",
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
"OS-EXT-SRV-ATTR:root_device_name": "/dev/vda",
"OS-SRV-USG:launched_at": "2016-08-02T07:26:16.000000",
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fanguiju",
"flavor": {
"id": "84",
"links": [
{
"href": "http://200.21.18.2:8774/6c4e4d58cb9d4451b36e774b348e8813/flavors/84",
"rel": "bookmark"
}
]
},
"id": "42da5d12-a470-4193-8410-0209c04f333a", # GuestOS ID
"security_groups": [
{
"name": "default"
}
],
"OS-SRV-USG:terminated_at": null,
"OS-EXT-SRV-ATTR:kernel_id": "",
"OS-EXT-AZ:availability_zone": "nova",
"user_id": "135b2cb86962401c82044fd4ca9daae4",
"name": "TestVMwareInterface",
"OS-EXT-SRV-ATTR:launch_index": 0,
"created": "2016-08-02T07:25:49Z",
"tenant_id": "6c4e4d58cb9d4451b36e774b348e8813", #tenant_id novaclient shell.sh HTTP URL
"OS-DCF:diskConfig": "AUTO",
"os-extended-volumes:volumes_attached": [],
"accessIPv4": "",
"accessIPv6": "",
"OS-EXT-SRV-ATTR:reservation_id": "r-kud9zm9w",
"OS-EXT-SRV-ATTR:hostname": "testvmwareinterface",
"progress": 0,
"OS-EXT-STS:power_state": 0,
"config_drive": "True",
"metadata": {}
}
]
}
2.PasteDeploy HTTP要求を特定のWSDIアプリケーションにルーティングする
まず、Openstackはnova-apiサービスを起動する際に、Novaプロファイルnovaに従う.confのコンフィギュレーション項目
enabled_apis = ec2,osapi_compute,metadata
は、1つまたは複数のWSDIサーバを作成するために使用される.各WSGIサーバは、3つのタイプのNova APIを表す1つのタイプのNova API要求を処理する.また、WSGIサーバを作成する際には、Pasteのプロファイルnova/etc/nova/api-pasteに従う.ini WSDIアプリケーションをロードします.WSGIアプリケーションがロードされると、WSGIアプリケーションはリクエストを待機および傍受する状態になります.ロード動作はnova/nova/service.py実装.# nova/nova/service.py
class WSGIService(service.Service):
"""Provides ability to launch API from a 'paste' configuration."""
def __init__(self, name, loader=None, use_ssl=False, max_url_len=None):
self.name = name
self.manager = self._get_manager()
self.loader = loader or wsgi.Loader()
# Nova API WSGI Application, HTTP URL
self.app = self.loader.load_app(name)
# inherit all compute_api worker counts from osapi_compute
if name.startswith('openstack_compute_api'):
wname = 'osapi_compute'
else:
wname = name
self.host = getattr(CONF, '%s_listen' % name, "0.0.0.0")
self.port = getattr(CONF, '%s_listen_port' % name, 0)
self.workers = (getattr(CONF, '%s_workers' % wname, None) or
processutils.get_worker_count())
if self.workers and self.workers < 1:
worker_name = '%s_workers' % name
msg = (_("%(worker_name)s value of %(workers)s is invalid, "
"must be greater than 0") %
{
'worker_name': worker_name,
'workers': str(self.workers)})
raise exception.InvalidInput(msg)
self.use_ssl = use_ssl
# HostIP Port HTTP Socket, Socket host port HTTP 。
self.server = wsgi.Server(name,
self.app,
host=self.host,
port=self.port,
use_ssl=self.use_ssl,
max_url_len=max_url_len)
# Pull back actual port used
self.port = self.server.port
self.backdoor_port = None
api-paste.iniプロファイルは、異なるタイプのcomposite sectionを定義します.EG.
[composite:metadata] / [composite:ec2] / [composite:ec2cloud] / [composite:osapi_compute] / [composite:openstack_compute_api_v21]
等.SocketがHTTP要求:GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/servers/detail
を傍受すると、composite sectionは、nova−apiにアクセスした後に最初に通過するSectionである.以下、api-pasteを介して要求する.Ini構成をWSGIアプリケーションにマッピングするには:nova.api.openstack.urlmap
モジュールのurlmap_factory
関数を使用して[composite:openstack_compute_api_v21]
に要求が配布される.[composite:osapi_compute]
use = call:nova.api.openstack.urlmap:urlmap_factory
/: oscomputeversions
/v1.1: openstack_compute_api_v21_legacy_v2_compatible
/v2: openstack_compute_api_v21_legacy_v2_compatible
/v2.1: openstack_compute_api_v21
[composite:openstack_compute_api_v21]
は、nova.api.auth
モジュールの下のpipeline_factory_v21
関数を使用して、要求をさらに配布する.そしてここではnovaに基づいてconfプロファイルの認証ポリシーオプションauth_strategy
は、nova/api/authで、その認証方式(keystone/noauth 2)を使用することを決定する.pyファイルは、認証方式がkeystoneであることをデフォルトで定義します.[composite:openstack_compute_api_v21]
use = call:nova.api.auth:pipeline_factory_v21
noauth2 = compute_req_id faultwrap sizelimit noauth2 osapi_compute_app_v21
keystone = compute_req_id faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v21
osapi_compute_app_v21
が呼び出されます.[app:osapi_compute_app_v21]
paste.app_factory = nova.api.openstack.compute:APIRouterV21.factory
したがって、HTTP要求をどのWSGIアプリケーションにルーティングかは、プロファイルapi-pasteによって決まる.iniが決めた.さらに、Openstack Projectは、それぞれ異なるPasteプロファイル、すなわち、それぞれ異なるWSGI SereverとWSGIアプリケーションを持っていることに注意してください.
3.RoutesはHTTP要求を特定の操作関数にルーティングして実行する
Openstackでは、各リソースがnovaにカプセル化する.api.openstack.wsgi.Resourceオブジェクトは、WSGIアプリケーションに対応しており、リソースの独立性を保証します.以上、HTTPリクエストを処理するApplicationを決定しましたが、このHTTPリクエストがApplicationの具体的な操作関数を実行したいかを決定する必要があります.これをサポートするには、Routes ModuleのMapperオブジェクトが必要です.
Routes Module:主に受信したHTTP URL要求の接尾辞Path(EG./servers/detail)を特定の操作関数にマッピングするために用いられる.その実現原理は、mapperオブジェクトを作成し、そのオブジェクトの
connect()
メソッドを呼び出して、接尾辞PathおよびHTTP組み込みメソッドをControllerのアクションにマッピングすることである.Controllerはカスタムクラスインスタンスオブジェクトであり、OPenstackリソースごとに1つのControllerに対応し、Controllerもリソース操作関数の集合である.Actionは、Controllerオブジェクトが提供する操作関数(EG.index/show/delect/update/create)を表します.一般にこれらのアクションを呼び出す前にこのアクションをHTTPの組み込みメソッドにマッピングする.EG. GET/POST/DELETE/PUT . HTTPリクエストのURL PathおよびHTTP内蔵メソッドは、Openstack内の唯一のリソースに対してどのような操作を実行するかを決定することができる.class Router(object):
"""WSGI middleware that maps incoming requests to WSGI apps."""
def __init__(self, mapper):
"""Create a router for the given routes.Mapper.
Each route in `mapper` must specify a 'controller', which is a
WSGI app to call. You'll probably want to specify an 'action' as
well and have your controller be an object that can route
the request to the action-specific method.
Examples:
mapper = routes.Mapper()
sc = ServerController()
# Explicit mapping of one route to a controller+action
mapper.connect(None, '/svrlist', controller=sc, action='list')
# Actions are all implicitly defined
mapper.resource('server', 'servers', controller=sc)
# Pointing to an arbitrary WSGI app. You can specify the
# {path_info:.*} parameter so the target app can be handed just that
# section of the URL.
mapper.connect(None, '/v1.0/{path_info:.*}', controller=BlogApp())
"""
self.map = mapper
# routers mapper _dispatch
# routes.middleware.RoutesMiddleware
self._router = routes.middleware.RoutesMiddleware(self._dispatch,
self.map)
@webob.dec.wsgify(RequestClass=Request)
def __call__(self, req):
"""Route the incoming request to a controller based on self.map.
If no match, return a 404.
"""
# mapper HTTP WSGI Application, 。 HTTP URL Controller Action。
return self._router
@staticmethod
@webob.dec.wsgify(RequestClass=Request)
def _dispatch(req):
"""Dispatch the request to the appropriate controller.
Called by self._router after matching the incoming request to a route
and putting the information into req.environ. Either returns 404
or the routed WSGI app's response.
"""
# HTTP environ environ URL Controller 。
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound()
app = match['controller']
return app
Routeモジュールにより,1つのHTTP要求のURLを対応するリソースのAction(リソース操作の方法)にマッピングすることができる.