ZStack HTTP API使用

1. 介绍

ZStack的API原语是JSON格式的消息,可以在各种消息总线上调用,目前ZStack使用的默认消息总线是RabbitMQ。由于这个特性,ZStack的API可以被封装成各种格式。为了方便大家使用,ZStack自带一个HTTP server,用户可以通过HTTP POST发送API JSON文本,该HTTP Server会自动将其转换成API消息实现调用。

我们未来会将ZStack API封装成Restful格式,但当前HTTP POST发送API JSON原语的方式将一直保留

ZStack的命令行工具(zstack-cli)是完全使用HTTP POST方法调用API的,为了方便用户阅读,我们用户手册对所有API的解释都是以zstack-cli为示例,每个cli命令都对应一个API。用户可以在中文用户手册获得每个API的详细解释。

通过zstack-cli的log,用户可以查看所有API调用和返回的具体格式(即HTTP POST的BODY)。

Log路径: /var/log/zstack/zstack-cli

我们建议用户通过tail -f /var/log/zstack/zstack-cli实时查看log,这样你可以在zstack-cli中执行API时实时观测到具体调用和输出。例如:

   
   
   
   
  1. >>LogInByAccount accountName=admin password=password
执行了登录操作后,你会看到LOG中输出类似如下内容: 
   
   
   
   
  1. 2016-02-16 16:29:48,664 DEBUG [apibinding.api] async call[url: http://localhost:8080/zstack/api/, request: {"org.zstack.header.identity.APILogInByAccountMsg": {"password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86", "session": {}, "accountName": "admin"}}]
  2. 2016-02-16 16:29:48,741 DEBUG [apibinding.api] async call[url: http://localhost:8080/zstack/api/, response: {"org.zstack.header.identity.APILogInReply":{"inventory":{"uuid":"083f3518d1bd469fa0ff789fc1a25382","accountUuid":"36c27e8ff05c4780bf6d2fa65700f22e","userUuid":"36c27e8ff05c4780bf6d2fa65700f22e","expiredDate":"Feb 17, 2016 12:29:48 PM","createDate":"Feb 16, 2016 4:29:48 PM"},"success":true}}]

这里http://localhost:8080/zstack/api/是HTTP调用的URL,request后的内容是API调用时HTTP POST的BODY,例如这里LogInByAccount这个API的HTTP POST BODY就是:

   
   
   
   
  1. {
  2. "org.zstack.header.identity.APILogInByAccountMsg": {
  3. "password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86",
  4. "session": {},
  5. "accountName": "admin"
  6. }
  7. }
response后的内容是API返回的HTTP response的BODY,例如这里LogInByAccount的返回是: 
   
   
   
   
  1. {
  2. "org.zstack.header.identity.APILogInReply": {
  3. "inventory": {
  4. "uuid": "083f3518d1bd469fa0ff789fc1a25382",
  5. "accountUuid": "36c27e8ff05c4780bf6d2fa65700f22e",
  6. "userUuid": "36c27e8ff05c4780bf6d2fa65700f22e",
  7. "expiredDate": "Feb 17, 2016 12:29:48 PM",
  8. "createDate": "Feb 16, 2016 4:29:48 PM"
  9. },
  10. "success": true
  11. }
  12. }

2. API的格式

ZStack API的调用和返回都是以JSON原语描述的,格式统一为:只有一个entry的JSON map,该entry的key是API描述符,value是承载具体内容的一个map。API描述符用来唯一标示一个API调用或返回,用户可以把它看做API的名称。在上一节的例子中,API调用的描述符是org.zstack.header.identity.APILogInByAccountMsg,API返回的描述符是org.zstack.header.identity.APILogInReply

3. HTTP返回码

返回码 描述
200 HTTP调用成功。但并不代表API执行成功,API的执行结果由API返回中的success字段决定,true表示成功;false表示失败
其他 含义跟标准的HTTP返回码相同,例如500代表Internal Server Error;404代表No such page

4. HTTP Response Body

API的HTTP response返回的是一个Job结构,调用者需要用该Job的uuid去轮询查询API是否已经完成。API Job的格式如下:

字段 类型 描述
uuid 字符串 JOB UUID,用户可以用该UUID去查询一个API JOB当前的执行状态。当state == Done时,该字段可能为NULL。
state 字符串 JOB状态。包括两种状态:Processing,该JOB还在执行;Done,JOB已经完成
result 字符串 API结果,JSON字符串。当state = Processing时,该字段为NULL
createdDate 字符串 JOB创建时间
finishedDate 字符串 JOB完成时间

state == Processing的Job例子:

   
   
   
   
  1. {
  2. "uuid": "fee83ed8529340cd8528b3b408dc16b0",
  3. "state": "Processing",
  4. "createdDate": "Feb 16, 2016 5:01:11 PM"
  5. }

state == Done的Job例子:

   
   
   
   
  1. {
  2. "uuid": "fee83ed8529340cd8528b3b408dc16b0",
  3. "state": "Done",
  4. "createdDate": "Feb 16, 2016 5:01:11 PM",
  5. "finishedDate": "Feb 16, 2016 5:01:12 PM",
  6. "result": "{"org.zstack.header.zone.APICreateZoneEvent":{"inventory":{"uuid":"f1ed8f95163c4b6c88a8c0673b7913b7","name":"xx","state":"Enabled","type":"zstack","createDate":"Feb 16, 2016 5:01:12 PM","lastOpDate":"Feb 16, 2016 5:01:12 PM"},"success":true}}"
  7. }

4.1 查询API JOB的状态

当调用一个API后,HTTP response返回一个Job结构,其中包含有该Job的uuid,用户需要通过该uuid去查询该Job的状态。

查询的方法是向http://locahost:8080/api/result/{job uuid}发送一个HTTP Get请求,例如: 
   
   
   
   
  1. curl http://localhost:8080/zstack/api/result/fee83ed8529340cd8528b3b408dc16b0

其HTTP response返回一个Job结构,用户可以通过判断Job的state字段来判断Job是否完成,从而决定是否需要继续轮询Job的状态

5. API的调用流程

ZStack API的调用的标准流程是:

  1. 调用LogInByAccount,获得一个Session UUID,作为后续API调用的token
  2. 调用API 1
  3. 调用API 2
  4. ... ...
  5. 调用API N
  6. 调用LogOut


5.1 登录

在调用其他API前,用户需要首先调用LogInByAccount以获得一个session UUID,以此作为后续API调用的token。该API的描述符为:org.zstack.header.identity.APILogInByAccountMsg,包含以下字段:


字段 描述
accountName 用户名。例如admin|
password 密码。zstack不对密码进行任何处理,只是单纯将其与数据库中存储的密码数据进行字符串比对。我们建议在调用CreateAccount这样的API时,密码使用sha512加密。

默认用户名密码:ZStack默认的用户名是admin,其密码明文为password,sha512哈希后的结果为

b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86


所以该API的JSON描述类似于: 
   
   
   
   
  1. {
  2. "org.zstack.header.identity.APILogInByAccountMsg": {
  3. "password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86",
  4. "accountName": "admin"
  5. }
  6. }

用curl调用该API:

   
   
   
   
  1. curl -H "Content-Type: application/json" -d '{"org.zstack.header.identity.APILogInByAccountMsg": {"password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86", "accountName": "admin"}}' http://localhost:8080/zstack/api

返回的Job结构为:

  
  
  
  
  1. {
  2. "state": "Done",
  3. "createdDate": "Feb 16, 2016 7:15:01 PM",
  4. "finishedDate": "Feb 16, 2016 7:15:01 PM",
  5. "result": "{"org.zstack.header.identity.APILogInReply":{"inventory":{"uuid":"9eba9754f8c2470cbb377088e61c4da2","accountUuid":"36c27e8ff05c4780bf6d2fa65700f22e","userUuid":"36c27e8ff05c4780bf6d2fa65700f22e","expiredDate":"Feb 17, 2016 3:15:01 PM","createDate":"Feb 16, 2016 7:15:01 PM"},"success":true}}"
  6. }


其result字段包含的是API的结果,JSON表达为:

  
  
  
  
  1. {
  2. "org.zstack.header.identity.APILogInReply": {
  3. "inventory": {
  4. "uuid": "9eba9754f8c2470cbb377088e61c4da2",
  5. "accountUuid": "36c27e8ff05c4780bf6d2fa65700f22e",
  6. "userUuid": "36c27e8ff05c4780bf6d2fa65700f22e",
  7. "expiredDate": "Feb 17, 2016 3:15:01 PM",
  8. "createDate": "Feb 16, 2016 7:15:01 PM"
  9. },
  10. "success": true
  11. }
  12. }

其中uuid字段即是我们需要的Session UUID。

5.2 普通API调用

除登录(LogInByAccount)、登出(LogOut)等少数API外,剩下的都是普通API,在调用时需要传入LogIn拿到的Session UUID,其JSON原语为:

   
   
   
   
  1. {
  2. "API描述符": {
  3. "session": {
  4. "uuid": "LogIn时拿到的session UUID"
  5. },
  6. "API字段名1" ...,
  7. "API字段名2”: ...
  8. }
  9. }
再次提醒:你可以通过查看/var/log/zstack/zstack-cli得到你在zstack-cli执行的每个API的描述符、request和response。

5.3 登出

当你执行完需要的API后,应该调用LogOut API退出当前session。该API的描述符是org.zstack.header.identity.APILogOutMsg,其JSON原语是:


   
   
   
   
  1. {
  2. "org.zstack.header.identity.APILogOutMsg": {
  3. "sessionUuid": "你要LogOut的Session UUID"
  4. }
  5. }
用curl调用: 
   
   
   
   
  1. curl -H "Content-Type: application/json" -d '{"org.zstack.header.identity.APILogOutMsg": {"sessionUuid": "083f3518d1bd469fa0ff789fc1a25382"}}' http://localhost:8080/zstack/api

6. 创建一个Zone的Curl示例

这里我们将用创建Zone这个例子,展示如何用Curl手动调用ZStack的API。

6.1 登录

调用:

   
   
   
   
  1. curl -H "Content-Type: application/json" -d '{"org.zstack.header.identity.APILogInByAccountMsg": {"password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86", "accountName": "admin"}}' http://localhost:8080/zstack/api

返回:

   
   
   
   
  1. {"state":"Done","createdDate":"Feb 16, 2016 7:53:14 PM","finishedDate":"Feb 16, 2016 7:53:14 PM","result":"{"org.zstack.header.identity.APILogInReply":{"inventory":{"uuid":"2f68cf0a5783400694bd8efdd536a2a8","accountUuid":"36c27e8ff05c4780bf6d2fa65700f22e","userUuid":"36c27e8ff05c4780bf6d2fa65700f22e","expiredDate":"Feb 17, 2016 3:53:14 PM","createDate":"Feb 16, 2016 7:53:14 PM"},"success":true}}"}

6.2 创建一个Zone

调用: 
   
   
   
   
  1. curl -H "Content-Type: application/json" -d '{"org.zstack.header.zone.APICreateZoneMsg": {"session": {"uuid": "2f68cf0a5783400694bd8efdd536a2a8"}, "name": "zone1"}}' http://localhost:8080/zstack/api
返回:
   
   
   
   
  1. {"uuid":"2252332b14fb42599558577cb24fa168","state":"Processing","createdDate":"Feb 16, 2016 7:55:34 PM"}


这里我们得到了一个Job UUID 2252332b14fb42599558577cb24fa168,通过它我们可以轮询创建Zone这个API的结果。

轮询结果:


   
   
   
   
  1. curl http://localhost:8080/zstack/api/result/2252332b14fb42599558577cb24fa168

返回:

   
   
   
   
  1. {"uuid":"2252332b14fb42599558577cb24fa168","state":"Done","createdDate":"Feb 16, 2016 7:55:34 PM","finishedDate":"Feb 16, 2016 7:55:34 PM","result":"{"org.zstack.header.zone.APICreateZoneEvent":{"inventory":{"uuid":"dd625f8fb2074f4fa1c0870ef76bb24a","name":"zone1","state":"Enabled","type":"zstack","createDate":"Feb 16, 2016 7:55:34 PM","lastOpDate":"Feb 16, 2016 7:55:34 PM"},"success":true}}"}

这里我们看到该API已经完成了,state == Done。API的结果以一个JSON字符串的形式保存在result字段中。可以看到该API调用成功,因为success字段为true

6.3 登出

调用:

   
   
   
   
  1. curl -H "Content-Type: application/json" -d '{"org.zstack.header.identity.APILogOutMsg": {"sessionUuid": "2252332b14fb42599558577cb24fa168"}}' http://localhost:8080/zstack/api

返回:

   
   
   
   
  1. {"state":"Done","createdDate":"Feb 16, 2016 8:04:36 PM","finishedDate":"Feb 16, 2016 8:04:37 PM","result":"{"org.zstack.header.identity.APILogOutReply":{"success":true}}"}

7. 创建一个Zone的Python示例

你可以点击这里获得完整代码。

   
   
   
   
  1. import httplib
  2. import json
  3. import time
  4.  
  5. # return a dict containing API return value
  6. def api_call(session_uuid, api_id, api_content):
  7. conn = httplib.HTTPConnection("localhost", 8080)
  8. headers = {"Content-Type": "application/json"}
  9.  
  10. if session_uuid:
  11. api_content["session"] = {"uuid": session_uuid}
  12.  
  13. api_body = {api_id: api_content}
  14.  
  15. conn.request("POST", "/zstack/api", json.dumps(api_body))
  16. response = conn.getresponse()
  17.  
  18. if response.status != 200:
  19. raise Exception("failed to make an API call, %s, %s" % (response.status, response.reason))
  20.  
  21. rsp_body = response.read()
  22.  
  23. rsp = json.loads(rsp_body)
  24.  
  25. if rsp["state"] == "Done":
  26. return json.loads(rsp["result"])
  27.  
  28. job_uuid = rsp["uuid"]
  29. def query_until_done():
  30. conn.request("GET", "/zstack/api/result/%s" % job_uuid)
  31. response = conn.getresponse()
  32. if response.status != 200:
  33. raise Exception("failed to query API result, %s, %s" % (response.status, response.reason))
  34.  
  35. rsp_body = response.read()
  36. rsp = json.loads(rsp_body)
  37. if rsp["state"] == "Done":
  38. return json.loads(rsp["result"])
  39.  
  40. time.sleep(1)
  41. print "Job[uuid:%s] is still in processing" % job_uuid
  42. return query_until_done()
  43.  
  44. return query_until_done()
  45.  
  46.  
  47.  
  48. def error_if_fail(rsp):
  49. success = rsp.values()[0]["success"]
  50. if not success:
  51. error = rsp.values()[0]["error"]
  52. raise Exception("failed to login, %s" % json.dumps(error))
  53.  
  54. def login():
  55. content = {
  56. "accountName": "admin",
  57. "password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86"
  58. }
  59. rsp = api_call(None, "org.zstack.header.identity.APILogInByAccountMsg", content)
  60. error_if_fail(rsp)
  61.  
  62. session_uuid = rsp.values()[0]["inventory"]["uuid"]
  63.  
  64. print "successfully login, session uuid is: %s" % session_uuid
  65. return session_uuid
  66.  
  67.  
  68. def create_zone(session_uuid):
  69. content = {"name": "zone1"}
  70.  
  71. rsp = api_call(session_uuid, "org.zstack.header.zone.APICreateZoneMsg", content)
  72. error_if_fail(rsp)
  73.  
  74. print "successfully created zone1"
  75.  
  76.  
  77. def logout(session_uuid):
  78. content = {"sessionUuid": session_uuid}
  79. rsp = api_call(None, "org.zstack.header.identity.APILogOutMsg", content)
  80. error_if_fail(rsp)
  81.  
  82. print "successfully logout"
  83. session_uuid = login()
  84. create_zone(session_uuid)
  85. logout(session_uuid)

你可能感兴趣的:(server,IaaS,私有云)