概览

对于运营大规模云的企业用户来说,最大的挑战之一是快速精准定位所需资源。例如,需要从100,000台虚拟机中找到拥有EIP(17.12.53.8)的虚拟机。ZStack Cloud提供了丰富全面的API可以用来查询所有资源的每一个域,具体参看《开发手册》的查询API章节了解设计架构。


架构(Architecture)

每个ZStack Cloud资源都依据属性(properties)组织成JSON格式的清单(inventory)。

例如,区域(Zone)清单:
{             "createDate": "Nov 17, 2017 8:27:47 PM",             "description": "Test",             "lastOpDate": "Nov 20, 2017 5:40:52 PM",             "name": "Zone-1",             "state": "Enabled",             "type": "zstack",             "uuid": "c3a228078e8c4f81ba7da0b16fb8d77f"         }
一个资源清单可以包含其他资源的清单;例如,一个L3网络清单包含IP范围(IP Range)清单:
{             "category": "Public",             "createDate": "Nov 17, 2017 9:11:59 PM",             "dns": [                 "223.5.5.5"             ],             "ipRanges": [                 {                     "createDate": "Nov 17, 2017 9:18:47 PM",                     "endIp": "10.108.10.110",                     "gateway": "10.0.0.1",                     "l3NetworkUuid": "a8b7054aaa9141f696afebdb1721e5c8",                     "lastOpDate": "Nov 17, 2017 9:18:47 PM",                     "name": "L3-Pub",                     "netmask": "255.0.0.0",                     "networkCidr": "10.0.0.1/8",                     "startIp": "10.108.10.100",                     "uuid": "df5b1ab49a53440bb44eb14c7ebfd50a"                 }             ],             "l2NetworkUuid": "16fecf5ff5754c3fb6669986ec1fe645",             "lastOpDate": "Nov 17, 2017 9:11:59 PM",             "name": "L3-Pub",             "networkServices": [                 {                     "l3NetworkUuid": "a8b7054aaa9141f696afebdb1721e5c8",                     "networkServiceProviderUuid": "3d46e334773845adac0d90c86a5999ee",                     "networkServiceType": "Userdata"                 },                 {                     "l3NetworkUuid": "a8b7054aaa9141f696afebdb1721e5c8",                     "networkServiceProviderUuid": "3d46e334773845adac0d90c86a5999ee",                     "networkServiceType": "Eip"                 },                 {                     "l3NetworkUuid": "a8b7054aaa9141f696afebdb1721e5c8",                     "networkServiceProviderUuid": "3d46e334773845adac0d90c86a5999ee",                     "networkServiceType": "DHCP"                 }             ],             "state": "Enabled",             "system": false,             "type": "L3BasicNetwork",             "uuid": "a8b7054aaa9141f696afebdb1721e5c8",             "zoneUuid": "c3a228078e8c4f81ba7da0b16fb8d77f"         }
清单中的域(field)分为两类:原生域(primitive field)和嵌套域(nested field)
  • 原生域是由一个基本类型(primitive type)构成的域,如数字(number)、字符串(string)、布尔(boolean)、或日期(date);在上述示例中,uuidnamesystem都是原生域。
  • 嵌套域通常是由代表其它资源数据类型组合而成; 在上述示例中,ipRanges就是一个嵌套域。
说明:
  • 除非特别声明,所有清单的所有域都是可以被查询的。
  • 对于一个清单,通常都有对应的查询API;例如,QueryZone、QueryHost、QueryVmInstance等。
  • 查询API通常返回一个清单列表,在没有匹配结果时会返回一个空列表。
  • 一个查询的结果类似于:
    {     "inventories": [         {             "allocatorStrategy": "LeastVmPreferredHostAllocatorStrategy",             "cpuNum": 1,             "cpuSpeed": 0,             "createDate": "Nov 17, 2017 8:48:06 PM",             "lastOpDate": "Nov 17, 2017 8:48:06 PM",             "memorySize": 1073741824,             "name": "instance-offering",             "sortKey": 0,             "state": "Enabled",             "type": "UserVm",             "uuid": "32c3405f7bbf43009cfaf58cb41e39fc"         }     ],     "success": true }

查询API由一个查询条件(query conditions)的列表和一些辅助参数(helper parameters)构成:

查询API的参数(Parameters)

名字 描述 此参数可选 可选参数值 起始支持版本
conditions :ref:`QueryCondition <QueryCondition>`组成的列表 0.6
limit 允许查询API返回清单的最大数量;默认为1000 true 0.6
start 返回清单的起始编号;默认为0 true 0.6
count 如果为true, 查询响应只返回清单数量;默认为false
  • true
  • false
