ZStack Logo

ZStack AIOS

SDK使用示例

面向开发者的 API 使用规范、SDK 调用方式和 AIOS 相关接口说明。

本文以查询云主机为例,介绍ZStack AIOS Java SDK和Python SDK的使用方法。

使用Java SDK查询云主机

代码如下:
package org.zstack;
 
import org.zstack.sdk.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.io.UnsupportedEncodingException;
 
/**
 * 演示如何用Java SDK 查询VM列表
 */
public class CloudSDKDemo {
    public static void main(String[] args) {
        String cloudServerHostname = "请输入管理节点IP地址";
        String accountName = "请输入账号";
        String password = "请输入账号密码";
 
        ZSClient.configure(
                new ZSConfig.Builder()
                        .setHostname(cloudServerHostname)
                        .setPort(8080)
                        .setContextPath("zstack")
                        .build()
        );
 
        String sessionId = getSessionByLoginAccount(accountName, password);
 
        QueryVmInstanceAction action = new QueryVmInstanceAction();
        action.sessionId = sessionId;
        QueryVmInstanceAction.Result result = action.call();
        result.throwExceptionIfError();
 
        List<VmInstanceInventory> vmList = result.value.getInventories();
        System.out.println(String.format("查询云主机列表成功,查询到%s台云主机",
                vmList != null ? vmList.size() : 0));
    }
 
    private static String getSessionByLoginAccount(String accountName, String password) {
        LogInByAccountAction action = new LogInByAccountAction();
        action.accountName = accountName;
        action.password = encryptToSHA512(password);
 
        LogInByAccountAction.Result result = action.call();
        result.throwExceptionIfError();
        System.out.println("登录成功");
        return result.value.getInventory().getUuid();
    }
 
