学习CloudStack的API使用

http://docs.cloudstack.apache.org/en/latest/developersguide/dev.html#the-cloudstack-api
http://cloudstack.apache.org/api/apidocs-4.13/

所有CloudStack API请求都以HTTPGET/POST的形式提交,也就是说所有的API请求是一个网络请求

本博客就是将官方文档 抄了一遍。。。

CloudStackAPI的组成(API KEY 认证)

API KEY 和 SECRTE KEY 生成在用户界面

所有CloudStack API请求都以HTTPGET/POST的形式提交,并带有相关的命令和任何参数。

根据CloudStack官方文档,一个完整的API URL请求包含如下。
示例 API GET请求如下

http://localhost:8080/client/api?command=deployVirtualMachine&serviceOfferingId=1&diskOfferingId=1&templateId=2&zoneId=4&apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ&signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D

更易懂的形式

1. http://localhost:8080/client/api
2. ?command=deployVirtualMachine
3. &serviceOfferingId=1
4. &diskOfferingId=1
5. &templateId=2
6. &zoneId=4
7. &apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXqjB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ
8. &signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D
1		CloudStack API URL。希望与之交互的云实例
2		待执行的命令 与APIURL 之间 使用 ? 隔开分离
3-6 	待执行命令的参数 不同段值对(field=value)前面有一个符号字符&
7		唯一标识帐户的用户API KEY
8		为验证执行API命令的用户帐户而创建的签名散列。

其中 2-7 ? 后面内容顺序可以调换 且提交请求是段值对(field=value) field 不区分大小写,但是value区分大小写

分解API URL
  • 基础URL: CloudStack管理服务器基本URL 加上 处理传入请求的APIservlet的路径。
http://localhost:8080/client/api?
  • 命令字符串: 查询字符串由命令、命令参数和标识帐户的API KEY组成。
command=deployVirtualMachine&serviceOfferingId=1&diskOfferingId=1&templateId=2&zoneId=4&apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ
&field=value
段值对(field=value) field 不区分大小写,但是value区分大小写
  • 签名:使用用户 Secret Key 和HMAC SHA-1散列算法组合生成的命令字符串的签名。
&signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D

## Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D散列签名
## 注,改签名生成后是要经过URL编码。
## 大致是将+=/等转换为%2B %3D %2F等
API签名散列生成

API URL 经分解后发现组成部分大都比较简单,比较复杂的是 签名的生成

  1. 对命令字符串中每个字段值(field=value),URL对 值(value)进行URL编码。以便通过HTTP GET发送
为什么强调 是 对value 进行URL编码,因为field的值是CloudStack指定的(一般是字母),不会包含特殊字符串。而value的值却有可能是用户生成的,很有可能存在特殊字符串。
另编码时确保 空格 被编码为 "%20"  而不是 "+"  
URL编码工具应该编码结果是一致的,编码完成可以进行字符串替换将 "+"  替换为 "%20"  
  1. 小写命令字符串 不管是 field 还是 value 然后通过field对段值对进行排序。排序结果大致如下
apikey=mivr6x7u6bn_sdahobpjnejpgest35exq-jb8cg20yi3yaxxcgpyuairmfi_ejtvwz0nukkjbpmy3y2bcikwfq&command=deployvirtualmachine&diskofferingid=1&serviceofferingid=1&templateid=2&zoneid=4
  1. 对已排序的命令字符串,通过 HMAC HSA-1 散列算法(大多数编程语言都有对应操作方法),使用用户SECRET KEY运行它。得到的字节数组使用Base64进行编码(编码格式 UTF-8)。
Lxx1DM40AjcXU%2 FcaiK8RAP0O1hU%3d
## 再次重复 最后得到的 签名也要经过 URL 编码。将+-=/ 等进行编码
  1. 最终 基本URL+API路径+命令字符串+签名的格式重构最终URL,最终URL应该如下所示
http://localhost:8080/client/api?command=deployVirtualMachine&serviceOfferingId=1&diskOfferingId=1&templateId=2&zoneId=4&apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ&signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D

可以通过编程工具 发送 HTTP GET请求或者直接使用某个浏览器输入以上地址即可获取结果。

Python 测试调用API