0.6
replyWithCount 如果为true, 查询响应会同时返回清单及其数量;默认为false
  • true
  • false
0.6
sortBy 指定的域被作为排序依据;这个域必须是原生域 true 0.6
sortDirection 如果sortBy不等于null,这个域指定排序方向;默认为asc
  • asc
  • desc
0.6
fields 原生域组成的一个列表;指定时, 查询返回的清单只会包含这些域 true 0.6

查询条件(Query Condition)

查询API接受查询条件组成的列表,查询条件包含以下属性:
名字 描述 此参数可选 可选的参数值 起始支持版本
name 域名 0.6
op 比较操作符(comparison operator)
  • =
  • !=
  • >
  • >=
  • <
  • <=
  • in
  • not in
  • is null
  • is not null
  • like
  • not like
0.6
value 查询值 0.6
域名可以是原生域的名字,也可以是嵌套域的子域名字,或者是扩展域(expanded field)的子域(sub-field)名字(请参看:ref:Join <query join>); op是SQL语言中的比较操作符。
操作符 CLI格式 描述
= = 等于操作符; 字符串比较区分大小写
!= != 不等于操作符; 字符串比较区分大小写
> > 大于操作符; 字符串比较请参看MySQL的规范
>= >= 大于等于操作符; 字符串比较请参看MySQL的规范
< < 小于; 字符串比较请参看MySQL的规范
<= <= 小于或等于操作符; 字符串比较请参看MySQL的规范
in ?= 检查一个值是否在一个集合内
not in !?= 检查值是否不在一个集合内
is null =null NULL值测试
is not null !=null 非NULL值测试
like ~= 简单模式匹配;用%匹配任一数量的字符, 甚至零个字符; 用_匹配单个字符
not like !~= 简单模式匹配的反式;用%匹配任一数量的字符, 甚至零个字符;用_匹配单个字符
查询条件之间的关系是逻辑与(logical AND), 当前版本只支持这种关系,例如:
#用来查找名字为L3Network1的L3网络,并且这个网络有一个或多个IP范围的名字是range1 QueryL3Network ipRanges.name=range1 name=L3Network1

CLI查询条件

有两种方式可以在CLI中使用查询条件:
  • 一种是查询API的原始形式:
    QueryHost conditions='[{"name":"name", "op":"=", "value":"KVM1"}]'
  • 另一种是CLI格式:
    QueryHost name=KVM1
显然,CLI格式更直观更容易理解。CLI格式通常使用以下格式表示查询条件:
condition_name(no_space)CLI_comparison_operator(no_space)condition_value
在CLI中键入命令时, 你可以使用*Tab*来自动补全或者提示包括原生域,嵌套域以及扩展域在内的可以被查询的域:
admin >>>QueryVmInstance [Query Conditions:] allVolumes.            cluster.               host.                  image.                 instanceOffering. resourcePool.          rootVolume.            vmCdRoms.              vmNics.                zone.   __systemTag__=         __tagUuid__=           __userTag__=           allocatorStrategy=     clusterUuid= cpuNum=                cpuSpeed=              createDate=            defaultL3NetworkUuid=  description= groupBy=               hostUuid=              hypervisorType=        imageUuid=             instanceOfferingUuid= lastHostUuid=          lastOpDate=            memorySize=            name=                  platform= rootVolumeUuid=        state=                 systemTags=            type=                  userTags= uuid=                  zoneUuid=  [Parameters:] count=                 fields=                limit=                 replyWithCount=        sortBy= sortDirection=         start=                 timeout=

联结(Join)扩展查询(expanded query)

ZStack Cloud中联结(Join)被称为扩展查询(expanded query);这种查询允许通过其它和要查询的目标资源有关系的资源的域来查询;在ZStack Cloud的术语中这些域被称为扩展域。

例如,依据云主机的网卡(nic)拥有EIP的VIP为10.108.10.102来查询其L3网络:
admin >>>QueryL3Network vmNic.eip.vipIp=10.108.10.102

上述示例中,L3网络的清单没有vmNic.eip.vipIp域;但此IP地址与云主机的网卡nic清单有关系,而云主机的网卡nic清单又与EIP清单有关系;可以构造一个跨越三个清单的扩展查询:L3网络清单、云主机nic清单、和EIP清单。

基于此联结扩展查询条件,ZStack Cloud可以提供将近400万种查询条件以及无穷无尽的组合条件。

