Python API:OpenStack 隱藏深處的秘密
OpenStack 是一個越來越流行的、用于部署基礎架構即服務 (IaaS) 云的開源解決方案。OpenStack 附帶了一個儀表板 Web 應用程序,非常適合執行手動任務,比如啟動單個虛擬機 (VM) 實例,但是,如果希望自動化基于云的任務,則需要編寫可操作 OpenStack 的腳本。
OpenStack 中的服務
OpenStack 中的 服務e 這個詞承載了太多含義。它用于表示:
- 一個 OpenStack 項目(比如 Compute Service ( nova ) 和 Identity Service ( keystone ))
- Identity Service 目錄中的一個條目(比如 Image、Compute 和 Volume)
- 一個 Linux? 守護進程(比如 nova-api 和 quantum-l3-agent )
一個 OpenStack 項目與 Identity Service 目錄中的一個或多個條目有關聯,由一個或多個 Linux 守護進程實現。在本文中,我使用 “服務” 表示 OpenStack 項目。
許多用戶直接為 OpenStack 具象狀態傳輸 (REST) 應用編程接口 (API) 編寫自動化腳本,或者編寫調用命令行工具(比如 keystone 或 nova )的 shell 腳本。但 Python 中有一種編寫 OpenStack 自動化腳本的更好方法。所有 OpenStack 服務都公開了原生 Python API,以公開與命令行工具相同的特性集。不幸的是,描述如何使用這些 API 的文檔很少。
如果您是 Python 程序員,那么 Python API 會比命令行工具或 REST API 容易使用得多。在本文中,我將演示如何使用原生 OpenStack Python API 自動化常見的用戶和管理性任務。
OpenStack 項目和代號
OpenStack 這個詞不是指單個應用程序。它是一個服務集合,這些服務協同工作來實現 IaaS 云。(參見邊欄,了解這里所說的 “服務” 的含義。)每個 OpenStack 服務都有一個正式名稱和一個代號,如表 1 所示,而且每個 OpenStack 服務公開了自己的 Python API。
表 1. OpenStack 服務和代號
正式名稱 | 代號 |
---|---|
Identity Service | keystone |
Image Service | glance |
Compute Service | nova |
Networking Service | quantum |
Block Storage Service | cinder |
Object Storage Service | swift |
安裝 Python 綁定
Python 綁定與每個服務的命令行工具捆綁在一起。事實上,每個命令行工具使用相應的 Python API 實現。可從 Python Package Index(PyPi — 參見,獲取相關鏈接)中使用 pip (一個 Python 包安裝程序)來安裝每個工具。 pip 包名稱包括:
- python-keystoneclient
- python-glanceclient
- python-novaclient
- python-quantumclient
- python-cinderclient
- python-swiftclient
例如,要安裝 keystone 客戶端,可運行以下命令:
$ pipinstallpython-keystoneclient
可將這些包安裝到 Python 虛擬環境或您的系統級 Python 包中,只要您擁有本地機器上的根用戶特權。
所有 OpenStack API 都有一些版本,Python 綁定支持多個 API 版本,以保持向后兼容性。因此可以安全地下載這些包的最新版本,因為它們將會適合 OpenStack 服務的所有更低版本。
在本文中,我將重點介紹來自以下服務的 Python API 示例:
- OpenStack Identity Service ( keystone )
- OpenStack Image Service ( glance )
- OpenStack Compute Service ( nova )
設置一個測試環境
為了最充分地掌握本文的內容,建議您使用管理員特權訪問一個 OpenStack 云,以便試用這些代碼段。如果目前沒有 OpenStack 云的管理員訪問權,那么最簡單的方法就是在一個 VM 中部署 OpenStack。DevStack 項目(參見獲取鏈接)旨在簡化在單個機器上創建一個面向開發的 OpenStack 部署的過程。配合 VirtualBox 等虛擬化工具,您可以在筆記本電腦上(甚至在 Mac 或 Windows? 上)實現一個 OpenStack 云。
您還可以獲得 TryStack 上的一個免費帳戶,TryStack 是由社區維護的 OpenStack 沙盒(參見)。請注意,只能獲取 TryStack 上的用戶級特權,不能獲得管理級特權,所以您無法使用 TryStack 測試需要管理特權的腳本。
OpenStack Identity (keystone)
客戶端要對 Identity ( keystone ) API 發出請求,可實例化適當的 keystone 客戶端 Python 對象并調用它的方法。因為 API 提供了版本控制,所以 Python 客戶端始終與該 API 的一個特定版本有關聯。
清單 1 顯示了使用 keystone 客戶端的 2.0 版將 Image Service 添加到服務目錄的示例。
清單 1. 使用 keystone 創建一個管理員角色
importkeystoneclient.v2_0.clientas ksclient
# Replace the method arguments with the ones from your local config
keystone = ksclient.Client(auth_url="http://192.168.27.100:35357/v2.0",
username="admin",
password="devstack",
tenant_name="demo")
glance_service = keystone.services.create(name="glance",
service_type="image",
description="OpenStack Image Service")
憑據
在實例化 keystoneclient.v2_0.client.Client 對象時必須提供憑據。 keystone 端點接受兩種類型的憑據:令牌,或者用戶名和密碼。如果您是管理員,那么您可以使用 admin 令牌,這是一種具有管理員特權且永不過期的特殊令牌。要定義此令牌,可以使用運行 keystone 服務的機器上的 /etc/keystone/keystone.conf 文件中的 admin_token 選項(參見清單 2)。
清單 2. 使用身份驗證令牌執行身份驗證
importkeystoneclient.v2_0.clientas ksclient
# Replace the values below with the ones from your local config
endpoint = "http://192.168.27.100:35357/v2.0"
admin_token = "devstack"
keystone = ksclient.Client(endpoint=endpoint, token=admin_token)
出于安全原因,一般不贊成使用 admin 令牌。相反,在創建了具有管理特權的用戶之后,建議 OpenStack Identity 開發人員始終使用用戶名和密碼進行身份驗證(參見清單 3)。
清單 3. 使用用戶名和密碼執行身份驗證
importkeystoneclient.v2_0.clientas ksclient
# Replace the values below the ones from your local config,
auth_url = "http://192.168.27.100:35357/v2.0"
username = "admin"
password = "devstack"
tenant_name = "demo"
keystone = ksclient.Client(auth_url=auth_url, username=username,
password=password, tenant_name=tenant_name)
加載一個 openrc 文件
為了簡化身份驗證,建議創建一個 openrc 文件,將憑據導出到環境變量中。這樣做可以避免將登錄信息硬編碼到腳本中。清單 4 顯示了一個 openrc 文件示例。
清單 4. 從環境變量加載憑據
exportOS_USERNAME="myname"
exportOS_PASSWORD="mypassword"
exportOS_TENANT_NAME="mytenant"
exportOS_AUTH_URL="http://10.20.0.2:5000/v2.0/"
環境變量 OS_USERNAME、OS_PASSWORD、OS_TENANT_NAME 和 OS_AUTH_URL 在所有 Python 命令行工具中已標準化。如果設置了這些環境變量,命令行工具( keystone 、 nova )將會使用它們對其 API 端點進行身份驗證。
使用 Bash source 內置命令將這些環境變量加載到您當前的 shell 中。如果使用 Bash 作為標準 shell,那么您可能希望將這行代碼添加到 .profile 中,以便在您每次登錄時自動設置這些環境變量:
$ sourceopenrc
找到 openrc 文件后,Python 腳本就可以從環境中檢索憑據。我們創建了一個名為 credentials.py 的 Python 文件(如清單 5 所示),以便從環境中提取登錄信息。請注意, keystone 和 nova 在其客戶端初始化器方法中使用了稍微不同的變量名,所以我為每個工具定義了不同的函數。
清單 5. credentials.py
#!/usr/bin/env python
importos
defget_keystone_creds():
d = {}
d['username'] = os.environ['OS_USERNAME']
d['password'] = os.environ['OS_PASSWORD']
d['auth_url'] = os.environ['OS_AUTH_URL']
d['tenant_name'] = os.environ['OS_TENANT_NAME']
return d
defget_nova_creds():
d = {}
d['username'] = os.environ['OS_USERNAME']
d['api_key'] = os.environ['OS_PASSWORD']
d['auth_url'] = os.environ['OS_AUTH_URL']
d['project_id'] = os.environ['OS_TENANT_NAME']
return d
身份驗證令牌
如果客戶端初始化器返回時沒有拋出異常,則它已成功向端點驗證。您可訪問剛才通過返回的對象 auth_token 屬性發出的 keystone 令牌,如清單 6 所示。當對 glance API 進行身份驗證時,需要顯式地將一個 keystone 身份驗證令牌作為參數傳遞給初始化器,我們稍后會對此進行討論。
清單 6. 在一個交互式 Python 會話中對一個 keystone 端點執行成功的驗證
>>> importkeystoneclient.v2_0.clientas ksclient
>>> fromcredentialsimportget_keystone_creds
>>> creds = get_keystone_creds()
>>> keystone = ksclient.Client(**creds)
>>> keystone.auth_token
u'MIILkAYJKoZIhvcNAQcCoIILgTCCC30CAQExCTAHBgUrDgMCGjCCCmkGCSqGSIb3DQEHAaCCCloE
ggpWeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxMy0wNS0yNlQwMjoxMjo0Mi
42MDAwMjUiLCAiZXhwaXJlcyI6ICIyMDEzLTA1LTI3VDAyOjEyOjQyWiIsICJpZCI6ICJwbGFjZWhv
bGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogbnVsbCwgImVuYWJsZWQiOiB0cnVlLCAiaW
...
fI9JnOBZJwuoma8je0a1AvLff6AcJ1zFkVZGb'
備注:OpenStack Identity 的 Grizzly 版本默認情況下使用了公鑰基礎架構令牌,這些令牌比 OpenStack 的以前版本中使用的通用惟一標識符令牌(例如 7d9fde355f09458f8e97986a5a652bfe )要長得多。
CRUD 操作
keystone API 實質上是一個創建、讀取、更新、刪除 (CRUD) 接口:與 keystone API 的大多數交互都會讀取 keystone 后端數據庫或修改它。與該 API 的大多數交互都會調用 Manager 對象。一個 Manager 表示一個具有相同類型的對象集合。例如, UserManager 處理 keystone 用戶, TenantManager 處理租戶, RoleManager 處理角色,等等。這些管理器支持多種操作,比如 create (創建一個新對象)、 get (按 ID 檢索一個對象)、 list (檢索所有對象)和 delete 。
創建用戶、租戶和角色
通常,在部署 OpenStack 時,執行的第一個任務是創建一個 keystone 租戶,然后創建一個具有管理特權的 keystone 用戶。顯示了一個使用 Python API 自動化此過程的示例。該腳本可執行以下任務:
- 創建一個用戶角色 ( Client.roles.create )。
- 創建一個管理角色 ( Client.roles.create )。
- 創建一個名為 acme 的租戶 ( Client.tenants.create )。
- 創建一個名為 admin 的用戶 ( Client.users.create )。
- 為 admin 用戶分配 acme 租戶中的管理角色 ( Client.roles.add_user_role )。
這是一個適合使用 admin 令牌的場景,因為 Identity Service 不包含任何具有管理特權的用戶。
清單 7. 創建一個用戶、租戶和角色
importkeystoneclient.v2_0.clientas ksclient
endpoint = "http://192.168.27.100:35357/v2.0"
admin_token = "devstack"
keystone = ksclient.Client(endpoint=endpoint, token=admin_token)
user_role = keystone.roles.create("user")
admin_role = keystone.roles.create("admin")
acme_tenant = keystone.tenants.create(tenant_name="Acme",
description="Employees of Acme Corp.",
enabled=True)
admin_user = keystone.users.create(name="admin",
password="a.G'03134!j",
email="cloudmaster@example.com", tenant_id=acme_tenant.id)
keystone.roles.add_user_role(admin_user, admin_role, acme_tenant)
創建服務和端點
通常,在 OpenStack 云中,部署 Identity Service 的下一個任務是在 keystone 中填充云和端點中的服務。清單 8 顯示了使用 Client.services.create 和 Client.endpoints.create 方法為 Identity Service 添加一個服務和端點的示例。
清單 8. 創建一個服務和端點
importkeystoneclient.v2_0.clientas ksclient
creds = get_keystone_creds() # See <a href="#openrc">openrc-creds</a>
keystone = ksclient.Client(**creds)
service = keystone.services.create(name="keystone",
service_type="identity",
description="OpenStack Identity Service")
keystone_publicurl = "http://192.168.27.100:5000/v2.0"
keystone_adminurl = "http://192.168.27.100:35357/v2.0"
keystone.endpoints.create(service_id=service.id,
region="Northeast",
publicurl=keystone_publicurl,
adminurl=keystone_adminurl,
internalurl=keystone_publicurl)
訪問服務目錄
keystone 的主要功能之一就是充當服務目錄。客戶端可使用 keystone 查找 OpenStack 服務的端點 URL。該 API 通過 keystoneclient.v2_0.client.Client.service_catalog.url_for 方法提供此功能。此方法支持按類型(例如 image、volume、compute、network)和端點類型( publicURL 、 internalURL 、 adminURL )查找服務端點。
清單 9 演示了如何使用 url_for 方法檢索 OpenStack Image ( glance ) Service 的端點。
清單 9. 在一個交互式 Python 會話中查詢 glance 端點
>>> import keystoneclient.v2_0.clientas ksclient
>>> creds = get_keystone_creds() # See <a href="openrc-creds" />
>>> keystone = ksclient.Client(**creds)
>>> glance_endpoint = keystone.service_catalog.url_for(service_type='image',
endpoint_type='publicURL')
>>> glance_endpoint
u'http://192.168.27.100:9292'
OpenStack Compute (nova)
nova API 的 1.1 版和第 2 版
nova API 的 1.1 版和第 2 版是相同的。可用 “2” 代替 “1.1”,傳遞它作為 novaclient.client.Client initializer 的第一個參數,但沒有 novaclient.v2 模塊,只有一個 novaclient.v1_1 模塊。
OpenStack Compute ( nova ) Python API 的工作原理類似于 OpenStack Identity API。這里使用了 nova API 的 1.1 版,所以本文中使用的 nova Python 綁定的 1.1 版中的類位于 novaclient.v1_1 Python 命名空間中。
對 nova-api 端點執行身份驗證
要向 nova-api 端點發出請求,可實例化一個 novaclient.v1_1.client.Client 對象并對它執行調用。可通過兩種方式獲取一個與該 API 的 1.1 版進行通信的客戶端。清單 10 演示了如何通過傳遞版本字符串作為參數來獲取合適的客戶端。
清單 10. 傳遞版本作為參數
fromnovaclientimportclientas novaclient
fromcredentialsimportget_nova_creds
creds = get_nova_creds()
nova = novaclient.Client("1.1", **creds)
清單 11 演示了如何通過顯式導入 1.1 版模塊來獲取合適的客戶端。
清單 11. 直接導入版本
importnovaclient.v1_1.clientas nvclient
fromcredentialsimportget_nova_creds
creds = get_nova_creds()
nova = nvclient.Client(**creds)
清單實例
使用 Client.servers.list 方法列出當前的 VM 實例,如清單 12 所示。
清單 12. 在一個交互式 Python 會話中獲取一個 VM 實例列表
>>> import novaclient.v1_1.clientas nvclient
>>> from credentialsimport get_nova_creds
>>> creds = get_nova_creds()
>>> nova = nvclient.Client(**creds)
>>> nova.servers.list()
[<Server: cirros>]
按名稱獲取一個實例并關閉它
如果不知道實例的 ID,只知道它的名稱,那么可以使用 Server.find 方法。清單 13 顯示了如何按名稱找到一個實例,然后使用 Server.delete 方法終止它。
清單 13. 終止 “my-vm” 實例
importnovaclient.v1_1.clientas nvclient
fromcredentialsimportget_nova_creds
creds = get_nova_creds()
nova = nvclient.Client(**creds)
server = nova.servers.find(name="my-vm")
server.delete()
啟動一個實例并檢查狀態
要啟動一個新實例,可以使用 Client.servers.create 方法,如清單 14 所示。請注意,必須傳遞一個 image 對象和 flavor 對象,而不是 image 和 flavor 的名稱。該示例還使用 Client.keypairs.create 方法將 Secure Shell (SSH) 公鑰上傳到 ~/.ssh/id_rsa.pub ,并將密鑰對命名為 mykey(假設該密鑰對還不存在)。最后,它使用 Client.servers.get 方法獲取該實例的當前狀態,使用它來輪詢狀態。
清單 14. 啟動一個新實例
importos
importtime
importnovaclient.v1_1.clientas nvclient
fromcredentialsimportget_nova_creds
creds = get_nova_creds()
nova = nvclient.Client(**creds)
if not nova.keypairs.findall(name="mykey"):
withopen(os.path.expanduser('~/.ssh/id_rsa.pub')) as fpubkey:
nova.keypairs.create(name="mykey", public_key=fpubkey.read())
image = nova.images.find(name="cirros")
flavor = nova.flavors.find(name="m1.tiny")
instance = nova.servers.create(name="test", image=image, flavor=flavor, key_name="mykey")
# Poll at 5 second intervals, until the status is no longer 'BUILD'
status = instance.status
while status == 'BUILD':
time.sleep(5)
# Retrieve the instance again so the status field updates
instance = nova.servers.get(instance.id)
status = instance.status
print "status: %s" % status
附加一個浮動 IP 地址
要附加一個浮動 IP 地址,必須首先驗證 OpenStack 是否擁有一個可用的浮動 IP 地址。使用 Client.floating_ips.list 方法獲取可用的浮動 IP 地址列表。如果結果列表是空的,可使用 Client.floating_ips.create 方法分配一個新的浮動 IP 地址,然后使用 Server.add_floating_ip 方法將它分配給該實例,如清單 15 所示。
清單 15. 創建一個浮動 IP 地址
>>> nova.floating_ips.list()
[]
>>> floating_ip = nova.floating_ips.create()
<FloatingIPfixed_ip=None, id=1, instance_id=None, ip=192.168.27.129, pool=public>
>>> instance = nova.servers.find(name="test")
>>> instance.add_floating_ip(floating_ip)
更改一個安全組
使用 Client.security_group_rules.create 方法向一個安全組添加規則。清單 16 中的示例修改了默認的安全組,以便支持 SSH(在端口 22 上運行)以及所有 Internet Control Message Protocol (ICMP) 流量。為此,我使用 Client.security_groups.find 方法獲取了名為 default 的安全組。
清單 16. 允許使用 default 安全組中的端口 22 和 ICMP
importnovaclient.v1_1.clientas nvclient
fromcredentialsimportget_nova_creds
creds = get_nova_creds()
nova = nvclient.Client(**creds)
secgroup = nova.security_groups.find(name="default")
nova.security_group_rules.create(secgroup.id,
ip_protocol="tcp",
from_port=22,
to_port=22)
nova.security_group_rules.create(secgroup.id,
ip_protocol="icmp",
from_port=-1,
to_port=-1)
獲取控制臺日志
Server.get_console_output 方法獲取了在啟動 VM 時發送給控制臺的文本。可以分析控制臺輸出,以解決更改主機密鑰的常見問題。
IaaS 云(比如 OpenStack)的一個缺陷是,它不能很好地與 SSH 主機密鑰檢查功能進行互操作。如果登錄到(比如 10.40.1.150 上的)某個實例,而該 IP 地址之前被您過去登錄的另一個實例使用過,那么您將獲得一個類似清單 17 的錯誤。
清單 17. ID 更改后的錯誤
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTEHOSTIDENTIFICATIONHASCHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ITIS POSSIBLETHATSOMEONEIS DOINGSOMETHINGNASTY!
Someonecouldbeeavesdroppingonyourightnow (man-in-the-middleattack)!
Itis alsopossiblethat a hostkeyhasjustbeenchanged.
Thefingerprintfor theRSAkeysentbytheremotehostis
6f:2b:59:46:cb:8c:81:48:06:f3:c5:db:40:23:d3:be.
Pleasecontactyoursystemadministrator.
Addcorrecthostkeyin /home/mylogin/.ssh/known_hoststo getridofthis message.
Offendingkeyin /home/mylogin/.ssh/known_hosts:1
RSAhostkeyfor 10.40.1.150 haschangedand youhaverequestedstrictchecking.
Hostkeyverificationfailed.
如果您的 VM 映像安裝了 cloud-init 包(參見),那么它會將主機密鑰輸出到控制臺,如清單 8 所示。
清單 18. 控制臺中的 SSH 密鑰輸出示例
-----BEGINSSHHOSTKEYKEYS-----
ecdsa-sha2-nistp256AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDciNMyzj0osyPOM+
1OyseTWgkzw+M43zp5H2CchG8daRDHel7V3OHETVdI6WofNn
SdBJAwIoisRFPxyroNGiVw= root@my-name
ssh-rsaAAAAB3NzaC1yc2EAAAADAQABAAABAQDU854+fNdcKMZTLCUejMOZllQmmphr6V5Aaz1F2+x2jXql5rqKQ
d5/h6OdFszcp+gdTeVtfgG++/298qodTemVVrvqwjp4eN87iHvhPxH6GDEevAKlEed2ckdAmgvzI9rcOYgR/46G9x
Iea0IdgNjMvN1baj6WPtv+HfcfH/ZV58G306lSJfbz/GVxNTIxW+Wg7ZQCAe6jWgm4oQ+66sco+7Fub24EPue3kO8
jqufqq3mY5+MFlzEHSX5B04ioG5Alw/JuqVx5+7zHt9I2wA3nzsyUdKtCTrw8V4fYEhWDm53WLOpW+8CeYCXuv+yL
7EjwLqhIH/TUuzGQiWmFGvyzroot@my-name
-----END SSHHOSTKEYKEYS-----
清單 19 給出的腳本使用 Server.get_console_output API 方法從控制臺中提取 SSH 主機密鑰,然后更新 ~/.ssh/known_hosts 文件,所以在首次使用 SSH 訪問浮動 IP 地址時,您不會獲得此 SSH 警告。
清單 19. 從控制臺提取 SSH 主機密鑰
importos
importsubprocess
importnovaclient.v1_1.clientas nvclient
fromcredentialsimportget_nova_creds
defget_server(creds, servername):
nova = nvclient.Client(**creds)
return nova.servers.find(name=servername)
defremove_hostkey(ip):
subprocess.call(["ssh-keygen", "-R", ip])
defget_hostkey_from_console(text):
lines = text.split('n')
start = '-----BEGIN SSH HOST KEY KEYS-----r'
end = '-----END SSH HOST KEY KEYS-----r'
start_ind = lines.index(start)
end_ind = lines.index(end)
for i in range(start_ind+1, end_ind):
key = lines[i].rstrip()
if key.startswith('ssh-rsa'):
return key
raiseKeyError("ssh host key not found")
defmain():
server = get_server(get_nova_creds(), "my-server")
netname = "my-network"
(fixed_ip, floating_ip) = server.networks[netname]
# Remove existing key, if any
remove_hostkey(floating_ip)
output = server.get_console_output()
key = get_hostkey_from_console(output)
withopen(os.path.expanduser("~/.ssh/known_hosts"), 'a') as f:
f.write("{0} {1}n".format(floating_ip, key))
if __name__ == '__main__':
main()
OpenStack Image (glance)
OpenStack Image Service ( glance ) 負責管理 Compute Service 所使用的一個 VM 映像目錄。
對 glance 端點執行身份驗證
OpenStack Image ( glance ) Python API 在執行初始身份驗證時與 Compute API 有一些細微的差別。 glance API 依賴于必須從 keystone API 獲取的信息:
- glance 端點 URL
- 一個 keystone 身份驗證令牌
像 nova API 一樣,對于 glance API,您可以傳遞 API 的版本作為參數或直接導入該模塊。清單 20 中的示例展示了如何使用該 API 的第 2 版,對 glance 端點執行身份驗證。
清單 20. 對 glance API 執行身份驗證
importkeystoneclient.v2_0.clientas ksclient
importglanceclient
creds = get_keystone_creds()
keystone = ksclient.Client(**creds)
glance_endpoint = keystone.service_catalog.url_for(service_type='image',
endpoint_type='publicURL')
glance = glanceclient.Client('2',glance_endpoint, token=keystone.auth_token)
清單 21 中的示例直接導入了相關的 glance 模塊。
清單 21. 直接導入 glance 模塊
importkeystoneclient.v2_0.clientas ksclient
importglanceclient.v2.clientas glclient
creds = get_keystone_creds()
keystone = ksclient.Client(**creds)
glance_endpoint = keystone.service_catalog.url_for(service_type='image',
endpoint_type='publicURL')
glance = glclient.Client(glance_endpoint, token=keystone.auth_token)
列出可用映像
使用 Client.images.list 方法列出當前的映像,如清單 22 所示。請注意,此方法會返回一個生成器,其中 nova API 中的 list 方法將會返回列表對象。
清單 22. 獲取一個 VM 映像列表
>>> import keystoneclient.v2_0.clientas ksclient
>>> import glanceclient.v2.clientas glclient
>>> creds = get_keystone_creds()
>>> keystone = ksclient.Client(**creds)
>>> glance_endpoint = keystone.service_catalog.url_for(service_type='image',
... endpoint_type='publicURL')
>>> glance = glclient.Client(glance_endpoint, token=keystone.auth_token)
>>> images = glance.images.list()
>>> images
<generatorobject list at 0x10c8efd70>
>>> images.next()
{u'status': u'active', u'tags': [], u'kernel_id':
u'8ab02091-21ea-434c-9b7b-9b4e2ae49591', u'container_format': u'ami', u'min_ram': 0,
u'ramdisk_id': u'd36267b5-7cae-4dec-b5bc-6d2de5c89c64', u'updated_at':
u'2013-05-28T00:44:21Z', u'visibility': u'public', u'file':
u'/v2/images/cac50405-f4d4-4715-b1f6-7f00ff5030e6/file', u'min_disk': 0,
u'id': u'cac50405-f4d4-4715-b1f6-7f00ff5030e6', u'size': 25165824, u'name':
u'cirros-0.3.1-x86_64-uec', u'checksum': u'f8a2eeee2dc65b3d9b6e63678955bd83',
u'created_at': u'2013-05-28T00:44:21Z', u'disk_format': u'ami', u'protected':
False, u'schema': u'/v2/schemas/image'}
將一個映像上傳到 glance
清單 23 中的示例展示了如何使用 glance API 上傳一個文件。這里需要使用該 API 的第 1 版創建一個映像,因為 Python API 綁定還未實現第 2 版的 create 方法。
清單 23. 將一個映像上傳到 glance
importkeystoneclient.v2_0.clientas ksclient
importglanceclient
creds = get_keystone_creds()
keystone = ksclient.Client(**creds)
glance_endpoint = keystone.service_catalog.url_for(service_type='image',
endpoint_type='publicURL')
glance = glanceclient.Client('1',glance_endpoint, token=keystone.auth_token)
withopen('/tmp/cirros-0.3.0-x86_64-disk.img') as fimage:
glance.images.create(name="cirros", is_public=True, disk_format="qcow2",
container_format="bare", data=fimage)
后續步驟
本文僅簡短概述了 OpenStack Python API 公開的功能。可通過多種方式進一步了解這些 API 的工作原理。
官方 API 文檔
OpenStack 項目維護著所有 OpenStack Python API 的文檔(參見)。所有這些 API 都擁有每個模塊、類和方法的自動生成的文檔。一些 API 的文檔中包含使用示例,而其他文檔沒有。
Introspect the API
了解 API 的一種最佳方式是在一個交互式命令行 Python 解釋器中使用它們。bpython 解釋器是一個增強的 Python 解釋器,會在您鍵入時顯示有效的方法名稱,還會自動顯示一個函數的文檔字符串(參見圖 1)。
圖 1. bpython 的自動幫助顯示界面
查閱 CLI 源代碼
Python 的一個優勢在于它的可讀性,沒有任何方法能夠比閱讀源代碼更好地了解 API。所有包都托管在 openstack 小組中的 github 上。例如,要獲取 nova API 源代碼的副本,可運行以下命令:
gitclone http://github.com/openstack/python-novaclient
因為這些命令行客戶端是使用該 API 實現的,所以每個包都提供了一個示例應用程序。
對于 novaclient API,最有趣的文件包含在 novaclient/v1_1 目錄中,該目錄包含形成此 API 的 Python 類。shell 上的命令行命令被實現為 novaclient/v1_1/shell.py 中的 do_* 方法。例如, nova flavor-list 被實現為 do_flavor_list 方法,該方法最終會調用 Client.flavors.list API 方法。
查閱其他使用 Python API 的應用程序
其他一些應用程序也使用了 OpenStack Python API。OpenStack Dashboard(參見,獲取相關鏈接)完全使用 Python API 與各種 OpenStack 服務進行通信。它是使用 Python API 的應用程序的一個很好的例子。具體來講,您可以查看 openstack_dashboard/api 目錄,看看該儀表板是如何使用 Python API 的。
OpenStack Client(參見)用于將現有客戶端上的功能統一到單個命令行接口中。它使用了來自其他所有項目的 Python API。
Heat 項目是一個設計為使用 OpenStack 的業務流程層,它使用了這些 API。具體來講,請查看 heat/engine/clients.py 文件。
Ansible 是一個基于 Python 的配置管理工具,擁有多個使用 Python API 的 OpenStack 模塊。具體來講,請查看 library/cloud 目錄,其中包含 Ansible OpenStack 模塊。
了解 Python API 的工作原理后,很難想像再返回使用 REST API 或命令行工具構建您的 OpenStack 自動化腳本的情形。
來自:http://python.jobbole.com/87408/