理论部分完毕,使用 python 交互工具 进行一番测试。

调用一个简单地API 查看 虚拟实例信息 json格式返回

command=listVirtualMachines&response=json
导入所需的 模块
[root@agent ~]# python
Python 2.7.5 (default, Apr  2 2020, 13:16:51) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> import urllib2
>>> import hashlib
>>> import hmac
>>> import base64
urllib:		主要负责进行URL编码
urllib2:	主要负责发送HTTP GET 请求
hashlib hmac base64 三个库主要用来实现 签名 的生成
			其它语言自然也有对应的 HMAC SHA-1 算法 方法实现
定义基础URL 命令字符串和用户的SECRET KEY

请求字符串就是之前分解 API URL中命令字符串 段值对(field=value)之间没有先后顺序,唯一要求value 要经过URL编码以便通过 HTTP GET发送

>>> baseurl = 'http://192.168.199.91:8080/client/api?'
>>> command_str = 'command=listVirtualMachines&response=json&apiKey=9Ssb1m64hHRc9A4XQFsghUBuB1fsz_PJ2wHeHEjQARWtFA_pMu_Trhd7Vyy023OONVYLv0UrZY9EfihDwx-b4A'
>>> secretkey='H91jpAE7LTSMD-ze3eoz8QRtlZtv1EKN-iAQIZwTUdjXu1bvIPDpVZW3E0U_XfkWiaoOyQ9aAw7bMSEhS9jh7A'

方便起见 命令字符串 直接手动输入 field=value 中value值未经过URL编码(可以这么做的原因是本例中value也都是符合URL编码的没有特殊字符,因此编码后结果和编码前一致)。段值对之间无顺序。

官方文档中是将field=value 构造成字典,{field1: value1…}从字典中依次取值,将value进行URL编码后重新变为field=value 格式,段值对之间使用&隔开。这也只是一种方法,目的就是将value编码。
注意千万不要直接将 command_str 整体进行URL编码(因为field=value)中间的=是有意义的,直接URL编码会将该=也编码。

计算签名

需要将命令字符串字符小写,然后field-value 按照字母通过field进行排序。注小写后依然需对value进行编码 然后确保 空格被编译为"%20"而不是"+"

仍然是方便起见,本例中value没有特殊字符,只用排序后整体变为小写即可。

>>> sig_str = 'apiKey=9Ssb1m64hHRc9A4XQFsghUBuB1fsz_PJ2wHeHEjQARWtFA_pMu_Trhd7Vyy023OONVYLv0UrZY9EfihDwx-b4A&command=listVirtualMachines&response=json'.lower()
>>> sig_str
'apikey=9ssb1m64hhrc9a4xqfsghubub1fsz_pj2whehejqarwtfa_pmu_trhd7vyy023oonvylv0urzy9efihdwx-b4a&command=listvirtualmachines&response=json'

>>> sig=hmac.new(secretkey,sig_str,hashlib.sha1)
>>> sig
<hmac.HMAC instance at 0x7f3648ca9cf8>
>>> sig=hmac.new(secretkey,sig_str,hashlib.sha1).digest()
>>> sig
'Kn\x92"\x84\xab\xad\x84.\xeb<\x8c\xcfv\xb1\x84\x86\xd1\xf7R'
>>> sig=base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest())
>>> sig
'S26SIoSrrYQu6zyMz3axhIbR91I=\n'
>>> sig=base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip()
>>> sig
'S26SIoSrrYQu6zyMz3axhIbR91I='
>>> sig=urllib.quote_plus(base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip())
>>> sig
'S26SIoSrrYQu6zyMz3axhIbR91I%3D'

通过HAMC SHA1算法使用SECRTE运行命令字符串,然后使用base64编码生成签名,最后还要进行URL编码的步骤。

urllib.quote_plus() # 就是进行URL编码的方法

一步步分解看的更清楚,最终只用这一步