以下是构造的复杂示例,用于展示强大的查询功能:
QueryVolumeSnapshot volume.vmInstance.vmNics.l3Network.l2Network.attachedClusterUuids?=13238c8e0591444e9160df4d3636be82

此查询用于查找云盘快照,此查询依赖云盘所在的云主机,云主机所在的L3网络的L2网络被挂载在一个uuid为13238c8e0591444e9160df4d3636be82的集群上。

查询列表(Query List)

当一个域是列表的时候,可以包含类似int、long、string的基本类型或者嵌套清单。

查询列表并不特殊;编写本章节只是用来提醒大家,不要误认为只能用in(?=)和not in(!?=)来查询一个列表域;实际上,我们可以使用所有的比较操作符。

例如:
#查找所有的拥有类似72.72.72.*的DNS的L3网络 QueryL3Network dns~=72.72.72.%
#查找所有的IP范围从192.168.0.10开始的L3网络 QueryL3Network ipRanges.startIp=192.168.0.10

查询标签(Query Tags)

在这一节中:ref:`tags <tag>`你会看到所有的资源都可以用系统标签(system tags)和用户标签(user tags),它们都可以作为查询条件。

ZStack Cloud使用两个特别的域: __userTag____systemTag__来做查询。

例如:
QueryVmInstance __userTag__?=web-tier-VMs
QueryHost __systemTag__?=os::distribution::Ubuntu managementIp=192.168.0.212
  • 操作符>>=<<=只会返回拥有满足条件的标签的资源;
  • is not null会返回所有拥有标签的资源;
  • is null会返回所有没有标签的资源;
  • !=not innot like会返回拥有的标签不满足条件的以及没有标签的所有资源。

避免循环查询(Avoid Loop Query)

大多数ZStack Cloud资源拥有双向的扩展查询。

例如,主机拥有扩展至集群的扩展查询,而集群也拥有扩展至主机的扩展查询。这使得从任意方向查询资源成为可能,但同时也可能导致查询循环。

例如:
QueryHost vmInstance.vmNics.eip.vmNic.vmInstance.uuid=d40e459b97db5a63dedaffcd05cfe3c2
就是一个循环查询, 它和下面的查询作用相同:
QueryHost vmInstance.uuid=d40e459b97db5a63dedaffcd05cfe3c2

循环查询的行为是未定义的;有可能得到也有可能得不到正确的结果。因此,请避免使用循环查询。

有效的使用查询

查询API很强大,可以通过不同的查询方式得到相同的结果。

例如, 要查找运行在UUID为e497e90ab1e64db099eea93f998d525b的物理机上的云主机:

方式一:
QueryVmInstance hostUuid=e497e90ab1e64db099eea93f998d525b
方式二:
QueryVmInstance host.uuid=e497e90ab1e64db099eea93f998d525b

上述示例中,方式一更高效,因为它只是用了VM表的原生域进行查询;方式二使用了联结VM表和host表的扩展查询。

当查询条件是UUID的时候,建议使用原生域而非扩展域的子域进行查询。


示例

普通查询

QueryVmInstance defaultL3NetworkUuid=7e52c8b7b6f94e4485a61f3f1a8bfe42 QueryPortForwardingRule protocolType=TCP

查询计数

QueryVmInstance defaultL3NetworkUuid=7e52c8b7b6f94e4485a61f3f1a8bfe42 count=true QueryPortForwardingRule protocolType=TCP count=true

带计数的普通查询

QueryVmInstance defaultL3NetworkUuid=7e52c8b7b6f94e4485a61f3f1a8bfe42 replyWithCount=true QueryPortForwardingRule protocolType=TCP replyWithCount=true

设置限制

QueryVmInstance defaultL3NetworkUuid=7e52c8b7b6f94e4485a61f3f1a8bfe42 limit=3 QueryPortForwardingRule protocolType=TCP limit=2

设置条件

QueryVmInstance name~=clone QueryPortForwardingRule vipPortStart?=23,24

设置起始

QueryVmInstance imageUuid=4b5e37a47a402977a3b285ccecf9c0c1 start=2 limit=3 QueryPortForwardingRule protocolType=TCP start=1 limit=3

选择域

QueryVmInstance fields=name,uuid clusterUuid=5cac8330d5ab4c2ea393b8c3986c8850 QueryPortForwardingRule fields=uuid,privatePortStart,privatePortEnd vipPortStart=23 vipPortEnd=23

排序

QueryVmInstance clusterUuid=5cac8330d5ab4c2ea393b8c3986c8850 sortBy=createDate sortDirection=asc QueryPortForwardingRule sortBy=privatePortStart sortDirection=desc