RESTful API Overview
ZStack AIOS Platform 5.5.38 provides native RESTful supports. You can design principles and conventions by using the REST-defined framework, and use the HTTP-based programming language for further development.
HTTP Verbs
ZStack AIOS Platform API allows you to perform operations on resources by using the following four HTTP verbs.
| HTTP Verb | Description |
|---|---|
| GET | Obtains resource information.
|
| POST | Creates a resource. |
| PUT | Updates a resource.
|
| DELETE | Deletes a resource. |
Parameter Passing
URL, Query String, and HTTP Body can all be used to pass parameters. Each method can be used independently, or be used in conjunction with other methods. Note that the specific method is determined by the API you use.
URL Parameter Passing
When you operate on a specific resource, the resource UUID will be encoded and then passed to a URL.
For example, start a VM instance with the UUID f97143d60f1042c9badd9a1336d3c105. Then, the URL format is as follows:
zstack/v1/vm-instances/f97143d60f1042c9badd9a1336d3c105/actions
In the preceding sample, the UUID is encoded and passed to a URL.
Query String Parameter Passing
All APIs that use the HTTP GET verb pass parameters by using query strings.
For example, query all the VM instances that are in the running state. Then, the URL format is as follows:
zstack/v1/vm-instances?q=state=Running
HTTP Body Parameter Passing
When you create a resource by using the POST verb, or modify a resource by using the PUT verb, the rest of the parameters will be passed by using the HTTP body method apart for those passed by using a URL.
For example, start a VM instance on a specified host.
PUT zstack/v1/vm-instances/f97143d60f1042c9badd9a1336d3c105/actions
{
"startVmInstance": {
"hostUuid": "8aef7e3a53b34eedaa05027a919156d9"
}
}
In the preceding sample, the UUID of the VM instance is passed by using a URL, while the hostUuid parameter is passed by using the HTTP body.
HTTP Headers
ZStack AIOS Platform API uses the following custom HTTP headers.
Authorization
You need a session before you use all ZStack AIOS Platform APIs, except for a few APIs such as login API. When you call an API, the session UUID will be passed by using the Authorization HTTP header. The header format is as follows:
Authorization: OAuth Session UUID
Example:
Authorization: OAuth 34cbfddd470a47d8bdb0727cd2182618
OAuth and the session UUID must be separated by using a space.
X-Job-UUID
If you use an asynchronous API, you can specify the API Job UUID by using the X-Job-UUID HTTP header. For example,
X-Job-UUID: d825b1a26f4e474b8c59306081920ff2
If an HTTP header is not specified, ZStack AIOS Platform will automatically generate a UUID for API Job.
X-Job-UUID must be a version 4 UUID (a random UUID) without hyphens (-). ZStack AIOS Platform will authenticate the validity of the X-Job-UUID format, and returns the 400 Bad Request error for invalid strings.
X-Web-Hook
If you use an asynchronous API, you can specify a callback URL by using the X-Web-Hook HTTP header to receive API responses. By using the callback URL method, the caller can avoid using the round-robin policy to query the results of an asynchronous API operation. For example,
X-Web-Hook: http://localhost:5000/api-callback
X-Job-Success
When you obtain the operation results of an asynchronous API by using the X-Web-Hook callback method, ZStack AIOS Platform will include the X-Job-Success HTTP header to the HTTP Post request send to the callback URL. The X-Job-Success HTTP header indicates whether the API operation succeeds or not. For example,
X-Job-Success: true
If the value is true, the operation succeeds, or vice versa.
HTTP Status Code
The following table lists the status codes used by ZStack AIOS Platform .
| HTTP Status Code | Description |
|---|---|
| 200 | The API operation has succeeded. |
| 202 | The API request has been accepted by ZStack AIOS Platform, and you need to obtain the API result by using the round-robin policy or webhook. The status code only appears when you call an asynchronous API. |
| 400 | The API request does not include the required parameter, or includes an invalid parameter. The detailed information can be obtained from the HTTP response body. |
| 404 | The correct URL was not found, which usually because a wrong API URL is specified. If the URL that you access is the round-robin address returned by the asynchronous API, the round-robin address has expired. |
| 405 | The API call uses a wrong HTTP method. For example, when you create a resource, you might mistakenly used the GET method instead of the POST method. |
| 500 | The ZStack AIOS Platform RESTful terminal has encountered an internal error. |
| 503 | The API operation incurred an error. For example, you cannot create a VM instance because of the resource shortage. The detailed error information can be obtained from the HTTP response body. |
API Type
ZStack AIOS Platform API includes the following two types of APIs.
Synchronous API
APIs that use the GET method are all synchronous APIs, and includes API results in HTTP response received by callers. For example,
GET zstack/v1/zones/f3fa7671894a40f6a73f5bfc7d90c126
{
"inventory": {
"uuid": "f3fa7671894a40f6a73f5bfc7d90c126",
"name": "zone1",
"description": "test",
"state": "Enabled",
"type": "zstack",
"createDate": "Jan 6, 2017 3:51:16 AM",
"lastOpDate": "Jan 6, 2017 3:51:16 AM"
}
}
Asynchronous API
Apart from the login APIs, all APIs that do not use the GET method are asynchronous APIs. After you successfully called an asynchronous API, you will receive a 202 status code and a round-robin address and timeout period (the location and apiTimeout fields) contained in Body. The unit of the apiTimeout field value is milliseconds. In addition, by using the GET method, you need to periodically request the round-robin address to obtain API operation results. For example,
Status Code: 202
Body:
{
"apiTimeout":43200000
"location": "http://localhost:8989/v1/api-jobs/967a26b7431c49c0b1d50d709ef1aef3"
}
Normally, when you request a round-robin address by using the GET method, you can obtain the following four types of responses:
- 202 status code: indicates that the API is still being processed, and you need to continuously use the round-robin policy.
- 200 status code: indicates that the API operation succeeded, and the API result is contained in Body.
- 503 status code: indicates that the API operation failed, and the error code is contained in Body.
- 404 status code: indicates that the round-robin address has expired. That means that you probably access a wrong round-robin address, or the round-robin address is deleted because you have not accessed the round-robin address for a long time (for example, 2 days).
If you use an asynchronous API, you can also obtain the operation results by using webhook. The detailed usage can be seen in the following topics or sections.
API Operation
Similar to all RESTful APIs, most of ZStack AIOS Platform APIs can perform create, read, update, and delete (CRUD) operations and remote procedure call (RPC) style operations.
Create Resource
To create resources, use the POST method. The parameters are passed by using the HTTP body. The following is an example of creating a VM instance:
POST zstack/v1/vm-instances
Authorization: OAuth 0c234e29a2ad4ff4b0d97d4f3b47c6cf
{
"params": {
"l3NetworkUuids": ["37a701c7fe4a40758da15593aedd8aff"],
"defaultL3NetworkUuid": "37a701c7fe4a40758da15593aedd8aff",
"dataDiskOfferingUuids": [],
"name": "TestVm",
"description": "Test",
"systemTags": [],
"instanceOfferingUuid": "dd53f94b58924510b0122e40799a4114",
"type": "UserVm",
"imageUuid": "cc7b56780879409f98c1f992b75a12b0"
}
}
Query Resource
To query resources, use the GET method. The query conditions are passed by using a query string. The following is an example of querying the VM instances whose name is not equal to web-vm in the cluster1:
GET zstack/v1/vm-instances?condition=name!=web-vm&condition=cluster.name=cluster1
Authorization: OAuth 0c234e29a2ad4ff4b0d97d4f3b47c6cf
If you already know the resource UUID and want to obtain directly the resource information, use directly the GET method without adding any query condition. For example,
GET zstack/v1/vm-instances/56f0fd314a2647ffb4f9565f6d05858e
Authorization: OAuth 0c234e29a2ad4ff4b0d97d4f3b47c6cf
This sample above returns information about the VM instance whose UUID is 56f0fd314a2647ffb4f9565f6d05858e.
Delete Resource
To delete resources, use the DELETE method. The UUID of the deleted resource is encoded in a URL. For example,
DELETE zstack/v1/vm-instances/56f0fd314a2647ffb4f9565f6d05858e
Authorization: OAuth 0c234e29a2ad4ff4b0d97d4f3b47c6cf
This sample above deletes the VM instance whose UUID is 56f0fd314a2647ffb4f9565f6d05858e.
Change Resource and Perform RPC-Style Operation
Due to the nature of IaaS businesses, a portion of operations, such as starting a VM instance, are more similar to RPC operations instead of CRUD operations. According to some best practices of RESTful APIs, ZStack AIOS Platform will categorize all these operations into sub-resources of operations. For example, when you start VM instances, or stop VM instances, you are performing operations on the sub-resources.
Start a VM instance:
PUT zstack/v1/vm-instances/d46841bd4ebd47f8bf0bed85c3bdf0db/actions
{
"startVmInstance": {}
}
Stop a VM instance:
PUT zstack/v1/vm-instances/d46841bd4ebd47f8bf0bed85c3bdf0db/actions
{
"stopVmInstance": {}
}
In the preceding samples, both operations access the same URL /v1/vminstances/d46841bd4ebd47f8bf0bed85c3bdf0db/actions, and the specific operation types are indicated by the field name contained in Body. For example, if the stopVmInstance API contains additional parameters, these parameters are contained in the map to which the operation field name corresponds.
For more information about the specific field names of resource operations and examples, refer to detailed topics of each ZStack AIOS Platform API.
Basic Workflow
In the following example, we will create a zone to describe the basic workflow for using the RESTful API.
Log In
The first step to use APIs is to log in to your account to obtain a session UUID for subsequent API calls.
PUT zstack/v1/accounts/login
body:
{
"logInByAccount": {
"password": "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86",
"accountName": "admin"
}
}
In the preceding sample, the account password is the result generated by SHA-512.
The API response is as follows:
status code: 200
body:
{
"inventory": {
"uuid": "00d038b699b74e76a01705918d48d939",
"accountUuid": "36c27e8ff05c4780bf6d2fa65700f22e",
"userUuid": "36c27e8ff05c4780bf6d2fa65700f22e",
"expiredDate": "Jan 1, 2017 11:31:06 AM",
"createDate": "Jan 1, 2017 9:31:06 AM"
}
}
The response content contains the account UUID and other fields. The session UUID that you need is contained in the uuid field: 00d038b699b74e76a01705918d48d939.
Create Zone
POST zstack/v1/zones
headers:
Authorization: OAuth 00d038b699b74e76a01705918d48d939
body:
{
"params": {
"name": "Zone1",
"description": "Test"
}
}
The CreateZone API is an asynchronous API. Therefore, the API response is a round-robin address and a timeout period instead of a direct result. For example,
status code: 202
body:
{
"apiTimeout":1800000
"location": "http://localhost:8080/v1/api-jobs/d0345d3ddcae485f8170572b15a2b581"
}
You need to obtain API results periodically by using the round-robin policy. For example,
GET http://localhost:8989/v1/api-jobs/d0345d3ddcae485f8170572b15a2b581
Authorization: OAuth 00d038b699b74e76a01705918d48d939
If the API operation does not complete, the preceding GET operation still obtains a 202 status code and the round-robin address. After the API operation succeeded, you will get the following result:
status code: 200
body:
{
"inventory": {
"uuid": "f52fe55b64094ceb99b3893a238c4931",
"name": "Zone1",
"description": "Test",
"state": "Enabled",
"type": "zstack",
"createDate": "Jan 1, 2017 9:31:07 AM",
"lastOpDate": "Jan 1, 2017 9:31:07 AM"
}
}
Query Zone
You can use the GET method to obtain the information about the zone you created. For example,
GET zstack/v1/zones/f52fe55b64094ceb99b3893a238c4931
Authorization: OAuth 00d038b699b74e76a01705918d48d939
The response is as follows:
status code: 200
body:
{
"inventory": {
"uuid": "f52fe55b64094ceb99b3893a238c4931",
"name": "Zone1",
"description": "Test",
"state": "Enabled",
"type": "zstack",
"createDate": "Jan 1, 2017 9:31:07 AM",
"lastOpDate": "Jan 1, 2017 9:31:07 AM"
}
}
Log Out
When all API calls are completed, you need to log out the session. For example,
DELETE zstack/v1/accounts/sessions/00d038b699b74e76a01705918d48d939
The response is as follows:
status code: 200
Webhook
Using the round-robin policy to query the operation results of asynchronous APIs is inefficient. In this regard, zstack provides the webhook method to actively send API results to callers.
To use the webhook feature, you only need to specify X-Job-UUID and X-Web-Hook in the HTTP headers. In the preceding example of creating a zone, the version of the API that use the webhook method is as follows:
POST zstack/v1/zones
headers:
Authorization: OAuth 00d038b699b74e76a01705918d48d939
X-Job-UUID: d0345d3ddcae485f8170572b15a2b581
X-Web-Hook: http://127.0.0.1:8989/rest-webhook
body:
{
"params": {
"name": "Zone1",
"description": "Test"
}
}
The API response is still a 202 status code and a round-robin address. However, you do not need to use the round-robin policy again. After the API operation succeeded, the result will be sent to:
http://127.0.0.1:8989/rest-webhook
POST http://127.0.0.1:8989/rest-webhook
headers:
X-Job-Success: true
X-Job-UUID: d0345d3ddcae485f8170572b15a2b581
body:
{
"inventory": {
"uuid": "f52fe55b64094ceb99b3893a238c4931",
"name": "Zone1",
"description": "Test",
"state": "Enabled",
"type": "zstack",
"createDate": "Jan 1, 2017 9:31:07 AM",
"lastOpDate": "Jan 1, 2017 9:31:07 AM"
}
}
In the result above, X-Job-Success indicates whether the API operation succeeds. In addition, the value contained in X-Job-UUID is the same as that of X-Job-UUID when you call APIs. Note that you can compare the result with the API.
Query API
You can query a resource by using the GET method. Similar to MySQL, you can specify multiple query conditions and the order method, or select fields and perform cross-table query.
ZStack AIOS Platform supports more than 4 million query conditions as well as factorial of 4 million combinations of conditions.
Single Table Query
Query the VM instance whose name is vm1. For example,
GET zstack/v1/vm-instances?q=name=vm1
Query the VM instance whose name is vm1 and is in the Running state. For example,
GET zstack/v1/vm-instances?q=name=vm1&q=state=Running
These two samples are about querying the VM resource itself, which belongs to the single table query in the database level.
Cross-Table Query
You can perform cross-table queries by using the . delimiter. The following are two examples:
Query the VM instance whose IP address is 192.168.10.100. The cross-table query is performed for the VM instance table and the NIC table.
GET zstack/v1/vm-instances?q=vmNics.ip=192.168.10.100
Query all the VM instances that are running on the 10.10.20.3 IP address. The cross-table query is performed for the VM instance table and the host table.
GET zstack/v1/vm-instances?q=host.managementIp=10.10.20.3
Query API Parameters
| Name | Type | Location | Description | Optional Value | Starting Version |
|---|---|---|---|---|---|
| q | List | query | Optional. The query condition. For more information, see Query Condition. If omitted, all records will be returned. The number of returned records is subject to the limit field. | 0.6 | |
| limit | Integer | query | Optional. The maximum number of returned records. This field is equivalent to the limit field of MySQL. Default value: 1000. | 0.6 | |
| start | Integer | query | Optional. The first record to query. This field is equivalent to the offset field of MySQL. You can perform paginated query by using both the start and limit fields. | 0.6 | |
| count | Boolean | query | Optional. The count query. This field is equivalent to the count() function of MySQL. If true, the API only returns the number of records that meet the query condition. | 0.6 | |
| groupBy | String | query | Optional. Groups rows into subgroups based on values of columns or expressions. This field is equivalent to the Group By clause in MySQL, such as groupBy=type. | 1.9 | |
| replyWithCount | Boolean | query | Optional. If true, the query response returns both the records and the record count. Default value: false. For more information, see Paginated Query. | 0.6 | |
| sort | String | query | Optional. The sort field, which is equivalent to the sortBy keyword of MySQL. This field must be used with ‘+’ or ‘-’ followed by the sort field name. Note that ‘+’ means sort ascending, while ‘-’ means sort descending. For example,
|
‘+’ field name, ‘-’ field name | 0.6 |
| fields | List | query | Optional. The returned fields. This field is equivalent to the select field of MySQL. For example, if fields=name,uuid, only names and UUIDs that meet the query conditions are returned. | 0.6 |
Query Condition
The query conditions of ZStack AIOS Platform query API are similar to the MySQL database.
For example,
uuid=bfa67f956afb430890aa49db14b85153
totalCapacity>2000
vmInstanceUuid not null
- Any space must not be contained between the field name, query operator, and match value.
- For example, uuid = 25506342d1384c07b7342373a57475b9 is a wrong query condition. The correct format is uuid=25506342d1384c07b7342373a57475b9.
The relations among multiple query conditions are and. ZStack AIOS Platform supports the following 10 query operators:
=: Equal. For example,
vmInstanceUuid=c4981689088b40f98d2ade2548c323da!=: Not equal. For example,
vmInstanceUuid!=c4981689088b40f98d2ade2548c323da>: Greater than.
<: Less than.
>=: Greater than or equal.
<=: Less than or equal.
?=: in operator. This operator is used to check whether a value is within a set of values. Values in the set are separated by using commas (,). For example, check whether uuid is within a set of values.
uuid?=25506342d1384c07b7342373a57475b9,bc58d68090ac42358c0cb0fe72e3287f!?=: not int operator. This operator is used to check whether a value is not within a set of values. Values in the set are separated by using commas (,). For example, check whether name is not equal to VM1 and VM2.
name!?=VM1,VM2~=: Simple pattern matching, which is similar to the like operation in MySQL. Use % to match any number of characters, even zero characters. Use **_** to match exactly one character. For example, query a name that starts with IntelCore.
name~=IntelCore%Or query a name that starts with IntelCore and ends with 7. A character will be fuzzily matched between IntelCore and 7.
name~=IntelCore_7Here, names with IntelCoreI7 and IntelCoreM7 will be matched.
!~=: Negation of simple pattern matching. This operator is used to query a field that cannot be matched by using simple pattern matching. In addition, the match condition is the same as that of ~=.
is null: Checks whether a value is NULL.
name=nullnot null: Checks whether a value is not NULL.
name!=null
Paginated Query
start, limit, and replyWithCount can all be used in conjunction to achieve paginated queries.
- start: Specifies the first record to query.
- limit: Specifies maximum number of returned records.
- replyWithCount: If true, the query response returns both the records and the record count that meet the query condition. You can know how many times of paginated queries are required by comparing this field with the start field.
For example,
If a total of 1000 records meet the query condition, you can use the following combination:
start=0 limit=100 replyWithCount=true
Then, the API response will contain the first 100 records, and the total field is equal to 1000, indicating that a total number of 1000 records meet the query condition.
Obtaining Query Fields of a Resource
We support a large number of query conditions. The query conditions listed in this documentation are only a part of them.
You can check the queryable fields of a resource and the fields that can be queried across tables by using the autocomplete feature of zstack-cli.
For example, to query a VM instance, enter
QueryVmInstancein zstack-cli, and complete the rest of the fields by pressing the Tab key. Then, you can see the following prompt page:- >>>QueryVmInstance [Query Conditions:] allVolumes. cluster. host. image. instanceOffering. rootVolume. vmNics. zone. __systemTag__= __userTag__= allocatorStrategy= clusterUuid= cpuNum= cpuSpeed= createDate= defaultL3NetworkUuid= description= groupBy= hostUuid= hypervisorType= imageUuid= instanceOfferingUuid= lastHostUuid= lastOpDate= memorySize= name= platform= rootVolumeUuid= state= type= uuid= zoneUuid= [Parameters:] count= fields= limit= replyWithCount= sortBy= sortDirection= start= timeout=Information in the middle rows is displayed as follows:
__systemTag__= __userTag__= allocatorStrategy= clusterUuid= cpuNum= cpuSpeed= createDate= defaultL3NetworkUuid= description= groupBy= hostUuid= hypervisorType= imageUuid= instanceOfferingUuid= lastHostUuid= lastOpDate= memorySize= name= platform= rootVolumeUuid= state= type= uuid= zoneUuid=Except for both systemTag and userTag, the rest are all native fields in the VM table. You can specify them in the API query condition, and specify these fields in
fieldsto filter other fields that you do not want the API to return. For example,GET zstack/v1/vm-instances?q=cpuNum>5The sample above returns the VM instances whose CPU number is larger than 5.
GET zstack/v1/vm-instances?q=hypervisorType=KVM&fields=uuid&fields=nameThe sample above returns the VM instances whose hypervisor type is KVM. The API response will only contain the name and UUID of the KVM instances, because both uuid and name are specified in
fields.Only native fields of resources are selected by
fields. userTag, systemTag, and the following cross-table fields cannot appear infields.The first prompt row indicates which VM resources can be queried across tables with other resources. For example,
allVolumes. cluster. host. image. instanceOffering. rootVolume. vmNics. zone.In the sample above, allVolumes means all volumes, cluster means the cluster, and vmNics means the VM NICs.
If you need to check the specific fields of these resources, enter the resource name followed by a period (.), and complete the rest of the fields by pressing the Tab key.
For example,
- >>>QueryVmInstance vmNics. [Query Conditions:] vmNics.eip. vmNics.l3Network. vmNics.loadBalancerListener. vmNics.portForwarding. vmNics.securityGroup. vmNics.vmInstance. vmNics.__systemTag__= vmNics.__userTag__= vmNics.createDate= vmNics.deviceId= vmNics.gateway= vmNics.ip= vmNics.l3NetworkUuid= vmNics.lastOpDate= vmNics.mac= vmNics.metaData= vmNics.netmask= vmNics.uuid= vmNics.vmInstanceUuid=In the sample above, we entered the vmNics resource followed by a period (.) to indicate that a cross-table query will be performed. Pressing the Tab key completes the rest native fields of vmNics and other resources that can be queried cross tables.
vmNics.ip means the ip native field of a NIC.
GET zstack/v1/vm-instances?q=vmNics.ip=192.168.0.100In the sample above, we performed a cross-table query by using the ip field of the NIC table as the query condition. In the response, the VM instance whose IP address is 192.168.0.100 is returned.
Similarly, the NIC resource can be queried across tables with other resources, such as vmNics.eip.
For example, you can perform query across the NIC table and the EIP table.
GET zstack/v1/vm-instances?q=vmNics.eip.ip=192.168.0.100In the sample above, the query is performed across 3 tables. In the response, the VM instance whose EIP is 192.168.0.100 is returned.
The cross-table query allows you to perform query across resources that are logically related in the system. For example,
- >>>QueryVmInstance zone.cluster.l2Network.l3Network. [Query Conditions:] zone.cluster.l2Network.l3Network.ipRanges. zone.cluster.l2Network.l3Network.l2Network. zone.cluster.l2Network.l3Network.networkServices. zone.cluster.l2Network.l3Network.serviceProvider. zone.cluster.l2Network.l3Network.vmNic. zone.cluster.l2Network.l3Network.zone. zone.cluster.l2Network.l3Network.__systemTag__= zone.cluster.l2Network.l3Network.__userTag__= zone.cluster.l2Network.l3Network.createDate= zone.cluster.l2Network.l3Network.description= zone.cluster.l2Network.l3Network.dnsDomain= zone.cluster.l2Network.l3Network.l2NetworkUuid= zone.cluster.l2Network.l3Network.lastOpDate= zone.cluster.l2Network.l3Network.name= zone.cluster.l2Network.l3Network.state= zone.cluster.l2Network.l3Network.system= zone.cluster.l2Network.l3Network.type= zone.cluster.l2Network.l3Network.uuid= zone.cluster.l2Network.l3Network.zoneUuid=In the sample above, the query is performed across the tables of zone, cluster, L2 network, and L3 network.
- Since a resource logic has a loop, the loop path can be created. For example, assume that the VM instance is a query body, and can be queried across tables, such as using
QueryVmInstance vmNics.. Meanwhile, assume that the NIC is also a query body, and can be queried across tables with the VM instance, such as usingQueryVmNic vmInstance.. Hence, a loop path is created. - You must avoid performing the cross-table query for the loop. For example, use
QueryVmInstance vmNics.vmInstance.name=vm1to perform the cross-table query for the VM instance of name=vm1. In fact, it is totally equal to usingQueryVmInstance name=vm1. This is meaningless, because it will only generate complex SQL statements, which will lead to inefficient database queries.
- Since a resource logic has a loop, the loop path can be created. For example, assume that the VM instance is a query body, and can be queried across tables, such as using
Both systemTag and userTag are special query conditions, allowing you to query resources by using a tag.
For example, you can query a VM instance that has the staticIp:10.10.1.20 tag.
QueryVmInstance __systemTag__=staticIp:10.10.1.20
ZQL Syntax
ZQL (ZStack Query Language) is a dedicated language provided by ZStack AIOS Platform for querying cloud platform resources and services. It provides SQL-like query syntax and applies to scenarios that require complex queries.
ZQL Statement Structure
ZQL provides query statements that start with the three keywords query, count, and sum. Each statement consists of a query keyword, query fields, and clauses. The clauses supported by the query statements that start with these three keywords are slightly different. The statement structures are as follows:
Structure of a query statement that starts with the query keyword:
query queryTargetWithFunction (WHERE condition+)? restrictBy? returnWith? groupBy? orderBy? limit? offset? filterBy? namedAs?Structure of a query statement that starts with the count keyword:
count queryTargetWithFunction (WHERE condition+)? restrictBy? groupBy? orderBy? limit? offset? namedAs?Structure of a query statement that starts with the sum keyword:
sum queryTarget by sumByValue (WHERE condition+)? orderBy? limit? offset? namedAs?? indicates that the corresponding clause is optional.
ZQL Syntax Description
The functions and meanings of each component in a ZQL statement are as follows:
Query keywords:
- query: Queries and returns the inventory of resources, similar to
select *in SQL. For example,query vminstanceis similar toselect * from VmInstanceVO. - count: Queries and returns the number of resources that meet the query conditions, similar to
select count(*)in SQL. For example,count vminstanceis similar toselect count(*) from VmInstanceVO. - sum: Queries and returns the sum of the specified field, similar to
select sum(inv.cpuNum)in SQL. For example,sum instanceoffering.cpuNumis similar toselect sum(cpuNum) from InstanceOfferingVO.
- query: Queries and returns the inventory of resources, similar to
Query fields:
- querytarget: The target resource information to query. The resource name is formed by removing the VO suffix from the resource name and converting it to lowercase. For example, if the resource is VmInstanceVO, the resource name of querytarget is vminstance. querytarget supports querying only certain fields of a resource. For example,
query vminstance.uuid,namequeries the VM instance UUID and name. This statement is similar toselect uuid,name from VmInstanceVOin SQL. - function: The function that processes resource fields. querytarget supports specifying fields directly and specifying fields processed by functions. Currently, the query and count keywords support function processing, while subqueries do not support function processing. The function supported by ZStack AIOS Platform is
distinct. For example,query distinct(vminstance.name)queries and returns distinct VM instance names. This statement is similar toselect distinct name from VmInstanceVOorselect distinct(name) from VmInstanceVO.
- querytarget: The target resource information to query. The resource name is formed by removing the VO suffix from the resource name and converting it to lowercase. For example, if the resource is VmInstanceVO, the resource name of querytarget is vminstance. querytarget supports querying only certain fields of a resource. For example,
Query clauses:
where: Similar to the where clause in SQL, used to specify query conditions. If the query condition value is a string, enclose it in single quotation marks.
Similar to Query APIs, the query conditions specified in the where clause can be fields of the current resource or cross-table join query conditions. For example:
- In
query vminstance where name='webvm', the name field is a field of vminstance itself. - In
query vminstance where vmNics.ip='192.168.0.100', vmNics.ip is a field after automatic join query with the VmNicVO table.
- In
The where clause supports AND/OR logic and supports logical nesting with parentheses. For example:
query vminstance where (name = 'webvm' or cpuNum > 10) and description is not null
sub query: The query conditions specified in the where clause support subqueries (sub query), for example:
query vminstance where hostUuid in (query host.uuid where state = 'Disconnected') and state = 'Running'Note:
- The querytarget in a sub query clause supports selecting only one field, such as
host.uuid. An error is reported if no field or multiple fields are selected. The where clause in a sub query is the same as the where clause in a common query statement. - A sub query does not support restrict by or return with clauses, nor does it support the limit, order by, or offset keywords.
- The querytarget in a sub query clause supports selecting only one field, such as
restrict by: Used to solve resource association query issues. For example,
query eip restrict by (zone.uuid = '28818693f3924d92af2b19b2407317ff')queries EIPs in the zone whose UUID is 28818693f3924d92af2b19b2407317ff. Because EIP resources do not contain fields associated with Zone, you can specify the restrict by clause for the query.The condition name specified by restrict by has the same field query format as that in querytarget. Both use resource name.field name, such as zone.uuid.
The conditions in the restrict by clause support only AND logic. For example:
restrict by (zone.uuid = '28818693f3924d92af2b19b2407317ff', zone.name like '%east-%')
return with: Used to return attached data. Currently, two types of attached data are supported:
totalandzwatch.totalis used to specify the number of data records that meet the query conditions. For example, for thequery vminstance where cpuNum > 8 return with (total)statement, the query result returns thetotalfield value.zwatchis used to specify that monitoring data that meets the query conditions is returned. After the zwatch clause is specified in the return with clause, the zwatch query is executed together with the database query. The working mechanism is: l- Execute the database query conditions in the where clause first to obtain data that meets the query conditions.
- Inject the data returned by the query in the where clause as input conditions into the zwatch query.
For example, in the following ZQL statement, the data query is executed first to find VMs that meet the
cpuNum > 8condition, and then the UUIDs of the VMs are merged into a zwatch label and injected into the subsequent zwatch query conditions: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)})The zwatch clause starts with the
zwatchkeyword, and query conditions are placed in braces{}. The query conditions are the fields of the GetMetricData API. The parameters do not include the namespace field. This field is determined by the resource specified by querytarget. For example, vminstance represents 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;The zwatch clause usually passes the primary key of the object after query as a query parameter to the subsequent GetMetricData query. To use a non-primary-key field for a zwatch query, add the feildIndex parameter to the corresponding clause. fieldIndex=0 indicates that the first field after query is used. For example:
query faulttolerancevmgroup.primaryVmInstanceUuid return with (zwatch{resultName='cpuAverageUsedUtilization',metricName='CPUAverageUsedUtilization',offsetAheadOfCurrentTime=0,period=10,fieldIndex=0})String parameters must be marked with single quotation marks. For the labels and functions parameters of the list type, use multiple inputs. The order in the list is determined by the order in which the parameters appear, and parameters are separated by commas (,). For example:
labels='CPUNum=10', labels='CPUNum=8'The number of monitoring data records returned by the zwatch clause may be different from the number of database records that meet the where clause. For example, in the following ZQL statement, there may be 100 VMs that meet cpuNum > 8, but the zwatch clause uses the top(num=2) function, so only two monitoring data records are returned:
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)})If only monitoring data is of concern, the querytarget of ZQL should specify a field rather than the resource itself. For example, in the following ZQL statement, the returned data contains only the VM name and monitoring data, which greatly reduces the amount of data transmitted by the 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)})
The return with clause supports multiple zwatch clauses. When multiple clauses are used, specify the name of the returned data in the
reurnWithobject of the ZQL returned object by usingresultName. For example: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)})In this example, two clauses specify
resultName='zwatch1'andresultName='zwatch2'respectively, and the corresponding return values are named zwtach1 and 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: Similar to the group by clause in SQL, used to group results by resource fields. The group by clause supports only query and count queries. The by field of a sum query has the same meaning as the group by field. For example:
query vminstance group by nameis similar toselect * from VmInstanceVO group by namein SQL.count vminstance where cpuNum > 8 group by name,memorySizeis similar toselect count(*) where cpuNumin SQL.
The result format returned by
query group byis the same as that returned by a common query. For example, the return result of thequery vminstance.name return with (total) group by zoneUuidstatement is:{ "results": [ { "inventories": [ { "name": "win2016-new" } ], "total": 24 } ], "success": true }The total field value is different from the number after
group by.The return result of
count group byis different from that of a commoncount. For example, the return result of thecount vminstance group by imageUuid order by groupCount ascstatement is:{ "results": [ { "inventoryCounts": [ [ { "imageUuid": "20d8593c94934b4596af7109a1609811" }, 1 ], [ { "imageUuid": "4eabdabb64844f8eb2ae5d1aa2c44d7a" }, 2 ] ], "total": 3 } ], "success": true }Here,
inventoryCountsis an ordered map type with complex keys, namely objects of fields specified bygroup by. It is converted to this jsonArray format through json.If the
count vminstance group by imageUuid offset 2statement is executed, the return result is:{ "results": [ { "total": 3 } ], "success": true }In this result:
- Because no query result exists under the offset condition, the inventoryCounts field is null.
- The total field is still the total result before grouping.
order by: Similar to the order by clause in SQL, used to sort returned results by resource fields. For example:
query vminstance orderby cpuNum ascor
query vminstance orderby cpuNum descSorting results after count group by is supported. For example:
count vminstance groupby imageUuid orderby groupCount ascSorting results after sum is also supported. For example:
sum VolumeSnapshot.size by volumeUuid orderby size asclimit: Similar to the limit clause in SQL, used to limit the number of returned data records. For example:
query vminstance limit 100offset: Similar to the offset clause in SQL, used together with the limit clause to implement pagination. For example:
query vminstance limit 100 offset 10
If you use the sum keyword for summation queries, you can implement a summation function similar to the SQL statement select sum(xxx) ... group by yyy. For example, the following query statement sums the cpuNum and memorySize fields of vminstance respectively, and groups the data by the uuid field.
sum vminstance.cpuNum,memorySize by uuid where cpuNum >0
This statement is equivalent to the following SQL statement:
select sum(vm.cpuNum),sum(vm.memorySize) from VmInstanceVO vm where vm.cpuNum > 0
The return result is:
{
"results": [{
"inventories": [
["7dba128454014abc8a69e739f1c4e2ad", 2, 536870912],
["e889cbf61cf6434f875e80e3b1c5a92d", 4, 8589934592]
]
}]
}
Each element in the return result is an array: the first element is always the group by field specified by the by keyword, which can be used to identify the resource corresponding to the subsequent summation values. The second element and later elements are summation results, and their order is the same as the field order after the sum keyword. For example, 2 corresponds to vm.cpuNum, and 536870912 corresponds to vm.memorySize.
ZQL provides the query comparison operators has and not has, which apply to cascaded resource query scenarios:
Because cascaded resources have a one-to-many characteristic, you can use has to query results that have multiple cascaded resources at the same time. For example, query VM instances with HA paused:
query vminstance where __systemTag__ has ('ha', 'inhibitHA')has currently supports only definite values and does not support subqueries.
not has can be used to query results that do not have a certain cascaded resource. For example, query VM instances that do not use ipv4:
query vminstance where vmNics.ipVersion nothas ('4')
ZQL supports specifying multiple ZQL statements in one query to implement batch queries. Multiple ZQL statements are separated by semicolons (;).
The named as clause is supported to name ZQL statements, making it easy to view the execution result corresponding to each ZQL statement. To use the named as clause, add a string after the named as keywords as the name of the ZQL statement.
- The name of a ZQL statement must be globally unique. Otherwise, a later ZQL statement overwrites the result of an earlier statement with the same name.
- The named as clause is optional. When it is omitted, the returned result does not contain the name field, and you can identify its correspondence with the ZQL statement only by the order of results in the array.
For example:
query host named as 'host';
query zone return with (total) named as 'zone'
The return result format is as follows:
{
"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"
}]
}
ZStack AIOS Platform supports embedding API results into ZQL statements. The API is not limited to Get APIs. Query APIs can also be embedded, but the request must return synchronously. The following examples are given for different conditions or parameters:
Condition is in:
query vminstance.hostUuid where hostUuid in getapi(api='GetVmStartingCandidateClustersHosts', output='hosts.uuid', uuid='${vm1.uuid}') limit 1Condition is =:
query vminstance.hostUuid where hostUuid = getapi(api='GetVmStartingCandidateClustersHosts', output='hosts.uuid', uuid='${vm1.uuid}') limit 1Parameter is boolean:
query vminstance.hostUuid where hostUuid ingetapi(api='GetCandidateMiniHosts', output='hosts.hostname', local=true, configure=false) limit 1Parameter is list:
query vminstance.hostUuid where hostUuid ingetapi(api='GetPciDeviceCandidatesForNewCreateVm',output='inventories.uuid', clusterUuids=list('${cluster.uuid}','${vm1.uuid}')) limit 1
Use Curl to Call a ZQL Query
Curl sample:
curl http://localhost:8080/zstack/v1/zql?zql=yourZQL -X GET -H 'Connection:close' -H 'Content-Type:application/json' -H 'Authorization:OAuth SesionID'
In this sample:
- yourZQL: The ZQL statement used for the query. It must be encoded by using a URL.
- SessionID: The Sesion ID required for calling the ZQL statement, such as 376c223518e347bcbeca40d2c7c515b9.
ZQL statement sample:
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
ZQL statement return result:
{
"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": "Failover Cluster 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
}
Changing API Service Port
Assume that you need to change an API service port. For example, to change the original API service port 8080 to the API service port 8989, follow the following steps:
Go to
/usr/local/zstacktest/apache-tomcat/webapps/zstack/WEB-INF/classes/zstack.properties, and configure the following parameters in the zstack.properties configuration file:CloudBus.httpPort = 8989 RESTFacade.port = 8989Go to
/usr/local/zstacktest/apache-tomcat-8.5.35/conf/server.xml, and change port 8080 to port 8989 in the server.xml configuration file of tomcat.Run the following command to change the management node port to 8989:
zstack-ctl config_ui --mn-port 8989Restart the management node and UI.
zstack-ctl stop zstack-ctl startSpecify the port to 8989 when you are using zstack-cli.
zstack-cli --port 8989
The configured API service port must be in the valid range, and must not be in conflict with the API service port occupied by ZStack AIOS Platform.
Batch API Response
Batch API responses can be classified into two categories: responses of long jobs and responses of non-long jobs.
Non-Long Job API Response
For error responses of non-long jobs, the value of the success field in the first layer is true. The value of the success field in inner layers vary depending on the sub-task result. If a sub-task succeeded, success=true is returned. Otherwise, success=false is returned. The following shows a sample response of the APIBatchDeleteVolumeSnapshotMsg operation:
Error Response:
{
"results": [
{
"error": {
"code": "VOLUME_SNAPSHOT.1000",
"description": "Snapshot is not in correct status for operation.",
"details": "snapshot[uuid:e9c43724c6614aa488b63d6b33e30ebd, name:test1]'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:test2]'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
}
Successful Response:
{
"results": [
{
"snapshotUuid": "1c8408e0f05d4fc39465d7db27d6bc32",
"success": true
},
{
"snapshotUuid": "e071e0ec42de4323bff23993a6a236d2",
"success": true
}
],
"success": true
}
Long Job API Response
For error responses of long jobs, the value of the success field in the first layer is true. The value of the success field in inner layers vary depending on the sub-task result. If a sub-task succeeded, success=true is returned. Otherwise, success=false is returned. The following shows a sample response of the APIAddHostFromConfigFileMsg operation:
Error Response:
{
"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": "Error message: The SSH port[22] of host[10.0.231.23] is not open within 300 seconds. Connection timed out.",
"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": "A host whose management IP is [10.0.93.160] already exists."
},
"ip": "10.0.93.160",
"success": false
}
],
"success": true
}
Successful Response:
{
"results": [
{
"ip": "10.0.231.231",
"success": true
},
{
"ip": "10.0.93.160",
"success": true
}
],
"success": true
}
Conclusion
- The value of the
successfield in the first layer of the two categories of API responses istrue. - The value of the
successfield in the first layer indicates the result of a Restful API request. If the request succeeds, the value of thesuccessfield istrue. - The value of the
successfield in the inner layers indicates the result of a sub-task of a Restful API request. If a sub-task succeeds,succuess=trueis returned for the sub-task. Otherwise,succee=falseis returned for the sub-task.
API responses displayed on the UI may be modified. For example, the successCount and failCount fields may be added to the API response.
