API使用规范
ZStack ZSphere提供RESTful API。您可以使用支持HTTP的编程语言或工具访问API端点,完成身份认证、资源查询和资源操作。
本章介绍API请求、身份认证、响应与错误处理、异步API、查询API、ZQL以及批量API返回的通用规则。具体API的请求参数和返回字段请参见对应API正文。
快速入门
调用ZStack ZSphere API通常包括以下步骤:
- 确定管理节点地址、API端点和目标API的HTTP方法。
- 通过登录API获取Session UUID,或准备AccessKey。
- 按照具体API正文传递URL、Query String或HTTP Body参数。
- 发送请求,并根据HTTP状态码处理同步结果、异步轮询地址或错误信息。
- 使用Session认证时,在调用结束后执行LogOut释放Session。
以下示例使用Session查询虚拟机。示例中的地址和Session UUID均为占位符:
GET http://MANAGEMENT_NODE_IP:8080/zstack/v1/vm-instances?limit=10
Authorization: OAuth SESSION_UUID
查询成功时,HTTP状态码为200,返回Body中包含符合条件的资源清单。
API请求规范
调用API时,需要按照具体API正文指定的端点、HTTP方法、参数位置和HTTP Headers构造请求。
API端点与请求地址
REST API请求地址由协议、管理节点地址、端口、API上下文路径和资源路径组成:
http://MANAGEMENT_NODE_IP:8080/zstack/v1/RESOURCE_PATH
例如,查询虚拟机的资源路径为/v1/vm-instances:
GET http://MANAGEMENT_NODE_IP:8080/zstack/v1/vm-instances
HTTP方法与API操作
API使用以下HTTP方法:
| 方法 | 用途 |
|---|---|
| GET | 查询资源或获取资源信息。Query类和Get类API使用该方法。 |
| POST | 创建资源。 |
| PUT | 修改资源,或执行启动、停止等类RPC操作。类RPC操作通常访问资源的actions子路径。 |
| DELETE | 删除资源。 |
例如,启动虚拟机使用PUT方法,操作名和参数包含在HTTP Body中:
PUT zstack/v1/vm-instances/VM_UUID/actions
{
"startVmInstance": {}
}
每个API使用的HTTP方法、URL和Body字段以对应API正文为准。
参数传递
API支持通过URL、Query String和HTTP Body传递参数。具体方式由API定义,不同方式可以组合使用。
URL参数
对指定资源执行操作时,资源UUID通常编码在URL路径中:
GET zstack/v1/vm-instances/VM_UUID
Query String参数
GET请求通过Query String传递查询条件、分页和字段选择等参数。多个参数使用&连接,参数值应进行URL编码。
GET zstack/v1/vm-instances?q=state=Running&limit=20
HTTP Body参数
POST和PUT请求通常通过JSON Body传递参数。Body的顶层字段名和参数结构以API正文为准:
{
"params": {
"name": "vm1",
"description": "example"
}
}
HTTP Headers
API使用以下认证和异步任务相关HTTP Headers:
| Header | 说明 |
|---|---|
| Authorization | Session认证格式为OAuth SESSION_UUID;AccessKey认证格式为ZStack ACCESS_KEY_ID:SIGNATURE。 |
| Date | AccessKey认证使用的请求时间。该值必须与计算签名时使用的时间完全一致。 |
| X-Job-UUID | 为异步API任务指定UUID。应使用去除连字符的UUID v4字符串;未指定时由服务端生成。 |
| X-Web-Hook | 指定接收异步API结果的回调URL。 |
| X-Job-Success | Webhook回调中指示异步API是否执行成功,值为true或false。 |
身份认证
除登录等不要求认证的API外,调用API时需要使用Session或AccessKey完成身份认证。
Session认证
调用LogInByAccount或其他登录API成功后,返回的Session清单中包含Session UUID。后续请求通过Authorization Header传递该UUID:
Authorization: OAuth SESSION_UUID
Session具有有效期。调用结束后,应调用LogOut释放不再使用的Session,避免持续创建Session并占用系统配额。
AccessKey认证
AccessKey由AccessKey ID和AccessKey Secret组成。调用方使用AccessKey Secret对请求关键信息签名,服务端根据签名验证调用者身份。AccessKey Secret只在创建时返回,应由调用方妥善保存。
通过SDK使用AccessKey
Java SDK和Python SDK的Action对象均提供accessKeyId和accessKeySecret字段:
Java SDK:
QueryVmInstanceAction action = new QueryVmInstanceAction();
action.limit = 1;
action.accessKeyId = "ACCESS_KEY_ID";
action.accessKeySecret = "ACCESS_KEY_SECRET";
QueryVmInstanceAction.Result result = action.call();
Python SDK:
action = QueryVmInstanceAction()
action.conditions = []
action.limit = 1
action.accessKeyId = 'ACCESS_KEY_ID'
action.accessKeySecret = 'ACCESS_KEY_SECRET'
result = action.call()
SDK负责生成Date和Authorization Headers。不要同时为同一Action设置Session和AccessKey。
通过REST API使用AccessKey
直接调用REST API时,按照以下规则生成签名:
- 生成请求时间
DATE。时间格式应符合HTTP日期要求,并与签名计算使用的值完全一致。 - 构造待签名字符串:
HTTP_METHOD + "\n" + DATE + "\n" + API_URIAPI_URI以/v1开头,不包含协议、管理节点地址、端口、API上下文路径和Query String。例如:/v1/vm-instances。 - 以AccessKey Secret为密钥,对待签名字符串计算HMAC-SHA1,并对摘要执行Base64编码,得到
SIGNATURE。 - 发送请求时同时设置:
Date: DATE Authorization: ZStack ACCESS_KEY_ID:SIGNATURE
例如:
GET http://MANAGEMENT_NODE_IP:8080/zstack/v1/vm-instances?limit=1
Date: DATE
Authorization: ZStack ACCESS_KEY_ID:SIGNATURE
API响应与错误处理
调用方应同时检查HTTP状态码和返回Body。HTTP请求被接受不一定表示异步任务或批量任务中的每个子任务均执行成功。
API响应
同步API完成后通常返回200,结果包含在JSON Body中。资源类API常使用inventory返回单个资源,查询类API常使用inventories返回资源列表,并可包含total。
异步API请求被接受后返回202,Body中包含location轮询地址和apiTimeout超时时间。调用方需要轮询该地址或使用Webhook获取最终结果。
字段结构和含义以具体API正文中的返回示例与字段表为准。
HTTP状态码
| 状态码 | 说明 |
|---|---|
| 200 | API执行成功,Body中包含结果。 |
| 202 | 异步API请求已被接受,需要轮询或等待Webhook回调。 |
| 400 | 缺少必要参数或参数不合法,具体信息见Response Body。 |
| 404 | URL不存在;访问异步轮询地址时也可能表示轮询地址已过期。 |
| 405 | HTTP方法与API定义不匹配。 |
| 500 | RESTful API服务发生内部错误。 |
| 503 | API所执行的操作失败,错误详情见Response Body。 |
错误处理
请求失败时,Response Body中的error对象用于描述错误。调用方应至少记录并处理以下字段:
code:可供程序判断错误类型的错误码。description:错误的概要说明。details:与本次失败相关的详细信息。
部分错误还可能包含cause、causes、elaboration或其他扩展字段。程序不应只依据HTTP状态码判断业务操作成功;异步API还需要检查最终轮询或Webhook结果,批量API还需要逐项检查子任务结果。
异步API
异步API先接受请求,再通过轮询或Webhook返回最终结果。调用方需要保存任务标识,并根据最终结果判断操作是否成功。
同步与异步API
所有GET API均为同步API,HTTP Response直接包含API结果。除登录相关API外,不使用GET方法的API通常为异步API。
异步请求被接受时返回202,例如:
Status Code: 202
{
"apiTimeout": 1800000,
"location": "http://MANAGEMENT_NODE_IP:8080/zstack/v1/api-jobs/JOB_UUID"
}
apiTimeout的单位为毫秒,location是查询最终结果的地址。
轮询API结果
对异步API返回的location地址周期性发送GET请求:
GET POLLING_LOCATION
Authorization: OAuth SESSION_UUID
- 202:API仍在处理,继续轮询。
- 200:API执行成功,Body中包含最终结果。
- 503:API执行失败,Body中包含错误信息。
- 404:轮询地址错误或已过期。
轮询间隔和总等待时间应结合API返回的apiTimeout以及调用方的超时策略设置,避免无间隔的连续请求。
Webhook
Webhook用于将异步API的最终结果主动推送给调用方。发起异步请求时指定以下Headers:
X-Job-UUID: JOB_UUID
X-Web-Hook: https://CALLBACK_ENDPOINT/api-result
服务端仍返回202和轮询地址,但调用方可以等待回调。任务完成后,服务端向回调地址发送POST请求:
POST https://CALLBACK_ENDPOINT/api-result
X-Job-Success: true
X-Job-UUID: JOB_UUID
X-Job-Success表示API执行是否成功,X-Job-UUID用于将回调结果与原请求关联。
查询API
Query类API使用GET方法查询资源,支持组合查询条件、跨资源查询、排序、字段选择和分页。省略查询条件时返回资源列表,返回数量受limit限制。
| 参数 | 类型 | 说明 |
|---|---|---|
| q | List | 查询条件。可重复传递,多个条件之间为与关系。 |
| limit | Integer | 最多返回的记录数,默认值为1000。 |
| start | Integer | 起始记录位置,与limit配合实现分页。 |
| count | Boolean | 设置为true时只返回满足条件的记录数。 |
| groupBy | String | 按指定字段分组。 |
| replyWithCount | Boolean | 设置为true时在资源列表之外返回满足条件的记录总数。 |
| sort | String | 使用+字段名升序排列,使用-字段名降序排列。 |
| fields | List | 指定返回的资源原生字段。 |
查询条件
查询条件由字段名、查询操作符和匹配值组成,三者之间不能包含空格。例如:
GET zstack/v1/vm-instances?q=name=vm1&q=state=Running
多个q参数之间为与关系。支持以下操作符:
| 操作符 | 含义 | 示例 |
|---|---|---|
| = | 等于 | state=Running |
| != | 不等于 | state!=Stopped |
| >、<、>=、<= | 数值或可比较字段的范围判断 | cpuNum>=8 |
| ?= | 属于集合 | uuid?=UUID_1,UUID_2 |
| !?= | 不属于集合 | name!?=vm1,vm2 |
| ~= | 字符串模糊匹配;%匹配多个字符,_匹配一个字符 | name~=web% |
| !~= | 字符串模糊不匹配 | name!~=test% |
| =null | 字段为空 | hostUuid=null |
| !=null | 字段不为空 | hostUuid!=null |
跨资源查询
使用句点.连接资源关系和字段,可以按照关联资源的字段进行查询。
例如,查询网卡IP地址为192.168.10.100的虚拟机:
GET zstack/v1/vm-instances?q=vmNics.ip=192.168.10.100
查询运行在指定主机上的虚拟机:
GET zstack/v1/vm-instances?q=host.managementIp=192.168.10.10
资源关系可以继续向下连接,例如vmNics.eip.ip。可使用CLI对Query API执行Tab自动补全,查看当前资源支持的关联资源和字段。
排序与字段选择
使用sort参数对结果排序。字段名前的+表示升序,-表示降序:
GET zstack/v1/vm-instances?sort=+name
GET zstack/v1/vm-instances?sort=-createDate
使用一个或多个fields参数选择返回字段:
GET zstack/v1/vm-instances?fields=uuid&fields=name
此时每条记录仅返回uuid和name。
fields选取。用户标签、系统标签和跨资源字段不能作为fields值。分页查询
start、limit和replyWithCount配合使用可实现分页:
start:本页第一条记录的位置。limit:本页最多返回的记录数。replyWithCount=true:在返回结果中包含满足查询条件的记录总数。
GET zstack/v1/vm-instances?start=0&limit=100&replyWithCount=true
如果返回的total为1000,则下一页将start设置为100,并保持相同的limit和查询条件。分页过程中如需稳定顺序,应同时指定sort。
获取可查询字段
查询资源支持的字段和关联资源较多,可使用CLI自动补全查看当前环境实际支持的查询路径。
- 执行zstack-cli进入CLI。
- 输入Query API名和一个空格,例如
QueryVmInstance。 - 按Tab键查看资源原生字段、通用查询参数和可跨资源查询的关系。
- 输入关联资源名及句点后再次按Tab,例如
QueryVmInstance vmNics.,查看网卡字段及下一层关联资源。
__systemTag__和__userTag__可作为特殊查询条件;其他无句点字段通常是资源原生字段。是否支持某个查询路径以当前版本CLI返回的补全结果为准。
ZQL
ZQL (ZStack Query Language) 是ZStack ZSphere提供用于查询云平台资源和服务的专属语言,提供类似SQL语言的查询语法,适用于较为复杂的查询需求场景。
ZQL语句结构
- query关键字起始的查询语句结构:
query queryTargetWithFunction (WHERE condition+)? restrictBy? returnWith? groupBy? orderBy? limit? offset? filterBy? namedAs? - count关键字起始的查询语句结构:
count queryTargetWithFunction (WHERE condition+)? restrictBy? groupBy? orderBy? limit? offset? namedAs? - sum关键字起始的查询语句结构:
sum queryTarget by sumByValue (WHERE condition+)? orderBy? limit? offset? namedAs? -
Note: ?表示对应从句为选填项。
ZQL语法说明
- 查询关键字:
- query:查询并返回资源的inventory,类似于SQL的
select *。例如,query vminstance类似select * from VmInstanceVO。 - count:查询并返回满足查询条件的资源数目, 类似SQL的
select count(*)。例如,count vminstance类似select count(*) from VmInstanceVO。 - sum:查询并返回指定字段的和,类似于SQL的
select sum(inv.cpuNum)。例如,sum instanceoffering.cpuNum类似select sum(cpuNum) from InstanceOfferingVO。
- query:查询并返回资源的inventory,类似于SQL的
- 查询字段:
- querytarget:查询的目标资源信息。资源命名方式为从资源名中去掉VO后缀,且需全小写。例如,若资源为VmInstanceVO,querytarget的资源名称为vminstance。querytarget只支持查询资源的某些字段。例如,
query vminstance.uuid,name为查询虚拟机UUID和名称。该语句类似SQL的select uuid,name from VmInstanceVO。 - function:处理资源字段的函数。querytarget
支持直接指定字段和使用函数处理后的字段。当前,query和count关键字支持函数处理,子查询暂不支持函数处理。 ZStack ZSphere支持的函数为
distinct。例如,query distinct(vminstance.name)为查询并返回不同的虚拟机名称。该语句类似于select distinct name from VmInstanceVO或者select distinct(name) from VmInstanceVO。
- querytarget:查询的目标资源信息。资源命名方式为从资源名中去掉VO后缀,且需全小写。例如,若资源为VmInstanceVO,querytarget的资源名称为vminstance。querytarget只支持查询资源的某些字段。例如,
- 查询从句:
- where:与SQL中where从句类似,用于指定查询条件。查询条件的值若为字符串,需用单引号标识。
- 与Query API类似,where从句指定的查询条件可以是本资源的字段,也可以是跨表的Join查询条件。例如:
query vminstance where name='webvm'中,name字段为vminstance本身的字段。query vminstance where vmNics.ip='192.168.0.100'中,vmNics.ip为与VmNicVO表自动Join查询后的字段。
- where从句支持AND/OR逻辑,并支持通过括号做逻辑嵌套。例如:
query vminstance where (name = 'webvm' or cpuNum > 10) and description is not null
- 与Query API类似,where从句指定的查询条件可以是本资源的字段,也可以是跨表的Join查询条件。例如:
- sub query:where从句指定的查询条件支持子查询(sub
query),例如:
需注意:query vminstance where hostUuid in (query host.uuid where state = 'Disconnected') and state = 'Running'- sub
query从句中的querytarget只支持选择一个字段,例如
host.uuid。若未选择字段或选择多个字段均会报错。sub query中的where从句与普通query语句中的where从句一样。 - sub query不支持restrict by、return with从句,也不支持limit、order by、和 offset关键字。
- sub
query从句中的querytarget只支持选择一个字段,例如
- restrict by:用于解决资源关联查询的问题,例如,
query eip restrict by (zone.uuid = '28818693f3924d92af2b19b2407317ff')表示查询UUID为28818693f3924d92af2b19b2407317ff的数据中心(Zone)下的弹性IP(EIP)。由于弹性IP资源中无字段与Zone关联,此时可通过指定restrict by从句进行查询。- restrict by指定的条件名与querytarget中的带字段查询格式相同,均为资源名.字段名,例如zone.uuid。
- restrict
by从句中的条件只支持AND逻辑关系,例如:
restrict by (zone.uuid = '28818693f3924d92af2b19b2407317ff', zone.name like '%east-%')
- return
with:用于返回附带数据。目前支持两种附带数据:
total和zwatch。total用于指定满足查询条件的数据数量。例如,对于query vminstance where cpuNum > 8 return with (total)语句,查询结果会返回total字段值。zwatch用于指定返回满足查询条件的监控数据。return with从句中指定zwatch子句后,在执行数据库查询时会同时执行zwatch查询。其工作原理是:l- 先执行where子句中的数据库查询条件,获取符合查询条件数据。
- 将where子句中查询返回的数据作为输入条件注入zwatch查询。
cpuNum > 8条件的VM,然后将VM的uuid合并成一个zwatch的label,注入到之后的zwatch查询条件中:query vminstance where cpuNum > 8 return with (zwatch{metricName='CPUUsedUtilization',offsetAheadOfCurrentTime=3600,period=10,labels='CPUNum=10',labels='CPUNum=100', functions=limit(limit=10), functions=top(num=2)})zwatch子句以zwatch关键字打头,查询条件置于花括号中{}。查询条件即为GetMetricData API的各个字段。其中参数中无namespace字段,该字段由querytarget指定的资源确定,例如vminstance就代表ZStack/VM。private String metricName; private Long startTime; private Long endTime; private Long offsetAheadOfCurrentTime; private Integer period; private List<String> labels; private List<String> functions;- zwatch子句一般以query后的对象的主键作为查询参数传递到后面的GetMetricData查询中。若要使用非主键的字段进行zwatch查询,可在对应的子句中增加feildIndex参数。fieldIndex=0表示用query后的第一个字段。例如:
query faulttolerancevmgroup.primaryVmInstanceUuid return with (zwatch{resultName='cpuAverageUsedUtilization',metricName='CPUAverageUsedUtilization',offsetAheadOfCurrentTime=0,period=10,fieldIndex=0}) - 字符串型的参数需使用单引号标记。对于labels和functions两个list类型的参数,采用多个输入,在列表中的顺序按参数出现的先后顺序确定,参数之间用逗号(,)分隔。例如:
labels='CPUNum=10', labels='CPUNum=8' - zwatch子句查询返回的监控数据数目与满足where从句的数据库记录数据数目可能不一样。例如在以下ZQL语句中,满足cpuNum
>
8的VM可能有100个,但zwatch子句用了top(num=2)函数,则返回的监控数据只有2个:
query vminstance.name where cpuNum > 8 return with (zwatch{metricName='CPUUsedUtilization',offsetAheadOfCurrentTime=3600,period=10,labels='CPUNum=10',labels='CPUNum=100',functions=limit(limit=10), functions=top(num=2)}) - 若只关注监控数据,ZQL的querytarget应该指定字段而不是指定资源本身。例如在以下ZQL语句中,返回的数据中只包含vm的名称和监控数据,这样可以大大减少API传输的数据量:
query vminstance.name where cpuNum > 8 return with (zwatch{metricName='CPUUsedUtilization',offsetAheadOfCurrentTime=3600,period=10,labels='CPUNum=10',labels='CPUNum=100',functions=limit(limit=10), functions=top(num=2)})
return with从句支持多个zwatch子句。在使用多子句时,需要通过resultName指定返回数据在ZQL返回对象中reurnWith对象中的名字。例如:query vminstance.name where cpuNum > 8 return with (zwatch{resultName='zwatch1',metricName='CPUUsedUtilization',offsetAheadOfCurrentTime=3600,period=10,labels='CPUNum=10',labels='CPUNum=100', functions=limit(limit=10), functions=top(num=2)}, zwatch{resultName='zwatch2',metricName='CPUUsedUtilization',offsetAheadOfCurrentTime=3600,period=10,labels='CPUNum=10',labels='CPUNum=100', functions=limit(limit=10), functions=top(num=2)})其中用两个子句分别指定了resultName='zwatch1',resultName='zwatch2',则对应的返回值以zwtach1和zwatch2命名:"returnWith": { "zwatch1": [{ "value": 105.0, "time": 7.0, "labels": { "VMUuid": "bdbc971d1de74a91b8f3f0c7c9f5babe" } }, { "value": 101.0, "time": 1.0, "labels": { "VMUuid": "bdbc971d1de74a91b8f3f0c7c9f5babe" } }], "zwatch2": [{ "value": 105.0, "time": 7.0, "labels": { "VMUuid": "bdbc971d1de74a91b8f3f0c7c9f5babe" } }, { "value": 101.0, "time": 1.0, "labels": { "VMUuid": "bdbc971d1de74a91b8f3f0c7c9f5babe" } }] }
- group by:与SQL的group by从句类似,使用资源的字段对结果进行分组。group
by从句仅支持query和count查询,sum查询的by字段与group by字段同义。例如:
query vminstance group by name类似于 SQL中的select * from VmInstanceVO group by name。count vminstance where cpuNum > 8 group by name,memorySize类似于SQL中的select count(*) where cpuNum。
query group by返回的结果形式和普通 query 相同,例如:query vminstance.name return with (total) group by zoneUuid语句的返回结果为:{ "results": [ { "inventories": [ { "name": "win2016-new" } ], "total": 24 } ], "success": true }Note: total字段值与group by后的数量并不相同。count group by的返回结果和普通count有所不同,例如count vminstance group by imageUuid order by groupCount asc语句的返回结果为:
其中{ "results": [ { "inventoryCounts": [ [ { "imageUuid": "20d8593c94934b4596af7109a1609811" }, 1 ], [ { "imageUuid": "4eabdabb64844f8eb2ae5d1aa2c44d7a" }, 2 ] ], "total": 3 } ], "success": true }inventoryCounts是一个拥有复杂键(group by指定字段的对象)的有序 map 类型,经 json 转化成这种 jsonArray 的形式。若执行count vminstance group by imageUuid offset 2语句,返回结果为
其中:{ "results": [ { "total": 3 } ], "success": true }- 由于offset条件下并无查询结果,inventoryCounts 字段为null 。
- total字段仍然是分组前的total结果。
- order by :类似SQL的order
by从句,可以用资源的字段对返回结果排序,例如:
或query vminstance orderby cpuNum ascquery vminstance orderby cpuNum desc支持对 count group by 后的结果进行排序,例如:count vminstance groupby imageUuid orderby groupCount asc同时支持对 sum 后的结果进行排序,例如:sum VolumeSnapshot.size by volumeUuid orderby size asc - limit
:类似SQL的limit从句,限定返回数据数目,例如:
query vminstance limit 100 - offset
:类似SQL的offset从句,跟limit从句一起使用实现翻页功能,例如:
query vminstance limit 100 offset 10
- where:与SQL中where从句类似,用于指定查询条件。查询条件的值若为字符串,需用单引号标识。
select sum(xxx) ... group by
yyy的求和功能。例如以下查询语句对vminstance的cpuNum,
memorySize两个字段分别进行求和,并通uuid字段对数据进行分组。sum vminstance.cpuNum,memorySize by uuid where cpuNum >0该语句等同于以下SQL语句:select sum(vm.cpuNum),sum(vm.memorySize) from VmInstanceVO vm where vm.cpuNum > 0返回结果为:{
"results": [{
"inventories": [
["7dba128454014abc8a69e739f1c4e2ad", 2, 536870912],
["e889cbf61cf6434f875e80e3b1c5a92d", 4, 8589934592]
]
}]
}返回结果的每个元素为一个数组:第一个元素总是
by 关键字指定的group
by字段,通过该字段可以分辨后面求和值所对应的资源;第二个元素开始为求和的结果,其顺序跟sum关键字后的字段顺序相同。例如这里2对应vm.cpuNum,536870912对应vm.memorySize。- 由于级联资源一对多的特性,可以使用has查询同时拥有多种级联资源的结果。例如,查询高可用暂停的虚拟机:
query vminstance where __systemTag__ has ('ha', 'inhibitHA')Note: has目前只支持确定的值,不支持子查询。 - not has可用于查询不拥有某种级联资源的结果。 比如查询没有使用 ipv4
的虚拟机:
query vminstance where vmNics.ipVersion nothas ('4')
- 支持使用named as从句对ZQL语句命名,方便查看每条ZQL语句对应的执行结果。named as从句用法是named
as关键字后跟一个字符串,用作ZQL语句的名称。
- ZQL语句的名称必须全局唯一,否则后面的ZQL语句会覆盖前面同名语句的结果。
- named as从句可选,当省略时,返回的结果中不包含name字段,只能按照结果在数组中的顺序分辨其跟ZQL语句的对应关系。
query host named as 'host';
query zone return with (total) named as 'zone'返回结果格式如下:{
"results": [{
"inventories": [{
"username": "root",
"password": "password",
"sshPort": 22,
"zoneUuid": "1a29060d81724b6083caaf530b4c6ab5",
"name": "kvm",
"uuid": "f1e112cf4f3c4bbd939fdf18f72ac5e8",
"clusterUuid": "324fece70aa848ed917b9134ef7072c1",
"managementIp": "localhost",
"hypervisorType": "KVM",
"state": "Enabled",
"status": "Connected",
"totalCpuCapacity": 320,
"availableCpuCapacity": 314,
"cpuSockets": 2,
"totalMemoryCapacity": 34359738368,
"availableMemoryCapacity": 25232932864,
"cpuNum": 32,
"createDate": "Jul 10, 2018 5:32:56 PM",
"lastOpDate": "Jul 10, 2018 5:32:58 PM"
}],
"name": "host"
}, {
"inventories": [{
"uuid": "1a29060d81724b6083caaf530b4c6ab5",
"name": "zone",
"description": "test",
"state": "Enabled",
"type": "zstack",
"createDate": "Jul 10, 2018 5:32:54 PM",
"lastOpDate": "Jul 10, 2018 5:32:54 PM"
}],
"total": 1,
"name": "zone"
}]
}- 条件为in:
query vminstance.hostUuid where hostUuid in getapi(api='GetVmStartingCandidateClustersHosts', output='hosts.uuid', uuid='${vm1.uuid}') limit 1 - 条件为=:
query vminstance.hostUuid where hostUuid = getapi(api='GetVmStartingCandidateClustersHosts', output='hosts.uuid', uuid='${vm1.uuid}') limit 1 - 参数为boolean:
query vminstance.hostUuid where hostUuid ingetapi(api='GetCandidateMiniHosts', output='hosts.hostname', local=true, configure=false) limit 1 - 参数为list:
query vminstance.hostUuid where hostUuid ingetapi(api='GetPciDeviceCandidatesForNewCreateVm',output='inventories.uuid', clusterUuids=list('${cluster.uuid}','${vm1.uuid}')) limit 1
使用Curl调用ZQL查询示例
curl http://localhost:8080/zstack/v1/zql?zql=yourZQL -X GET -H 'Connection:close' -H 'Content-Type:application/json' -H 'Authorization:OAuth SesionID'其中:- yourZQL:查询使用的ZQL语句,需通过URL进行编码
- SessionID:调用ZQL语句所需的Sesion ID,例如376c223518e347bcbeca40d2c7c515b9
query vminstance where name='webvm' and vmnics.ip='192.168.0.10' or (vmnics.eip = '172.20.100.100' and (cpuNum >= 8 or clusterUuid in ('fe13b725c80e45709f0414c266a80239','73ca1ca7603d454f8fa7f3bb57097f80')))
restrict by (zone.uuid != 'fec2889fef2d49b1967c7e39025f4eb4') return with (total, zwatch{metricName='CPUUsedUtilization',offsetAheadOfCurrentTime=3600,period=10,labels='CPUNum=10', functions=limit(limit=10), functions=top(num=2)}) order by cpuNum desc limit 100 offset 10{
"results": [
{
"inventories": [
{
"allVolumes": [
{
"actualSize": 10775166976,
"createDate": "Nov 11, 2021 2:03:47 PM",
"description": "Root volume for VM[uuid:0d62f2c34390464d9bfd166c270a261a]",
"deviceId": 0,
"format": "qcow2",
"installPath": "sharedblock://e2402ed34190477cb9b4ae3a2cc58db6/fa75061b0fee4bc99bfba51d5191fc88",
"isShareable": false,
"lastOpDate": "Nov 16, 2021 11:42:25 PM",
"name": "ROOT-for-22222-2",
"primaryStorageUuid": "e2402ed34190477cb9b4ae3a2cc58db6",
"rootImageUuid": "b5876869ad3d464f8915f8a3597b5688",
"size": 42949672960,
"state": "Enabled",
"status": "Ready",
"type": "Root",
"uuid": "fa75061b0fee4bc99bfba51d5191fc88",
"vmInstanceUuid": "0d62f2c34390464d9bfd166c270a261a"
}
],
"allocatorStrategy": "LeastVmPreferredHostAllocatorStrategy",
"architecture": "x86_64",
"clusterUuid": "110fcbd2f0c344fd9c33604bc51b8316",
"cpuNum": 16,
"cpuSpeed": 0,
"createDate": "Nov 11, 2021 2:03:47 PM",
"defaultL3NetworkUuid": "776aa4f32c704acba90811ca071919ed",
"description": "",
"guestOsType": "Windows",
"hypervisorType": "KVM",
"imageUuid": "b5876869ad3d464f8915f8a3597b5688",
"instanceOfferingUuid": "05fe32439048403f9577eed860ca9644",
"lastHostUuid": "2926b5fce9384180a08d3cd46841e35c",
"lastOpDate": "Nov 16, 2021 11:42:25 PM",
"memorySize": 17179869184,
"name": "22222-2",
"platform": "Windows",
"rootVolumeUuid": "fa75061b0fee4bc99bfba51d5191fc88",
"state": "Stopped",
"type": "UserVm",
"uuid": "0d62f2c34390464d9bfd166c270a261a",
"vmCdRoms": [
{
"createDate": "Nov 11, 2021 2:03:47 PM",
"deviceId": 0,
"lastOpDate": "Nov 11, 2021 2:03:47 PM",
"name": "vm-0d62f2c34390464d9bfd166c270a261a-cdRom",
"uuid": "7bcf07ee5aba41399db62ef43ac9299c",
"vmInstanceUuid": "0d62f2c34390464d9bfd166c270a261a"
}
],
"vmNics": [
{
"createDate": "Nov 11, 2021 2:03:47 PM",
"deviceId": 0,
"driverType": "e1000",
"gateway": "172.25.0.1",
"hypervisorType": "KVM",
"internalName": "vnic8001.0",
"ip": "172.25.201.6",
"l3NetworkUuid": "776aa4f32c704acba90811ca071919ed",
"lastOpDate": "Nov 11, 2021 2:03:47 PM",
"mac": "fa:a7:65:4a:5b:00",
"netmask": "255.255.0.0",
"type": "VNIC",
"usedIps": [
{
"createDate": "Nov 11, 2021 2:03:47 PM",
"gateway": "172.25.0.1",
"ip": "172.25.201.6",
"ipInLong": 2887371014,
"ipRangeUuid": "9bc64be8aec24ab8bbc9b03b5db3eebc",
"ipVersion": 4,
"l3NetworkUuid": "776aa4f32c704acba90811ca071919ed",
"lastOpDate": "Nov 11, 2021 2:03:47 PM",
"netmask": "255.255.0.0",
"uuid": "688307033adb3bf081e5d9a0736ae0d3",
"vmNicUuid": "eab9d08437db4f03a800f3b01c198eab"
}
],
"uuid": "eab9d08437db4f03a800f3b01c198eab",
"vmInstanceUuid": "0d62f2c34390464d9bfd166c270a261a"
}
],
"zoneUuid": "5713bc952a904718be06f329222db7ce"
},
{
"allVolumes": [
{
"actualSize": 9680674816,
"createDate": "Oct 20, 2021 5:37:22 PM",
"description": "Root volume for VM[uuid:1e77e04fccea43f2b5ce9c27f672879f]",
"deviceId": 0,
"format": "qcow2",
"installPath": "/cloud_ps/rootVolumes/acct-36c27e8ff05c4780bf6d2fa65700f22e/vol-c6d41b9460ab497c989ed89b514202aa/c6d41b9460ab497c989ed89b514202aa.qcow2",
"isShareable": false,
"lastOpDate": "Oct 20, 2021 5:38:58 PM",
"name": "ROOT-for-vm$xzt3",
"primaryStorageUuid": "2116fa756e6f4e20a9f38ee5eabee186",
"rootImageUuid": "e21d04f8fb2e4389acfe9030e108b6a9",
"size": 10737418240,
"state": "Enabled",
"status": "Ready",
"type": "Root",
"uuid": "c6d41b9460ab497c989ed89b514202aa",
"vmInstanceUuid": "1e77e04fccea43f2b5ce9c27f672879f"
}
],
"allocatorStrategy": "LeastVmPreferredHostAllocatorStrategy",
"architecture": "x86_64",
"clusterUuid": "110fcbd2f0c344fd9c33604bc51b8316",
"cpuNum": 16,
"cpuSpeed": 0,
"createDate": "Oct 20, 2021 5:37:22 PM",
"defaultL3NetworkUuid": "7dbaf58d89994042b0c1e3c6704cb3bd",
"description": "cloned from vm[uuid:59404046cf6247a3bc1f4516762ec437]",
"guestOsType": "Ubuntu 18",
"hypervisorType": "KVM",
"imageUuid": "e21d04f8fb2e4389acfe9030e108b6a9",
"instanceOfferingUuid": "05fe32439048403f9577eed860ca9644",
"lastHostUuid": "2926b5fce9384180a08d3cd46841e35c",
"lastOpDate": "Nov 11, 2021 10:45:30 AM",
"memorySize": 17179869184,
"name": "vm$xzt3",
"platform": "Linux",
"rootVolumeUuid": "c6d41b9460ab497c989ed89b514202aa",
"state": "Stopped",
"type": "UserVm",
"uuid": "1e77e04fccea43f2b5ce9c27f672879f",
"vmCdRoms": [
{
"createDate": "Oct 20, 2021 5:37:22 PM",
"deviceId": 0,
"lastOpDate": "Oct 20, 2021 5:37:22 PM",
"name": "vm-1e77e04fccea43f2b5ce9c27f672879f-cdRom",
"uuid": "5ace720b83d4439c80ceba532457945a",
"vmInstanceUuid": "1e77e04fccea43f2b5ce9c27f672879f"
}
],
"vmNics": [
{
"createDate": "Oct 20, 2021 5:37:22 PM",
"deviceId": 0,
"driverType": "virtio",
"gateway": "192.168.81.1",
"hypervisorType": "KVM",
"internalName": "vnic7810.0",
"ip": "192.168.81.96",
"l3NetworkUuid": "7dbaf58d89994042b0c1e3c6704cb3bd",
"lastOpDate": "Oct 20, 2021 5:37:22 PM",
"mac": "fa:53:4a:f0:9d:00",
"netmask": "255.255.255.0",
"type": "VNIC",
"usedIps": [
{
"createDate": "Oct 20, 2021 5:37:22 PM",
"gateway": "192.168.81.1",
"ip": "192.168.81.96",
"ipInLong": 3232256352,
"ipRangeUuid": "e538dab6e1e84019bd7d0a78a333d071",
"ipVersion": 4,
"l3NetworkUuid": "7dbaf58d89994042b0c1e3c6704cb3bd",
"lastOpDate": "Oct 20, 2021 5:37:22 PM",
"netmask": "255.255.255.0",
"uuid": "9f4cdecfe309317eb07cf8ae95caf3a6",
"vmNicUuid": "482753eb89df4fe58b27192b12173dcb"
}
],
"uuid": "482753eb89df4fe58b27192b12173dcb",
"vmInstanceUuid": "1e77e04fccea43f2b5ce9c27f672879f"
}
],
"zoneUuid": "5713bc952a904718be06f329222db7ce"
},
{
"allVolumes": [
{
"actualSize": 4394319872,
"createDate": "Sep 15, 2021 2:22:29 PM",
"description": "Root volume for VM[uuid:077973f897a0453c8f7e0760c73689d0]",
"deviceId": 0,
"format": "qcow2",
"installPath": "sharedblock://e2402ed34190477cb9b4ae3a2cc58db6/65338b21e7364387811c764140788f65",
"isShareable": false,
"lastOpDate": "Sep 15, 2021 2:24:25 PM",
"name": "ROOT-for-000000-3",
"primaryStorageUuid": "e2402ed34190477cb9b4ae3a2cc58db6",
"rootImageUuid": "b5876869ad3d464f8915f8a3597b5688",
"size": 42949672960,
"state": "Enabled",
"status": "Ready",
"type": "Root",
"uuid": "65338b21e7364387811c764140788f65",
"vmInstanceUuid": "077973f897a0453c8f7e0760c73689d0"
}
],
"allocatorStrategy": "LeastVmPreferredHostAllocatorStrategy",
"architecture": "x86_64",
"clusterUuid": "110fcbd2f0c344fd9c33604bc51b8316",
"cpuNum": 16,
"cpuSpeed": 0,
"createDate": "Sep 15, 2021 2:22:29 PM",
"defaultL3NetworkUuid": "776aa4f32c704acba90811ca071919ed",
"description": "MSCS3",
"guestOsType": "WindowsServer 2016",
"hypervisorType": "KVM",
"imageUuid": "b5876869ad3d464f8915f8a3597b5688",
"instanceOfferingUuid": "05fe32439048403f9577eed860ca9644",
"lastHostUuid": "aa0ed44b22004d1a899007364ca0c7c8",
"lastOpDate": "Jan 12, 2022 2:38:09 PM",
"memorySize": 17179869184,
"name": "故障转移集群2",
"platform": "Windows",
"rootVolumeUuid": "65338b21e7364387811c764140788f65",
"state": "Stopped",
"type": "UserVm",
"uuid": "077973f897a0453c8f7e0760c73689d0",
"vmCdRoms": [
{
"createDate": "Sep 15, 2021 2:22:30 PM",
"deviceId": 0,
"lastOpDate": "Sep 15, 2021 2:22:30 PM",
"name": "vm-077973f897a0453c8f7e0760c73689d0-cdRom",
"uuid": "df81cd2b02814b88a78d60d11c5b08c3",
"vmInstanceUuid": "077973f897a0453c8f7e0760c73689d0"
}
],
"vmNics": [
{
"createDate": "Sep 15, 2021 2:22:30 PM",
"deviceId": 0,
"driverType": "virtio",
"gateway": "172.25.0.1",
"hypervisorType": "KVM",
"internalName": "vnic6672.0",
"ip": "172.25.201.186",
"l3NetworkUuid": "776aa4f32c704acba90811ca071919ed",
"lastOpDate": "Nov 11, 2021 11:50:01 AM",
"mac": "fa:44:0b:42:24:00",
"netmask": "255.255.0.0",
"type": "VNIC",
"usedIps": [
{
"createDate": "Sep 15, 2021 2:22:30 PM",
"gateway": "172.25.0.1",
"ip": "172.25.201.186",
"ipInLong": 2887371194,
"ipRangeUuid": "9bc64be8aec24ab8bbc9b03b5db3eebc",
"ipVersion": 4,
"l3NetworkUuid": "776aa4f32c704acba90811ca071919ed",
"lastOpDate": "Sep 15, 2021 2:22:30 PM",
"netmask": "255.255.0.0",
"uuid": "bb634a32ed2731edbb71fd9a9a5469db",
"vmNicUuid": "a62564e7600346bd9d42992403b2f416"
}
],
"uuid": "a62564e7600346bd9d42992403b2f416",
"vmInstanceUuid": "077973f897a0453c8f7e0760c73689d0"
}
],
"zoneUuid": "5713bc952a904718be06f329222db7ce"
},
{
"allVolumes": [
{
"actualSize": 15186984960,
"createDate": "Sep 24, 2021 10:42:26 PM",
"description": "Root volume for VM[uuid:1a9ccdc7f4854d93a3ad5e6e226c2a2c]",
"deviceId": 0,
"format": "qcow2",
"installPath": "sharedblock://cf1e9c4f3d674f159505c234c3e5356b/007154f1864a457b8658f81641c89485",
"isShareable": false,
"lastOpDate": "Sep 24, 2021 10:45:18 PM",
"name": "ROOT-for-111-3",
"primaryStorageUuid": "cf1e9c4f3d674f159505c234c3e5356b",
"rootImageUuid": "01ff0ca649604b1db590bf6ef641d957",
"size": 32212254720,
"state": "Enabled",
"status": "Ready",
"type": "Root",
"uuid": "007154f1864a457b8658f81641c89485",
"vmInstanceUuid": "1a9ccdc7f4854d93a3ad5e6e226c2a2c"
}
],
"allocatorStrategy": "LeastVmPreferredHostAllocatorStrategy",
"architecture": "x86_64",
"clusterUuid": "110fcbd2f0c344fd9c33604bc51b8316",
"cpuNum": 16,
"cpuSpeed": 0,
"createDate": "Sep 24, 2021 10:42:26 PM",
"defaultL3NetworkUuid": "a61146e6f2fe4ed382c47c09d968cea0",
"description": "",
"guestOsType": "WindowsServer 2016",
"hypervisorType": "KVM",
"imageUuid": "01ff0ca649604b1db590bf6ef641d957",
"instanceOfferingUuid": "05fe32439048403f9577eed860ca9644",
"lastHostUuid": "f740664d2688439abf620255eb05e843",
"lastOpDate": "Oct 1, 2021 10:25:21 AM",
"memorySize": 17179869184,
"name": "111-3",
"platform": "Windows",
"rootVolumeUuid": "007154f1864a457b8658f81641c89485",
"state": "Stopped",
"type": "UserVm",
"uuid": "1a9ccdc7f4854d93a3ad5e6e226c2a2c",
"vmCdRoms": [
{
"createDate": "Sep 24, 2021 10:42:26 PM",
"deviceId": 0,
"lastOpDate": "Sep 24, 2021 10:42:26 PM",
"name": "vm-1a9ccdc7f4854d93a3ad5e6e226c2a2c-cdRom",
"uuid": "3af14b1eebf74b05bccead5455b21649",
"vmInstanceUuid": "1a9ccdc7f4854d93a3ad5e6e226c2a2c"
}
],
"vmNics": [
{
"createDate": "Sep 25, 2021 11:38:22 PM",
"deviceId": 0,
"driverType": "e1000",
"gateway": "172.26.0.1",
"hypervisorType": "KVM",
"internalName": "vnic6711.0",
"ip": "172.26.201.214",
"l3NetworkUuid": "a61146e6f2fe4ed382c47c09d968cea0",
"lastOpDate": "Sep 25, 2021 11:38:22 PM",
"mac": "fa:a8:c6:4b:1e:00",
"netmask": "255.255.0.0",
"type": "VNIC",
"usedIps": [
{
"createDate": "Sep 25, 2021 11:38:22 PM",
"gateway": "172.26.0.1",
"ip": "172.26.201.214",
"ipInLong": 2887436758,
"ipRangeUuid": "63708e07fa374fe5b9d735b6455e5651",
"ipVersion": 4,
"l3NetworkUuid": "a61146e6f2fe4ed382c47c09d968cea0",
"lastOpDate": "Sep 25, 2021 11:38:22 PM",
"netmask": "255.255.0.0",
"uuid": "39c53c8847e7351c84c42b57ccb64c1e",
"vmNicUuid": "6a156d11879647228cf9a1cbc8b14538"
}
],
"uuid": "6a156d11879647228cf9a1cbc8b14538",
"vmInstanceUuid": "1a9ccdc7f4854d93a3ad5e6e226c2a2c"
}
],
"zoneUuid": "5713bc952a904718be06f329222db7ce"
}
],
"returnWith": {
"zwatch": [
{
"labels": {
"CPUNum": "10",
"VMUuid": "747d5c006d3a4654a84750772fdecf10"
},
"time": 1650601783,
"value": 0.18
},
{
"labels": {
"CPUNum": "10",
"VMUuid": "747d5c006d3a4654a84750772fdecf10"
},
"time": 1650601773,
"value": 0.16
}
],
"zwatchTotal": 2
},
"total": 252
}
],
"success": true
}批量API返回
批量返回消息分为非longjob和longjob两种类型,详情如下。
非longjob类型API
对于非longjob类型API的返回值,外层的success在出错时为true,而里层success则根据结果进行变化,若子任务成功则success=true,否则success=false。以下为APIBatchDeleteVolumeSnapshotMsg返回示例:
{
"results": [
{
"error": {
"code": "VOLUME_SNAPSHOT.1000",
"description": "Snapshot is not in correct status for operation.",
"details": "snapshot[uuid:e9c43724c6614aa488b63d6b33e30ebd, name:测试1]'s status[Ready] is not allowed for message[org.zstack.header.storage.snapshot.VolumeSnapshotDeletionMsg], allowed status[Ready, Creating, Deleting]"
},
"snapshotUuid": "e9c43724c6614aa488b63d6b33e30ebd",
"success": false
},
{
"error": {
"code": "VOLUME_SNAPSHOT.1000",
"description": "Snapshot is not in correct status for operation.",
"details": "snapshot[uuid:e9c43724c6614aa488b63d6b33e30ebd, name:测试2]'s status[Ready] is not allowed for message[org.zstack.header.storage.snapshot.VolumeSnapshotDeletionMsg], allowed status[Ready, Creating, Deleting]"
},
"snapshotUuid": "63daa66726b24f9390216b8edf32190d",
"success": false
}
],
"success": true
}{
"results": [
{
"snapshotUuid": "1c8408e0f05d4fc39465d7db27d6bc32",
"success": true
},
{
"snapshotUuid": "e071e0ec42de4323bff23993a6a236d2",
"success": true
}
],
"success": true
}Longjob类型API
对于longjob类型API的返回值,外层success在出错时也为true,而里层success则根据结果进行变化,若子任务成功则success=true,否则success=false。以下为APIAddHostFromConfigFileMsg返回示例:
{
"results": [
{
"error": {
"code": "SYS.1006",
"cost": "5ms",
"description": "An operation failed",
"details": "the host[10.0.231.23] ssh port[22] not open after 300 seconds, connect timeout",
"elaboration": "错误信息: 主机[10.0.231.23]的ssh端口[22]在 300 秒内未开放,连接超时",
"location": "HostManagerImpl.java: send-connect-host-message (location:2/4)"
},
"ip": "10.0.231.23",
"success": false
},
{
"error": {
"code": "SYS.1007",
"description": "One or more API argument is invalid",
"details": "已经存在一个管理IP是[10.0.93.160]的主机"
},
"ip": "10.0.93.160",
"success": false
}
],
"success": true
}{
"results": [
{
"ip": "10.0.231.231",
"success": true
},
{
"ip": "10.0.93.160",
"success": true
}
],
"success": true
}结果说明
- 两种类型API外层的
success的返回均为true。 - 外层
success代表REST请求的结果,当发起REST请求成功则success为true。 - 里层
success代表任务实际结果,成功则里层返回succuess=true,失败则返回success=false。