    private static String encryptToSHA512(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            md.reset();
            md.update(input.getBytes("utf8"));
            BigInteger bigInteger = new BigInteger(1, md.digest());
            return String.format("%0128x", bigInteger);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
 
}
其中,需要注意以下几个方面:
  1. 代码中,以下部分需要在对应位置,填写正确的管理节点IP、账号和密码信息。
    public static void main(String[] args) {
    String cloudServerHostname = "请输入管理节点IP地址";
    String accountName = "请输入账号";
    String password = "请输入账号密码";
    ZSClient.configure(
             new ZSConfig.Builder()
                     .setHostname(cloudServerHostname)
                     .setPort(8080)
                     .setContextPath("zstack")
                     .build()
    );
  2. 代码中,以下部分为所调用API的SDK信息,调用不同API需要填写对应的SDK信息,可参考开发手册。
    QueryVmInstanceAction action = new QueryVmInstanceAction();
     action.sessionId = sessionId;
     QueryVmInstanceAction.Result result = action.call();
     result.throwExceptionIfError();
  3. 代码编写完成后,编译、运行即可。

使用Python SDK查询云主机

代码如下:
import time
import os
import sys
import traceback
import hashlib

import zstacklib.utils.log as log

# comment out next line to print detail zstack cli http command to screen.
log.configure_log('/var/log/zstack/zstack-sdk.log', log_to_console=False)

import apibinding.api_actions as api_actions
from apibinding import api
import xml.etree.cElementTree as etree
import apibinding.inventory as inventory

zstack_server_ip = os.environ['ZS_SERVER_IP']
# 请按需设置登录云平台的账户/用户名
user_name = 'admin'
# 请按需设置登录云平台的密码
user_password = 'password'
# 请指定云主机所在物理机的UUID
host_uuid = 'acb492ce8cd640c8bb73bae75ea00adf'


# Must keep.
def sync_call(apiCmd, session_uuid):
    api_instance = api.Api(host=zstack_server_ip, port='8080')
    if session_uuid:
        api_instance.set_session_to_api_message(apiCmd, session_uuid)
    (name, reply) = api_instance.sync_call(apiCmd, )
    if not reply.success: raise api.ApiError("Sync call at %s: [%s] meets error: %s." % (
        zstack_server_ip, apiCmd.__class__.__name__, api.error_code_to_string(reply.error)))
    # print("[Sync call at %s]: [%s] Success" % (zstack_server_ip, apiCmd.__class__.__name__))
    return reply


# Must keep.
def async_call(apiCmd, session_uuid):
    api_instance = api.Api(host=zstack_server_ip, port='8080')
    api_instance.set_session_to_api_message(apiCmd, session_uuid)
    (name, event) = api_instance.async_call_wait_for_complete(apiCmd)
    time.sleep(1)
    if not event.success: raise api.ApiError("Async call at %s: [%s] meets error: %s." % (
        zstack_server_ip, apiCmd.__class__.__name__, api.error_code_to_string(reply.error)))
    # print("[Async call at %s]: [%s] Success" % (zstack_server_ip, apiCmd.__class__.__name__))
    return event


# Must keep.
def login_as_admin():
    accountName = user_name
    password = user_password
    return login_by_account(accountName, password)


# Must keep.
#tag::login_by_account[]
def login_by_account(name, password, timeout=60000):
    login = api_actions.LogInByAccountAction()
    login.accountName = name
    # Login API will use encrypted password string.
    login.password = hashlib.sha512(password).hexdigest()
    login.timeout = timeout
    session_uuid = async_call(login, None).inventory.uuid
    return session_uuid
#end::login_by_account[]


# logout must be called after session isn't needed.
# Must keep.
#tag::logout[]
def logout(session_uuid):
    logout = api_actions.LogOutAction()
    logout.timeout = 60000
    logout.sessionUuid = session_uuid
    async_call(logout, session_uuid)
#end::logout[]


# Must keep.
def execute_action_with_session(action, session_uuid, async=True):
    if session_uuid:
        action.sessionUuid = session_uuid
        if async:
            evt = async_call(action, session_uuid)
        else:
            evt = sync_call(action, session_uuid)
    else:
        session_uuid = login_as_admin()
        try:
            action.sessionUuid = session_uuid
            if async:
                evt = async_call(action, session_uuid)
            else:
                evt = sync_call(action, session_uuid)
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            raise e
        finally:
            # New login must be logout. If the active login session
            # exceed the limit, no account login is allowed.
            # The default active logined session limit is  500.
            logout(session_uuid)

    return evt


# All Query API need conditions. This help to generate common conditions.
# The op including: =, >, <, in, not in, like etc.
def gen_query_conditions(name, op, value, conditions=[]):
    new_conditions = [{'name': name, 'op': op, 'value': value}]
    new_conditions.extend(conditions)
    return new_conditions


#tag::query_zone[]
def query_zone(conditions=[], session_uuid=None):
    action = api_actions.QueryZoneAction()
    action.timeout = 3000
    action.conditions = conditions
    evt = execute_action_with_session(action, session_uuid)
    print 'Zone infomation: %s ' % evt.inventories
    return evt.inventories
#end::query_zone[]


def query_vm_by_host(host_uuid, conditions=[], session_uuid=None):
    action = api_actions.QueryVmInstanceAction()
    action.conditions = gen_query_conditions('hostUuid', '=', host_uuid, conditions)
    evt = execute_action_with_session(action, session_uuid)
    return evt.inventories


if __name__ == '__main__':
    session_uuid = login_as_admin()
    vm_list = query_vm_by_host(host_uuid, session_uuid=session_uuid)
    for vm in vm_list:
        print '查询到的云主机[uuid:%s]\n' % vm.uuid
    logout(session_uuid)
按照以下步骤运行代码示例文件:
  1. 在以上代码示例中,设置登录云平台的账户/用户名、密码、以及云主机所在物理机的UUID。
  2. 执行python $代码示例文件全路径命令查询云主机。
其中,需要注意以下几个方面:
  • 在调用ZStack AIOS API之前,需要确保已获取一个登陆Session的UUID。Session使用完毕后 , 需调用对应的logout API退出Session。
    说明: 系统已预设登录Session的阈值,默认为500。若在短时间内大量调用登陆API且不退出登陆 , 达到阈值后会导致无法登陆新的Session。
  • 登录ZStack AIOS对应的API代码:
    def login_by_account(name, password, timeout=60000):
        login = api_actions.LogInByAccountAction()
        login.accountName = name
        # Login API will use encrypted password string.
        login.password = hashlib.sha512(password).hexdigest()
        login.timeout = timeout
        session_uuid = async_call(login, None).inventory.uuid
        return session_uuid
    说明: 登陆API使用的秘钥为经过sha512加密过的密文。
  • 登出ZStack AIOS对应的API代码:
    def logout(session_uuid):
        logout = api_actions.LogOutAction()
        logout.timeout = 60000
        logout.sessionUuid = session_uuid
        async_call(logout, session_uuid)
  • 查询云主机对应的API代码:
    def query_zone(conditions=[], session_uuid=None):
        action = api_actions.QueryZoneAction()
        action.timeout = 3000
        action.conditions = conditions
        evt = execute_action_with_session(action, session_uuid)
        print 'Zone infomation: %s ' % evt.inventories
        return evt.inventories
  • 登录/登出/查询类API参数和返回值解析:
    • session_uuid 为可传入的参数 , 支持用户复用已登陆的 Session。
    • execute_action_with_session 函数是一个封装过的 API, 可以帮助执行所有ZStack AIOS的函数 , 若不传入 session_uuid , 该函数可确保执行 API 前后完成系统的登入和登出。因此建议用户使用该函数完成 API 调用。
    • 所有查询类API均需通过action.conditions参数设置数组结构的查询条件,例如action.conditions = ["name=TestZone","state=Enabled"]。若希望获取全部资源信息 , 可将参数设置为空数组。详细可参考查询 API
    • API的返回值表示API的执行结果,例如 查询类API返回值为evt.inventories,为数组类型。 用户可以使用count获取该数组的大小 , 并使用python数组的使用方式完成数据调用。对于大部分非查询类API,ZStack AIOS返回对象类型数据 , 例如创建云主机 (CreateVmInstanceAction), 返回值为evt.inventory。详细可参考API使用规范