1. 程式人生 > >openstack獲取使用者token(及endpoints)

openstack獲取使用者token(及endpoints)

        對於openstack的api操作來說,大量的命令都依賴相關使用者的token來完成,尤其對自動化測試來說,可以說拿到了使用者的token就相當於取得了進入openstack這個大工廠大門的鑰匙,有了這個鑰匙,才能進入這個工廠大顯身手。

        要想拿到token, 必須知道使用者的相關資訊,其中使用者名稱和密碼是必須的,如果還想取得更多的資訊,例如使用者對各種服務包括glance, keystond的訪問endpoint, 還需要提供使用者的tenant資訊。實際上,對於終端使用者來說,因為使用者名稱,密碼以及tenant名更為直觀,所以很少會直接用token進行操作,但對於自動化測試來說,因為要直接和相關api打交道,取得token就相當有必要了。

        命令列取得使用者token的命令為:

        # curl -X POST http://localhost:5000/v2.0/tokens -d '{"auth":{"passwordCredentials":{"username": "username", "password":"password"}}}' -H "Content-type: application/json"

        其中localhost:5000是openstack keystone服務的endpoint, 如果沒有特殊的設定,5000就是keystone服務程序的埠號。

        /v2.0/token 是openstack api裡定義的取得token的URI, 請求方式為POST,這個可以從openstack.org裡查到


       後面json結構的資料‘auth’是提供給keystone服務使用者資訊,包括使用者名稱和密碼。下面看一下輸出:

       {"access": {"token": {"expires": "2013-06-04T03:06:23Z", "id": "5fcf748e0d5d4a02ae3465e0dd301f40"}, "serviceCatalog": {}, "user": {"username": "username", "roles_links": [], "id": "ce205b61760c463cb46e41909de8495f", "roles": [], "name": "username"}}}

       這是openstack/essex版本下的token輸出,其中['token']['id']就是我們得到的使用者token。對於openstack/grizzly版本, 使用者的token比這個要長得多,但基本結構是一樣的。

       下面看一下使用tenant的情況:

       curl -X POST http://localhost:5000/v2.0/tokens -d '{"auth":{"passwordCredentials":{"username": "admin", "password":"crowbar"}, "tenantName":"tenantname"}}' -H "Content-type: application/json"

       輸出:

       {"access": {"token": {"expires": "2013-06-04T03:14:12Z", "id": "fc3e38a93e95462da5028b1fb3a688c0", "tenant": {"description": "description", "enabled": true, "id": "4e14ab2a2df045f1a6f02081a46deb2c", "name": "tenantname"}}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://localhost:8776/v1/4e14ab2a2df045f1a6f02081a46deb2c", "region": "RegionOne", "internalURL": "http://localhost:8776/v1/4e14ab2a2df045f1a6f02081a46deb2c", "publicURL": "http://localhost:8776/v1/4e14ab2a2df045f1a6f02081a46deb2c"}], "endpoints_links": [], "type": "volume", "name": "nova-volume"}, {"endpoints": [{"adminURL": "http://localhost:9292/v1", "region": "RegionOne", "internalURL": "http://localhost:9292/v1", "publicURL": "http://localhost:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}, {"endpoints": [{"adminURL": "http://localhost:8774/v2/4e14ab2a2df045f1a6f02081a46deb2c", "region": "RegionOne", "internalURL": "http://localhost:8774/v2/4e14ab2a2df045f1a6f02081a46deb2c", "publicURL": "http://localhost:8774/v2/4e14ab2a2df045f1a6f02081a46deb2c"}], "endpoints_links": [], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL": "http://localhost:8773/services/Admin", "region": "RegionOne", "internalURL": "http://localhost:8773/services/Cloud", "publicURL": "http://localhost:8773/services/Cloud"}], "endpoints_links": [], "type": "ec2", "name": "ec2"}, {"endpoints": [{"adminURL": "http://localhost:35357/v2.0", "region": "RegionOne", "internalURL": "http://localhost:5000/v2.0", "publicURL": "http://localhost:5000/v2.0"}], "endpoints_links": [], "type": "identity", "name": "keystone"}], "user": {"username": "admin", "roles_links": [], "id": "ce205b61760c463cb46e41909de8495f", "roles": [{"id": "454cb6cbddaf41f2af6f87e68ce58d64", "name": "KeystoneAdmin"}, {"id": "5a80a5b5d4244f48ac7d3079d56555c6", "name": "KeystoneServiceAdmin"}, {"id": "c5a190185ea7434eb2c35bbd1bb52051", "name": "username"}], "name": "tenentname"}}}      

        可以看到,如果在請求token的時候同時提供了tenant資訊,則可以額外獲取使用者相關的endpoints資訊。這樣,有了token和相關endpoints, 就能夠對openstack的api進行相關的訪問和操作了。順便說明,上述提供的tenant的資訊也可以是tenant的id, 格式為"tenantId":"<tenantID>“。

        使用者每次發出一次請求,就會生成一個token, 同時會在glance資料庫的token表內生成一個記錄。每個token的有效時間預設為24個小時。

        程式設計實現取得使用者token也極為簡單,程式碼如下:

import httplib2
import json

http_obj = httplib2.Http()
headers = {}
body = {
    "auth": {
            "passwordCredentials":{
                "username": 'username',
                "password": 'password',
            },
            "tenantName": 'tenantname',
        },
    }

req_url = "http://localhost:5000/v2.0/tokens"
method = "POST"

headers['Content-Type'] = 'application/json'
headers['Accept'] = 'application/json'

resp, token = http_obj.request(req_url, method,
                               headers=headers, body=json.dumps(body))

print resp
print token

如果在body裡不提供tenantName或tenantId的資料,則返回的是上述command line命令不包括endpoints的輸出。