sig=urllib.quote_plus(base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip())
构建整个字符串 并 执行 http GET
>>> req = baseurl + command_str + '&signature=' + sig
>>> req
'http://192.168.199.91:8080/client/api?command=listVirtualMachines&response=json&apiKey=9Ssb1m64hHRc9A4XQFsghUBuB1fsz_PJ2wHeHEjQARWtFA_pMu_Trhd7Vyy023OONVYLv0UrZY9EfihDwx-b4A&signature=S26SIoSrrYQu6zyMz3axhIbR91I%3D'
>>> res = urllib2.urlopen(req)
>>> res.read()
'{"listvirtualmachinesresponse":{"count":1,"virtualmachine":[{"id":"9ca24c5b-220c-4afb-8adc-a5085c44127d","name":"CentOS6MinimalTest","displayname":"CentOS6MinimalTest","account":"admin","userid":"d86f1bf0-ca2b-11ea-abc8-000c29972b82","username":"admin","domainid":"ab8efe85-ca2b-11ea-abc8-000c29972b82","domain":"ROOT","created":"2020-07-22T13:28:08+0800","state":"Running","haenable":false,"groupid":"ac0e5b62-9f0c-4b7e-9bcc-ba7629a85948","group":"CentOS6","zoneid":"2d372d51-fca5-409a-a98c-d09edb943138","zonename":"Zone1","hostid":"b9c1e868-81bf-4f2c-a28d-8876dafef3d1","hostname":"agent","templateid":"4bb3885b-0067-4c64-9cfd-f01ca2d6120e","templatename":"CentOS6Minimal","templatedisplaytext":"CentOS-6.10-x86_64-minimal","passwordenabled":false,"serviceofferingid":"4ae8a4b4-2eb4-4532-9e23-4a3a013ffd45","serviceofferingname":"Small Instance","diskofferingid":"e96401b6-446d-40af-86a9-c0741e52f440","diskofferingname":"Custom","cpunumber":1,"cpuspeed":500,"memory":512,"cpuused":"6.17%","networkkbsread":294,"networkkbswrite":4,"diskkbsread":1643797,"diskkbswrite":2401101,"memorykbs":524288,"memoryintfreekbs":262144,"memorytargetkbs":262144,"diskioread":84993,"diskiowrite":18263,"guestosid":"c583de96-ca2b-11ea-abc8-000c29972b82","rootdeviceid":0,"rootdevicetype":"ROOT","securitygroup":[{"id":"d86f5621-ca2b-11ea-abc8-000c29972b82","name":"default","description":"Default Security Group","account":"admin","ingressrule":[],"egressrule":[],"tags":[],"virtualmachineids":[]}],"nic":[{"id":"035d37db-2529-477a-918d-1b9eafbecb6a","networkid":"7f9883ab-d15d-45b1-a9c1-0aa9c1f7f230","networkname":"defaultGuestNetwork","netmask":"255.255.255.0","gateway":"192.168.199.1","ipaddress":"192.168.199.40","broadcasturi":"vlan://untagged","traffictype":"Guest","type":"Shared","isdefault":true,"macaddress":"1e:00:ac:00:00:15","secondaryip":[],"extradhcpoption":[]}],"hypervisor":"KVM","instancename":"i-2-5-VM","details":{"keyboard":"us","memoryOvercommitRatio":"2.0","Message.ReservedCapacityFreed.Flag":"false","cpuOvercommitRatio":"2.0"},"affinitygroup":[],"displayvm":true,"isdynamicallyscalable":false,"ostypeid":"c583de96-ca2b-11ea-abc8-000c29972b82","tags":[]}]}}'
urllib2.urlopen() # 就是python中发送http get请求的方法最终返回结果是json

API同步请求和异步请求

上面实=示例只是一个查询虚拟实例的同步请求。返回结果直接就是查询数据。而CloudStack API中有很多是异步请求,如创建实例,会返回一个jobid,根据该jobid再查询相关API即可查询异步请求的进度。

根据 jodid 查询进度 的 API和其他APIURL构造一致。

命令字符串

command=queryAsyncJobResult&response=json&jobid=XXX&apiKey=9Ssb1m64hHRc9A4XQFsghUBuB1fsz_PJ2wHeHEjQARWtFA_pMu_Trhd7Vyy023OONVYLv0UrZY9EfihDwx-b4A

上面的jobid=XXX XXX是执行异步命令返回的jobid。

然后再根据命令字符串 排序 小写 编码 生成签名 发型HTTP GET请求即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值