【Ovirt 笔记】RestAPI 调用机制分析和整理
2018-12-29 本文已影响0人
58bc06151329
文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
分析整理的版本为 Ovirt 4.2.3 版本。
1. 概述
RestAPI
- 一种软件架构设计风格,提供了一组设计原则和约束条件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。在 REST 中所有的东西都是资源,全部通过 URI 进行唯一标识。
- RestAPI 对资源的操作主要有以下几种方法。
方法 | 作用 |
---|---|
GET | 查看资源 |
POST | 创建资源 |
PUT | 更新资源 |
DELETE | 移除资源 |
2. 项目中 RestAPI 的使用
- 查看 RestAPI 会使用 https://<ip>/api 地址访问项目 API。
<api>
<link href="/api/capabilities" rel="capabilities"/>
<link href="/api/clusters" rel="clusters"/>
<link href="/api/clusters?search={query}" rel="clusters/search"/>
<link href="/api/datacenters" rel="datacenters"/>
<link href="/api/datacenters?search={query}" rel="datacenters/search"/>
<link href="/api/events" rel="events"/>
<link href="/api/events;from={event_id}?search={query}" rel="events/search"/>
<link href="/api/hosts" rel="hosts"/>
<link href="/api/hosts?search={query}" rel="hosts/search"/>
<link href="/api/networks" rel="networks"/>
<link href="/api/networks?search={query}" rel="networks/search"/>
<link href="/api/roles" rel="roles"/>
<link href="/api/storagedomains" rel="storagedomains"/>
<link href="/api/storagedomains?search={query}" rel="storagedomains/search"/>
<link href="/api/tags" rel="tags"/>
<link href="/api/templates" rel="templates"/>
<link href="/api/templates?search={query}" rel="templates/search"/>
<link href="/api/users" rel="users"/>
<link href="/api/users?search={query}" rel="users/search"/>
<link href="/api/groups" rel="groups"/>
<link href="/api/groups?search={query}" rel="groups/search"/>
<link href="/api/domains" rel="domains"/>
<link href="/api/vmpools" rel="vmpools"/>
<link href="/api/vmpools?search={query}" rel="vmpools/search"/>
<link href="/api/vms" rel="vms"/>
<link href="/api/vms?search={query}" rel="vms/search"/>
<link href="/api/vms/brief" rel="vms/brief"/>
<link href="/api/vms/logoff" rel="vms/logoff"/>
<link href="/api/disks" rel="disks"/>
<link href="/api/disks?search={query}" rel="disks/search"/>
<link href="/api/jobs" rel="jobs"/>
<link href="/api/storageconnections" rel="storageconnections"/>
<link href="/api/vnicprofiles" rel="vnicprofiles"/>
<link href="/api/permissions" rel="permissions"/>
......
查看资源(GET)
例如:
https://<ip>/api/datacenters/<id>
创建资源(POST)
例如:
POST https://<ip>/api/datacenters/
更新资源(PUT)
例如:
PUT https://<ip>/ovirt-engine/api/datacenters/<id>
移除资源(DELETE)
例如:
DELETE https://<ip>/api/datacenters/<id>
3. 项目中实现
- ovirt 项目 RestAPI 工程包含了 6 个模块。
模块名称 | 说明 |
---|---|
restapi-defination | RestAPI 定义模块 |
restapi-parent | Rest API 后端集成模块(包含 jaxrs、types、webapp、interface、apidoc 等模块) |
restapi-jaxrs | RestAPI 后端的资源集成模块 |
restapi-types | RestAPI 后端类型(实体)映射模块 |
restapi-webapp | RestAPI 网站(包含 RestAPI 服务器访问路径定义,一些过滤器的设置) |
restapi-apidoc | RestAPI 文档模块 |
3.1 restapi-defination 定义
- restapi-defination 模块包含了 5 个目录。如下表 (表 1)。
目录 | 说明 |
---|---|
org.ovirt.engine.api.model | 数据模型(RestAPI 实体类),初始包含了几个注解、工具类。 |
org.ovirt.engine.api.resource | 资源模块(RestAPI 资源接口),初始包含了几个通用接口。 |
org.ovirt.engine.api.rsdl | RestAPI rsdl 列表模块,包含一些工具类,封装的 rsdl 相关实体类。 |
org.ovirt.engine.api.utils | RestAPI 工具类。 |
v3 | 定义了 RestAPI v3 版本的 rsdl.xml 还有 XML schema(api.xsd、api.xjb) 文件。 |
- 该模块 org.ovirt.engine.api.model 和 org.ovirt.engine.api.resource 目录随着编译自动生成实体类型类和资源接口。
- restapi-defination 模块 pom.xml 文件中定义了插件的执行。
- 从 maven 库中拉取 model.jar 自动放置 /restapi/interface/definition/target/generated-resources/ 目录下。
<!-- Add the model .jar file as a generated resource: -->
<execution>
<id>copy-model-file</id>
<phase>generate-sources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.ovirt.engine.api</groupId>
<artifactId>model</artifactId>
<version>${model.version}</version>
<type>jar</type>
<classifier>sources</classifier>
<outputDirectory>${project.basedir}/target/generated-resources</outputDirectory>
<destFileName>model.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
model.jar
- 项目包含 ovirt 引擎 RestAPI 的规范,也称为模型。
- 可以从 https://github.com/oVirt/ovirt-engine-api-model 下载源码。
- Type 由 Java 接口表示。例如,Vm.java 文件包含 Vm 实体的规范,如下所示。
- 这些接口的方法表示数据类型的属性,包括它们的类型和名称。
@Type
public interface Vm extends VmBase {
String stopReason();
Date startTime();
Date stopTime();
...
}
- Service API 也由 Java 接口表示。例如,VmService.java 文件包含 Vm Service 的规范,如下所示。
- 操作(如 In、Out 等)表示为嵌套接口。这些嵌套接口的名称与操作的名称相对应,方法与操作的参数相对应。
@Service
public interface VmService extends MeasurableService {
interface Start {
@In Boolean pause();
@In Vm vm();
@In Boolean useCloudInit();
@In Boolean useSysprep();
@In Boolean async();
}
...
}
- Java 语言支持使用 JavaDoc 注释在代码本身中添加文档。这些注释以 /** 开始,以 */ 结束,并且可以在定义任何元素之前添加,比如接口和方法。这些 JavaDoc 注释是用于记录规范的机制。例如,可以记录 Vm 类型,如下所示。
/**
* Represents a virtual machine.
*/
@Type
public interface Vm extends VmBase {
...
}
- 可以用类似的方式记录属性,只需将 JavaDoc 注释放在表示该属性的方法的定义之前。
/**
* Represents a virtual machine.
*/
@Type
public interface Vm extends VmBase {
/**
* Contains the reason why this virtual machine was stopped. This reason is
* provided by the user, via the GUI or via the API.
*/
String stopReason();
...
}
- Service 的操作同样如此。
/**
* This service manages a specific virtual machine.
*/
@Service
public interface VmService extends MeasurableService {
/**
* This operation will start the virtual machine managed by this
* service, if it isn't already running.
*/
interface Start {
/**
* Specifies if the virtual machine should be started in pause
* mode. It is an optional parameter, if not given then the
* virtual machine will be started normally.
*/
@In Boolean pause();
...
}
...
}
- 这些 JavaDoc 注释由作为系统一部分的工具处理,并且用于自动生成参考文档。
/**
* Specifies if the virtual machine should be started in pause
* mode. It is an _optional_ parameter, if not given then the
* virtual machine will be started normally.
*
* To use this parameter with the Python SDK you can use the
* following code snippet:
*
* [source,python]
* ----
* # Find the virtual machine:
* vm = api.vms.get(name="myvm")
*
* # Start the virtual machine paused:
* vm.start(
* params.Action(
* pause=True
* )
* )
* ----
*/
@In Boolean pause();
metamodel
- 这个项目包含 ovirt 引擎 API 元模型。它是一组从 API 模型(model)读取、分析和生成代码的工具。
- 通过该工具将 model.jar 中代码转换为 JAX-RS RestAPI 应用接口。
- 可以从 https://github.com/oVirt/ovirt-engine-api-metamodel 下载源码。
- 后续提示目录除特殊说明,都是 restapi-defination 模块中目录。
- 提取 model.jar 中包含的 API 文档。
<!-- Extract the API documentation contained in the model
documentation artifact, so that it can then be added
to the generated .war file: -->
<execution>
<id>extract-model-documentation</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.ovirt.engine.api</groupId>
<artifactId>model</artifactId>
<version>${model.version}</version>
<type>jar</type>
<classifier>javadoc</classifier>
<outputDirectory>${project.basedir}/target/generated-resources</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
- 文档放在 /restapi/interface/definition/target/generated-resources/ 目录下。
- 文档访问页面为 model.html。
- 编译过程中通过
RsdlManager
类生成 rsdl 文件。- 自动生成到 /restapi/interface/definition/target/classes/v4/ 目录下。
<!-- Generate the RSDL: -->
<execution>
<id>generate-rsdl</id>
<phase>compile</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.ovirt.engine.api.rsdl.RsdlManager</mainClass>
<arguments>
<argument>${application.baseuri}</argument>
<argument>${project.build.outputDirectory}/v4/rsdl.xml</argument>
<argument>${project.build.outputDirectory}/v4/rsdl_gluster.xml</argument>
</arguments>
</configuration>
</execution>
- RsdlManager 中加载解析 rsdl_metadata.yaml 元数据资源文件,生成 rsdl。
private static final String METADATA_FILE_NAME = "/rsdl_metadata.yaml";
private static Rsdl buildRsdl(MetaData metadata, List<String> rels) throws IOException,
ClassNotFoundException {
RsdlBuilder builder = new RsdlBuilder(rels, metadata)
.description(RSDL_DESCRIPTION)
.rel(RSDL_REL)
.href(QUERY_PARAMETER + RSDL_CONSTRAINT_PARAMETER)
.schema(new SchemaBuilder()
.rel(SCHEMA_REL)
.href(QUERY_PARAMETER + SCHEMA_CONSTRAINT_PARAMETER)
.name(SCHEMA_NAME)
.description(SCHEMA_DESCRIPTION)
.build())
.generalMetadata(new GeneralMetadataBuilder()
.rel(GENERAL_METADATA_REL)
.href("*")
.name(GENERAL_METADATA_NAME)
.description(GENERAL_METADATA_DESCRIPTION)
.build());
Rsdl rsdl = builder.build();
return rsdl;
}
private static MetaData loadMetaData() throws IOException {
try (InputStream in = RsdlManager.class.getResourceAsStream(METADATA_FILE_NAME)) {
if (in == null) {
throw new IOException("Can't find metadata from resource \"" + METADATA_FILE_NAME + "\"");
}
return loadMetaData(in);
}
}
- 解析 model 并生成 XML 和 JSON 描述,XML schema 与 Java 代码。
<!-- Parse the model and generate the XML and JSON descriptions, the
XML schema and the Java code: -->
<execution>
<id>generate-code</id>
<phase>generate-sources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<classpathScope>runtime</classpathScope>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>org.ovirt.api.metamodel.tool.Main</argument>
<argument>org.ovirt.api.metamodel.tool.Tool</argument>
<argument>--model=${project.basedir}/target/generated-resources/model.jar</argument>
<argument>--in-schema=${project.basedir}/src/main/schema/api.xsd</argument>
<argument>--out-schema=${project.basedir}/target/generated-resources/v4/api.xsd</argument>
<argument>--jaxrs=${project.basedir}/target/generated-sources/model</argument>
<argument>--jaxrs-package=^services\.(.*)$=org.ovirt.engine.api.resource.$1</argument>
<argument>--jaxrs-package=org.ovirt.engine.api.resource</argument>
</arguments>
</configuration>
</execution>
- 执行 org.ovirt.api.metamodel.tool.Main 实现就是通过反射执行 org.ovirt.api.metamodel.tool.Tool 类的
run()
方法。 - 后续的 <argument> 都作为 Tool 的参数传入,下表(表 2)中说明。
- metamodel 工具中提供了
ModelAnalyzer
工具,用于解析 model。
序号 | 参数 | 说明 |
---|---|---|
1 | --model | 为模型解析器提供解析源。 |
2 | --in-schema | 指定需要解析的 XML schema 源,/src/main/schema/api.xsd 文件。 |
3 | --out-schema | 输出解析后重新生成的 XML schema,自动生成为 /restapi/interface/definition/target/generated-resources/v4/api.xsd 文件。 |
4 | --jaxrs | 设置 JAX-RS 源码目录为 /restapi/interface/definition/target/generated-sources/model,加上 5、6 设置自动生成 JAX-RS 源码。 |
5 | --jaxrs-package | 设置 JAX-RS 包路径为 /restapi/interface/definition/target/generated-sources/model/org/ovirt/engine/api/resource/$1,其中 $1 通过正则 ^services.(.*)$ 获取 model.jar 中包名称,然后一一对应生成。 |
6 | --jaxrs-package | 设置 JAX-RS 包路径为 /restapi/interface/definition/target/generated-sources/model/org/ovirt/engine/api/resource/。 |
--model
private static final String MODEL_OPTION = "model";
File modelFile = (File) line.getParsedOptionValue(MODEL_OPTION);
// Analyze the model files:
Model model = new Model();
ModelAnalyzer modelAnalyzer = new ModelAnalyzer();
modelAnalyzer.setModel(model);
modelAnalyzer.analyzeSource(modelFile);
--in-schema 与 --out-schema
private static final String IN_SCHEMA_OPTION = "in-schema";
private static final String OUT_SCHEMA_OPTION = "out-schema";
File inSchemaFile = (File) line.getParsedOptionValue(IN_SCHEMA_OPTION);
File outSchemaFile = (File) line.getParsedOptionValue(OUT_SCHEMA_OPTION);
// Generate the XML schema:
if (inSchemaFile != null && outSchemaFile != null) {
schemaGenerator.setInFile(inSchemaFile);
schemaGenerator.setOutFile(outSchemaFile);
schemaGenerator.generate(model);
}
--jaxrs 与 --jaxrs-package
private static final String JAXRS_OPTION = "jaxrs";
File jaxrsDir = (File) line.getParsedOptionValue(JAXRS_OPTION);
// Generate the JAX-RS source:
if (jaxrsDir != null) {
FileUtils.forceMkdir(jaxrsDir);
jaxrsGenerator.setOutDir(jaxrsDir);
jaxrsGenerator.generate(model);
// Generate the JAX-RS helper classes):
jaxrsHelperGenerator.setOutDir(jaxrsDir);
jaxrsHelperGenerator.generate(model);
}
- 解析 model 并将其中枚举生成为 JAXB 枚举。
<!-- Parse the model and generate replacements for the JAXB enums: -->
<execution>
<id>generate-enums-jaxb</id>
<phase>process-sources</phase> <!-- TODO: REVISIT phase -->
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<classpathScope>runtime</classpathScope>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>org.ovirt.api.metamodel.tool.Main</argument>
<argument>org.ovirt.api.metamodel.tool.EnumGenerationToolJaxb</argument>
<argument>--model=${project.basedir}/target/generated-resources/model.jar</argument>
<argument>--xjc=${project.basedir}/target/generated-sources/xjc-v4</argument>
</arguments>
</configuration>
</execution>
- 执行 org.ovirt.api.metamodel.tool.Main 实现就是通过反射执行 org.ovirt.api.metamodel.tool.EnumGenerationToolJaxb 类的
run()
方法。 - 后续的 <argument> 都作为 Tool 的参数传入,下表(表 3)中说明。
- metamodel 工具中提供了
ModelAnalyzer
工具,用于解析 model。
序号 | 参数 | 说明 |
---|---|---|
1 | --model | 为模型解析器提供解析源。 |
2 | --xjc | 最后生成至目录 /restapi/interface/definition/target/generated-sources/xjc-v4/ |
--xjc
// Generate the enums:
if (xjcDir != null) {
FileUtils.forceMkdir(xjcDir);
enumGenerator.setOutDir(xjcDir);
enumGenerator.generate(model);
}
- 根据 API v4 版本的 XML schema 生成 Java 代码。
- 最终生成至目录 /restapi/interface/definition/target/generated-sources/xjc-v4/
- 目录下生成的包路径为 org.ovirt.engine.api.model
- 依赖的 XML schema 文件所在目录 /restapi/interface/definition/target/generated-resources/v4/
- XML schema 文件名称为 api.xsd。
- 绑定JAXB 的配置文件(api.xjb )目录为 /src/main/schema/。
- 文件名为 api.xjb。
<!-- Generate the Java code from the XML schema of version 4 of the API: -->
<execution>
<id>xjc-v4</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<generateDirectory>${project.basedir}/target/generated-sources/xjc-v4</generateDirectory>
<generatePackage>org.ovirt.engine.api.model</generatePackage>
<extension>true</extension>
<schemaDirectory>${project.basedir}/target/generated-resources/v4</schemaDirectory>
<schemaIncludes>
<include>api.xsd</include>
</schemaIncludes>
<bindingDirectory>${project.basedir}/src/main/schema</bindingDirectory>
<bindingIncludes>
<include>api.xjb</include>
</bindingIncludes>
</configuration>
</execution>
- 根据 API v3 版本的 XML schema 生成 Java 代码。
- 最终生成至目录 /restapi/interface/definition/target/generated-sources/xjc-v3/
- 目录下生成的包路径为 org.ovirt.engine.api.v3.types。
- 依赖的 XML schema 文件所在目录 /src/main/resources/v3/
- XML schema 文件名称为 api.xsd。
- 绑定JAXB 的配置文件(api.xjb )目录为 /src/main/resources/v3/。
- 文件名为 api.xjb。
<!-- Generate the Java code from the XML schema of version 3 of the API: -->
<execution>
<id>xjc-v3</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<generateDirectory>${project.basedir}/target/generated-sources/xjc-v3</generateDirectory>
<generatePackage>org.ovirt.engine.api.v3.types</generatePackage>
<extension>true</extension>
<schemaDirectory>${project.basedir}/src/main/resources/v3</schemaDirectory>
<schemaIncludes>
<include>api.xsd</include>
</schemaIncludes>
<bindingDirectory>${project.basedir}/src/main/resources/v3</bindingDirectory>
<bindingIncludes>
<include>api.xjb</include>
</bindingIncludes>
</configuration>
</execution>
- 将生成的源码加入源码路径,便于后续编译成 class 文件。
<!-- This is needed to avoid having to manually add the generated sources
directory to the source paths in Eclipse: -->
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/xjc-v3</source>
<source>${project.build.directory}/generated-sources/xjc-v4</source>
<source>${project.build.directory}/generated-sources/model</source>
</sources>
</configuration>
</execution>
- 将需要用到的资源也加入资源路径,便于后续编译。
<!-- Include the regular resources directory and also the generated
resources, including the descriptions of the model and the XML
schema: -->
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${project.basedir}/target/generated-resources</directory>
</resource>
- 最终生成的 restapi-definition.jar 目录对应关系。
目录 | 来源 |
---|---|
org.ovirt.engine.api.model | 增加 /restapi/interface/definition/target/generated-sources/xjc-v4/org/ovirt/engine/api/model/ 目录中内容。 |
org.ovirt.engine.api.resourcel | 增加 /restapi/interface/definition/target/generated-sources/model/org/ovirt/engine/api/resource/ 目录中内容。 |
org.ovirt.engine.api.rsdl | 不变 |
org.ovirt.engine.api.utilsl | 不变 |
org.ovirt.engine.api.v3 | /restapi/interface/definition/target/generated-sources/xjc-v3/org/ovirt/engine/api/v3/types/ 目录中内容。 |
v3 | 不变 |
v4 中的 api.xsd 文件 | /restapi/interface/definition/target/generated-resources/v4/api.xsd。 |
v4 资源文件中 rsdl.xml 和 rsdl_gluster.xml 文件 | RsdlManager 类直接生成。 |
API 相关文档 | /restapi/interface/definition/target/generated-resources/ 目录下。 |
3.2 restapi-jaxrs 资源集成
- 主要完成了对 restapi-definition 资源接口定义的实现。
- 例如 restapi-definition 中生成的数据中心资源接口(DataCenterResource ),JSA-RS 应用的。
......
@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON })
public interface DataCenterResource {
@GET
default public DataCenter doGet() {
DataCenter dataCenter = get();
follow(dataCenter);
return dataCenter;
}
default public DataCenter get() {
throw new UnsupportedOperationException();
}
@PUT
@Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON })
default public DataCenter update(DataCenter dataCenter) {
throw new UnsupportedOperationException();
}
@DELETE
default public Response remove() {
throw new UnsupportedOperationException();
}
default public void follow (ActionableResource entity) {
}
@Path("storagedomains")
AttachedStorageDomainsResource getStorageDomainsResource();
@Path("clusters")
ClustersResource getClustersResource();
@Path("networks")
DataCenterNetworksResource getNetworksResource();
@Path("permissions")
AssignedPermissionsResource getPermissionsResource();
@Path("quotas")
QuotasResource getQuotasResource();
@Path("qoss")
QossResource getQossResource();
@Path("iscsibonds")
IscsiBondsResource getIscsiBondsResource();
}
- restapi-jaxrs 的对资源接口的实现。
......
public class BackendDataCenterResource extends AbstractBackendSubResource<DataCenter, StoragePool>
implements DataCenterResource {
public static final String FORCE = "force";
private final BackendDataCentersResource parent;
public BackendDataCenterResource(String id, BackendDataCentersResource parent) {
super(id, DataCenter.class, StoragePool.class);
this.parent = parent;
}
@Override
public DataCenter get() {
return performGet(QueryType.GetStoragePoolById, new IdQueryParameters(guid));
}
@Override
public DataCenter update(DataCenter incoming) {
return performUpdate(incoming,
new QueryIdResolver<>(QueryType.GetStoragePoolById, IdQueryParameters.class),
ActionType.UpdateStoragePool,
new UpdateParametersProvider());
}
@Override
public AssignedPermissionsResource getPermissionsResource() {
return inject(new BackendAssignedPermissionsResource(guid,
QueryType.GetPermissionsForObject,
new GetPermissionsForObjectParameters(guid),
DataCenter.class,
VdcObjectType.StoragePool));
}
@Override
public AttachedStorageDomainsResource getStorageDomainsResource() {
return inject(new BackendAttachedStorageDomainsResource(id));
}
@Override
public DataCenterNetworksResource getNetworksResource() {
return inject(new BackendDataCenterNetworksResource(id));
}
@Override
public ClustersResource getClustersResource() {
return inject(new BackendDataCenterClustersResource(id));
}
@Override
public QuotasResource getQuotasResource() {
return inject(new BackendQuotasResource(id));
}
@Override
public IscsiBondsResource getIscsiBondsResource() {
return inject(new BackendIscsiBondsResource(id));
}
public BackendDataCentersResource getParent() {
return parent;
}
@Override
protected DataCenter doPopulate(DataCenter model, StoragePool entity) {
return parent.doPopulate(model, entity);
}
@Override
protected DataCenter deprecatedPopulate(DataCenter model, StoragePool entity) {
return parent.deprecatedPopulate(model, entity);
}
protected class UpdateParametersProvider implements
ParametersProvider<DataCenter, StoragePool> {
@Override
public ActionParametersBase getParameters(DataCenter incoming, StoragePool entity) {
return new StoragePoolManagementParameter(map(incoming, entity));
}
}
/**
* Get the storage pool (i.e. datacenter entity) associated with the given
* cluster.
*/
@SuppressWarnings("unchecked")
public static StoragePool getStoragePool(DataCenter dataCenter, AbstractBackendResource parent) {
StoragePool pool = null;
if (dataCenter.isSetId()) {
String id = dataCenter.getId();
Guid guid;
try {
guid = new Guid(id); // can't use asGuid() because the method is static.
} catch (IllegalArgumentException e) {
throw new MalformedIdException(e);
}
pool = parent.getEntity(StoragePool.class, QueryType.GetStoragePoolById,
new IdQueryParameters(guid), "Datacenter: id=" + id);
} else {
String clusterName = dataCenter.getName();
pool = parent.getEntity(StoragePool.class, QueryType.GetStoragePoolByDatacenterName,
new NameQueryParameters(clusterName), "Datacenter: name="
+ clusterName);
dataCenter.setId(pool.getId().toString());
}
return pool;
}
/**
* Get the storage pools (i.e. datacenter entity) associated with the given
* storagedomain.
*/
@SuppressWarnings("unchecked")
public static List<StoragePool> getStoragePools(Guid storageDomainId, AbstractBackendResource parent) {
return parent.getEntity(List.class,
QueryType.GetStoragePoolsByStorageDomainId,
new IdQueryParameters(storageDomainId),
"Datacenters",
true);
}
@Override
public QossResource getQossResource() {
return inject(new BackendQossResource(id));
}
@Override
public Response remove() {
get();
StoragePoolParametersBase params = new StoragePoolParametersBase(asGuid(id));
boolean force = ParametersHelper.getBooleanParameter(httpHeaders, uriInfo, FORCE, true, false);
if (force) {
params.setForceDelete(force);
}
return performAction(ActionType.RemoveStoragePool, params);
}
}
3.3 restapi-types 后端类型(实体)映射
- 该模块实现了 RestAPI 实体与服务端实体的互相转换。
- 同样是数据中心资源为例。
- 服务器后端实体 StoragePool 与 RestAPI 实体 DataCenter 的互相转换。
......
public class DataCenterMapper {
@Mapping(from = DataCenter.class, to = StoragePool.class)
public static StoragePool map(DataCenter model, StoragePool template) {
StoragePool entity = template != null ? template : new StoragePool();
if (model.isSetId()) {
entity.setId(GuidUtils.asGuid(model.getId()));
}
if (model.isSetName()) {
entity.setName(model.getName());
}
if (model.isSetDescription()) {
entity.setdescription(model.getDescription());
}
if (model.isSetComment()) {
entity.setComment(model.getComment());
}
if (model.isSetLocal()) {
entity.setIsLocal(model.isLocal());
}
if (model.isSetStorageFormat()) {
entity.setStoragePoolFormatType(StorageFormatMapper.map(model.getStorageFormat(), null));
}
if (model.isSetVersion() && model.getVersion().getMajor() != null && model.getVersion().getMinor() != null) {
entity.setCompatibilityVersion(VersionMapper.map(model.getVersion()));
}
if (model.isSetMacPool() && model.getMacPool().isSetId()) {
entity.setMacPoolId(GuidUtils.asGuid(model.getMacPool().getId()));
}
if (model.isSetQuotaMode()) {
entity.setQuotaEnforcementType(map(model.getQuotaMode()));
}
return entity;
}
@Mapping(from = StoragePool.class, to = DataCenter.class)
public static DataCenter map(StoragePool entity, DataCenter template) {
DataCenter model = template != null ? template : new DataCenter();
model.setId(entity.getId().toString());
model.setName(entity.getName());
model.setLocal(entity.isLocal());
if (!StringUtils.isEmpty(entity.getdescription())) {
model.setDescription(entity.getdescription());
}
if (!StringUtils.isEmpty(entity.getComment())) {
model.setComment(entity.getComment());
}
if (entity.getStatus()!=null) {
model.setStatus(mapDataCenterStatus(entity.getStatus()));
}
if (entity.getCompatibilityVersion() != null) {
model.setVersion(VersionMapper.map(entity.getCompatibilityVersion()));
}
if (entity.getStoragePoolFormatType()!=null) {
StorageFormat storageFormat = StorageFormatMapper.map(entity.getStoragePoolFormatType(), null);
if (storageFormat!=null) {
model.setStorageFormat(storageFormat);
}
}
if (entity.getMacPoolId() != null) {
model.setMacPool(new MacPool());
model.getMacPool().setId(entity.getMacPoolId().toString());
}
if (entity.getQuotaEnforcementType() != null) {
model.setQuotaMode(map(entity.getQuotaEnforcementType()));
}
return model;
}
private static DataCenterStatus mapDataCenterStatus(StoragePoolStatus status) {
switch (status) {
case Contend:
return DataCenterStatus.CONTEND;
case Maintenance:
return DataCenterStatus.MAINTENANCE;
case NotOperational:
return DataCenterStatus.NOT_OPERATIONAL;
case NonResponsive:
return DataCenterStatus.PROBLEMATIC;
case Uninitialized:
return DataCenterStatus.UNINITIALIZED;
case Up:
return DataCenterStatus.UP;
default:
throw new IllegalArgumentException("Unknown data center status \"" + status + "\"");
}
}
@Mapping(from = QuotaEnforcementTypeEnum.class, to = QuotaModeType.class)
public static QuotaModeType map(QuotaEnforcementTypeEnum type) {
switch (type) {
case DISABLED:
return QuotaModeType.DISABLED;
case HARD_ENFORCEMENT:
return QuotaModeType.ENABLED;
case SOFT_ENFORCEMENT:
return QuotaModeType.AUDIT;
default:
throw new IllegalArgumentException("Unknown quota enforcement type \"" + type + "\"");
}
}
@Mapping(from = QuotaModeType.class, to = QuotaEnforcementTypeEnum.class)
public static QuotaEnforcementTypeEnum map(QuotaModeType type) {
switch (type) {
case DISABLED:
return QuotaEnforcementTypeEnum.DISABLED;
case ENABLED:
return QuotaEnforcementTypeEnum.HARD_ENFORCEMENT;
case AUDIT:
return QuotaEnforcementTypeEnum.SOFT_ENFORCEMENT;
default:
throw new IllegalArgumentException("Unknown quota mode type \"" + type + "\"");
}
}
}
3.4 restapi-apidoc 文档
- restapi-apidoc 模块中 jboss-web.xml 文件中定义了访问路径 /ovirt-engine/apidoc。
- 如果要通过网页上查看 API 文档,只需要访问 https://<ip>/ovirt-engine/apidoc。
<jboss-web
xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_8_0.xsd"
version="8.0">
<context-root>/ovirt-engine/apidoc</context-root>
<symbolic-linking-enabled>true</symbolic-linking-enabled>
</jboss-web>
- restapi-apidoc 模块中 web.xml 文件中定义了主页名称为 model.html。
3.5 restapi-webapp RestAPI 网站
- restapi-webapp 模块中 jboss-web.xml 文件中定义了访问路径 /ovirt-engine/api。
- restapi-webapp 模块中 web.xml 文件中定义了一些过滤器。
过滤器名称 | 作用 |
---|---|
CORSSupportFilter | 跨域支持过滤器,可以通过 ConfigValues.CORSSupport 参数设置是否支持。 |
CSRFProtectionFilter | 伪造请求恶意攻击防护,可以通过 ConfigValues.CSRFProtection 参数设置是否支持。 |
RestApiSessionValidationFilter | RestAPI session 验证。 |
SessionValidationFilter | 系统 session 验证。 |
SsoRestApiAuthFilter | 单点登录 RestAPI 用户授权。 |
SsoRestApiNegotiationFilter | 单点登录 RestAPI 协商验证。 |
VersionFilter | 访问 RestAPI 默认使用版本,ovirt-engine.conf 配置文件中定义。ENGINE_API_DEFAULT_VERSION = 4。使用 API v4 版本。 |
- 还提供了一个对 API 描述访问的 servlet。支持多种 MIME 类型。
<servlet>
<servlet-name>ModelServlet</servlet-name>
<servlet-class>org.ovirt.api.metamodel.server.ModelServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ModelServlet</servlet-name>
<url-pattern>/v4/model</url-pattern>
<url-pattern>/v4/model.xml</url-pattern>
<url-pattern>/v4/model.json</url-pattern>
<url-pattern>/v4/model.jar</url-pattern>
<url-pattern>/v4/model.zip</url-pattern>
<url-pattern>/v4/model.html</url-pattern>
</servlet-mapping>
3.6 ovirt 4.2.3 新增接口的步骤
- 以数据中心为例。
- 如果要增加实体类,需要在 model 的 types 中定义。
- @Type 设置该对象为实体接口(资源)
- @Link 设置关联的其他实体接口(资源)
- @Deprecated 设置不建议使用。
@Type
public interface DataCenter extends Identified {
Boolean local();
StorageFormat storageFormat();
Version version();
Version[] supportedVersions();
DataCenterStatus status();
QuotaModeType quotaMode();
@Link MacPool macPool();
@Link StorageDomain[] storageDomains();
@Link Cluster[] clusters();
@Link Network[] networks();
@Link Permission[] permissions();
@Link Quota[] quotas();
@Link Qos[] qoss();
@Link IscsiBond[] iscsiBonds();
}
- 枚举也需要设置为 @Type。
@Type
public enum DataCenterStatus {
UNINITIALIZED,
UP,
MAINTENANCE,
NOT_OPERATIONAL,
PROBLEMATIC,
CONTEND;
}
- 如果要增加资源接口,需要在 model 的 services 中定义。
- @Service 设置该对象为资源服务接口。
- @Out 设置该接口返回实体(资源)。
-
@In 设置该接口接收属性,例如。
- filter 是否根据用户的权限进行筛选过滤。
- async 设置是否异步执行更新。
- 实体本身,设置接收的实体(资源)。
- force 设置是否强制执行。
-
@InputDetail 定义接收的实体(资源)的属性集。
- optional 选择性参数设置。
- mandatory 强制性参数设置。
@Service
@Area("Virtualization")
public interface DataCenterService {
interface Get extends Follow {
@Out DataCenter dataCenter();
@In Boolean filter();
}
interface Update {
@InputDetail
default void inputDetail() {
optional(dataCenter().comment());
optional(dataCenter().description());
optional(dataCenter().local());
optional(dataCenter().macPool().id());
optional(dataCenter().name());
optional(dataCenter().storageFormat());
optional(dataCenter().version().major());
optional(dataCenter().version().minor());
}
@In @Out DataCenter dataCenter();
@In Boolean async();
}
interface Remove {
@In Boolean force();
@In Boolean async();
}
@Service AttachedStorageDomainsService storageDomains();
@Service ClustersService clusters();
@Service DataCenterNetworksService networks();
@Service AssignedPermissionsService permissions();
@Service QuotasService quotas();
@Service QossService qoss();
@Service IscsiBondsService iscsiBonds();
}
- 在 rsdl-metadata.yaml 文件中定义添加的接口信息,如描述,参数等,最终会生成 rsdl.xml 文件。会在输入 https://<ip>/ovirt-engine/api?rsdl 访问显示。
- name: /datacenters/{datacenter:id}|rel=update
description: update the specified data center in the system
request:
body:
parameterType: DataCenter
signatures:
- mandatoryArguments: {}
optionalArguments:
datacenter.name: xs:string
datacenter.description: xs:string
datacenter.comment: xs:string
datacenter.local: xs:boolean
datacenter.version.major: xs:int
datacenter.version.minor: xs:int
datacenter.description: xs:string
datacenter.storage_format: xs:string
datacenter.mac_pool.id: xs:string
description: update the specified data center in the system
- name: /datacenters|rel=get
description: get a list of data centers in the system
request:
urlparams:
search: {context: query, type: 'xs:string', value: 'search query', required: false}
case_sensitive: {context: matrix, type: 'xs:boolean', value: true|false, required: false}
headers:
Filter: {value: true|false, required: false}
- name: /datacenters/{datacenter:id}|rel=get
description: get the details of the specified data center in the system
request:
headers:
Filter: {value: true|false, required: false}
- name: /datacenters/{datacenter:id}|rel=delete
description: delete the specified data center in the system
request:
urlparams:
force:
context: matrix
type: xs:boolean
value: true|false
required: false
- name: /datacenters|rel=add
description: add a new data center to the system
request:
body:
parameterType: DataCenter
signatures:
- mandatoryArguments:
datacenter.local: xs:boolean
datacenter.name: xs:string
optionalArguments:
datacenter.comment: xs:string
datacenter.description: xs:string
datacenter.storage_format: xs:string
datacenter.version.major: xs:int
datacenter.version.minor: xs:int
datacenter.mac_pool.id: xs:string
description: add a new data center to the system
-
如果需要将 RestAPI 实体与服务器后端实体关联,则需要在 restapi-types 模块中增加 Mapper 映射关系。
-
如果需要输入 https://<ip>/ovirt-engine/api 显示的 API 列表中显示接口,则需要在
ApiRootLinksCreator
类中进行定义,如果只需要在 https://<ip>/ovirt-engine/api?rsdl 中显示则不需要定义。
public static Collection<DetailedLink> getLinks(String baseUri) {
Collection<DetailedLink> links = new LinkedList<>();
links.add(createLink("clusters", LinkFlags.SEARCHABLE, baseUri));
links.add(createLink("datacenters", LinkFlags.SEARCHABLE, baseUri));
links.add(createLink("events", LinkFlags.SEARCHABLE, getEventParams(), baseUri));
links.add(createLink("hosts", LinkFlags.SEARCHABLE, baseUri));
links.add(createLink("networks", LinkFlags.SEARCHABLE, baseUri));
......
- restapi-definition 模块的 org.ovirt.engine.api.model 目录中的类来自 /restapi/interface/definition/target/generated-sources/xjc-v4/org/ovirt/engine/api/model/ 目录,而该目录中大部分的源码又由 /restapi/interface/definition/target/generated-resources/v4/ 中的 api.xsd 生成。
- org.ovirt.engine.api.model 中有个类 Action 是专门用于针对动作复杂的 Java 类的,是由 api.xsd 自动生成的。
- 例如虚拟机开机操作,参数传递除了虚拟机对象 Vm 以外还需要很多其他的参数,这种情况下就可以通过 api.xsd 文件将这些参数设置给 Action 对象,最终生成的 Action 类中就包含了 Vm 等相关属性,可以通过 get 方法获取。
<xs:element name="action" type="Action"/>
<xs:complexType name="Action">
<xs:complexContent>
<xs:extension base="BaseResource">
<xs:sequence>
......
<xs:element maxOccurs="1" minOccurs="0" name="vm" type="Vm"/>
......
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
- maxOccurs 对应的是该 element 实体出现的最多次数。
- minOccurs 对应的是该 element 实体出现的最少次数。
4. 与 ovirt 3.4.5 区别
4.1 实现原理方式的区别
- ovirt 3.4.5 中未使用提供 model.jar 模型自动生成源码的方式。
- 直接在 restapi-definition 模块的 org.ovirt.engine.api.model 包中定义数据模型(RestAPI 实体类)
- 直接在 org.ovirt.engine.api.resource 包中定义资源接口(RestAPI 资源接口类)。
- 其他的模块关系保持了一致。
- org.ovirt.engine.api.model 包中的 Action 类,还是需要通过 api.xsd 生成。
- rsdl.xml 还是通过 rsdl-metadata.yaml 文件定义生成。
4.2 接口的区别
新增接口
接口 | 方法 |
---|---|
affinitylabels | add |
affinitylabels | get |
affinitylabels/{affinitylabel:id} | delete |
affinitylabels/{affinitylabel:id} | get |
affinitylabels/{affinitylabel:id} | update |
affinitylabels/{affinitylabel:id}/hosts | add |
affinitylabels/{affinitylabel:id}/hosts | get |
affinitylabels/{affinitylabel:id}/hosts/{host:id} | delete |
affinitylabels/{affinitylabel:id}/hosts/{host:id} | get |
affinitylabels/{affinitylabel:id}/vms | add |
affinitylabels/{affinitylabel:id}/vms | get |
affinitylabels/{affinitylabel:id}/vms/{vm:id} | delete |
affinitylabels/{affinitylabel:id}/vms/{vm:id} | get |
clusterlevels | get |
clusterlevels/{clusterlevel:id} | get |
clusterlevels/{clusterlevel:id}/clusterfeatures | get |
clusterlevels/{clusterlevel:id}/clusterfeatures/{clusterfeature:id} | get |
clusters/{cluster:id}/enabledfeatures | add |
clusters/{cluster:id}/enabledfeatures | get |
clusters/{cluster:id}/enabledfeatures/{enabledfeature:id} | delete |
clusters/{cluster:id}/enabledfeatures/{enabledfeature:id} | get |
clusters/{cluster:id}/externalnetworkproviders | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/getprofilestatistics | getprofilestatistics |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks | add |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks | delete |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/activate | activate |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/migrate | migrate |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/stopmigrate | stopmigrate |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id} | delete |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id} | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id}/replace | replace |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id}/statistics | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id}/statistics/{statistic:id} | get |
clusters/{cluster:id}/networkfilters | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/enabledfeatures | add |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks | add |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks | delete |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/activate | activate |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/migrate | migrate |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/stopmigrate | stopmigrate |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id} | delete |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id} | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id}/replace | replace |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id}/statistics | statistics |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/glusterbricks/{glusterbrick:id}/statistics/{statistic:id} | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/networkfilters | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/networklabels | add |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/networklabels | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/networklabels/{networklabel:id} | delete |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/networklabels/{networklabel:id} | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageserverconnections | add |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageserverconnections | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageserverconnections/{storageserverconnection:id} | delete |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageserverconnections/{storageserverconnection:id} | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageserverconnections/{storageserverconnection:id} | update |
datacenters/{datacenter:id}/storagedomains/{storagedomain:id}/disks/{disk:id}/register | register |
disks/{disk:id}/reduce | reduce |
externalvmimports | add |
groups/{group:id}/roles/{role:id} | get |
hosts/{host:id}/affinitylabels | add |
hosts/{host:id}/affinitylabels | get |
hosts/{host:id}/affinitylabels/{affinitylabel:id} | delete |
hosts/{host:id}/affinitylabels/{affinitylabel:id} | get |
hosts/{host:id}/externalnetworkproviderconfigurations | get |
hosts/{host:id}/nics/{nic:id}/networklabels | add |
hosts/{host:id}/nics/{nic:id}/networklabels | get |
hosts/{host:id}/nics/{nic:id}/networklabels/{networklabel:id} | delete |
hosts/{host:id}/nics/{nic:id}/networklabels/{networklabel:id} | get |
hosts/{host:id}/upgradecheck | upgradecheck |
imagetransfers | add |
imagetransfers | get |
imagetransfers/{imagetransfer:id} | get |
imagetransfers/{imagetransfer:id} | delete |
imagetransfers/{imagetransfer:id} | update |
imagetransfers/{imagetransfer:id}/cancel | cancel |
imagetransfers/{imagetransfer:id}/extend | extend |
imagetransfers/{imagetransfer:id}/finalize | finalize |
imagetransfers/{imagetransfer:id}/pause | pause |
imagetransfers/{imagetransfer:id}/resume | resume |
instancetypes/{instancetype:id}/nics/{nic:id} | delete |
networkfilters | get |
networkfilters/{networkfilter:id} | get |
networks/{network:id}/networklabels | add |
networks/{network:id}/networklabels | get |
networks/{network:id}/networklabels/{networklabel:id} | delete |
networks/{network:id}/networklabels/{networklabel:id} | get |
openstacknetworkproviders/{openstacknetworkprovider:id}/networks/{network:id}/import | import |
storagedomains/{storagedomain:id}/disks/{disk:id} | update |
storagedomains/{storagedomain:id}/disks/{disk:id}/reduce | reduce |
storagedomains/{storagedomain:id}/reduceluns | reduceluns |
storagedomains/{storagedomain:id}/updateovfstore | updateovfstore |
storagedomains/{storagedomain:id}/vms/{vm:id}/diskattachments | get |
templates/{template:id}/diskattachments | get |
templates/{template:id}/diskattachments/{diskattachment:id} | delete |
templates/{template:id}/diskattachments/{diskattachment:id} | get |
templates/{template:id}/nics/{nic:id} | delete |
users/{user:id}/groups | get |
users/{user:id}/roles/{role:id} | get |
vms/{vm:id}/affinitylabels | add |
vms/{vm:id}/affinitylabels | get |
vms/{vm:id}/affinitylabels/{affinitylabel:id} | delete |
vms/{vm:id}/affinitylabels/{affinitylabel:id} | get |
vms/{vm:id}/diskattachments | add |
vms/{vm:id}/diskattachments | get |
vms/{vm:id}/diskattachments/{diskattachment:id} | delete |
vms/{vm:id}/diskattachments/{diskattachment:id} | get |
vms/{vm:id}/diskattachments/{diskattachment:id} | update |
vms/{vm:id}/graphicsconsoles/{graphicsconsole:id}/proxyticket | proxyticket |
vms/{vm:id}/graphicsconsoles/{graphicsconsole:id}/remoteviewerconnectionfile | remoteviewerconnectionfile |
vms/{vm:id}/graphicsconsoles/{graphicsconsole:id}/ticket | ticket |
vms/{vm:id}/nics/{nic:id}/networkfilterparameters | add |
vms/{vm:id}/previewsnapshot | previewsnapshot |
vms/{vm:id}/undosnapshot | undosnapshot |
删除接口
接口 | 方法 |
---|---|
capabilities | get |
capabilities/{capability:id} | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id} | get response.type=GlusterVolumeProfileDetails |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks | add |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks | delete |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/activate | activate |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/migrate | migrate |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/stopmigrate | stopmigrate |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id} | delete |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id} | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id}/replace | replace |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id}/statistics | get |
clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id}/statistics/{statistic:id} | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id} | get response.type=GlusterVolumeProfileDetails |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks | add |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks | delete |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/activate | activate |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/migrate | migrate |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/stopmigrate | stopmigrate |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id} | delete |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id} | get |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id}/replace | replace |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id}/statistics | statistics |
datacenters/{datacenter:id}/clusters/{cluster:id}/glustervolumes/{glustervolume:id}/bricks/{brick:id}/statistics/{statistic:id} | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/labels | add |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/labels | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/labels/{label:id} | delete |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/networks/{network:id}/labels/{label:id} | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageconnections | add |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageconnections | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageconnections/{storageconnection:id} | delete |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageconnections/{storageconnection:id} | get |
datacenters/{datacenter:id}/iscsibonds/{iscsibond:id}/storageconnections/{storageconnection:id} | update |
datacenters/{datacenter:id}/networks/{network:id}/labels | add |
datacenters/{datacenter:id}/networks/{network:id}/labels | get |
datacenters/{datacenter:id}/networks/{network:id}/labels/{label:id} | delete |
datacenters/{datacenter:id}/networks/{network:id}/labels/{label:id} | get |
datacenters/{datacenter:id}/networks/{network:id}/permissions | add |
datacenters/{datacenter:id}/networks/{network:id}/permissions/{permission:id} | delete |
datacenters/{datacenter:id}/networks/{network:id}/permissions/{permission:id} | get |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles | add |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles | get |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles/{vnicprofile:id} | delete |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles/{vnicprofile:id} | get |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles/{vnicprofile:id}/permissions | add |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles/{vnicprofile:id}/permissions | get |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles/{vnicprofile:id}/permissions/{permission:id} | delete |
datacenters/{datacenter:id}/networks/{network:id}/vnicprofiles/{vnicprofile:id}/permissions/{permission:id} | get |
hosts/{host:id}/nics/{nic:id}/attach | attach |
hosts/{host:id}/nics/{nic:id}/detach | detach |
hosts/{host:id}/nics/{nic:id}/labels | add |
hosts/{host:id}/nics/{nic:id}/labels | get |
hosts/{host:id}/nics/{nic:id}/labels/{label:id} | delete |
hosts/{host:id}/nics/{nic:id}/labels/{label:id} | get |
networks/{network:id}/labels | add |
"networks/{network:id}/labels | get |
networks/{network:id}/labels/{label:id} | delete |
networks/{network:id}/labels/{label:id} | get |
templates/{template:id}/disks | get |
templates/{template:id}/disks/{disk:id} | delete |
templates/{template:id}/disks/{disk:id} | get |
templates/{template:id}/disks/{disk:id}/copy | copy |
templates/{template:id}/disks/{disk:id}/export | export |
vms/{vm:id}/commit_snapshot | commit_snapshot |
vms/{vm:id}/disks | add |
vms/{vm:id}/disks | get |
vms/{vm:id}/disks/{disk:id} | get |
vms/{vm:id}/disks/{disk:id} | update |
vms/{vm:id}/disks/{disk:id}/activate | activate |
vms/{vm:id}/disks/{disk:id}/deactivate | deactivate |
vms/{vm:id}/disks/{disk:id}/export | export |
vms/{vm:id}/disks/{disk:id}/move | move |
vms/{vm:id}/disks/{disk:id}/permissions | add |
vms/{vm:id}/disks/{disk:id}/permissions | get |
vms/{vm:id}/disks/{disk:id}/permissions/{permission:id} | delete |
vms/{vm:id}/disks/{disk:id}/permissions/{permission:id} | get |
vms/{vm:id}/disks/{disk:id}/statistics | statistics |
vms/{vm:id}/disks/{disk:id}/statistics/{statistic:id} | get |
vms/{vm:id}/preview_snapshot | preview_snapshot |
vms/{vm:id}/snapshots/{snapshot:id}/disks/{disk:id} | delete |
vms/{vm:id}/undo_snapshot | undo_snapshot |
修改接口
接口 | 方法 | 说明 |
---|---|---|
clusters | add | 参数增加、删除、修改 |
clusters/{cluster:id} | update | 参数增加、删除、修改 |
datacenters | add | 参数删除 |
datacenters/{datacenter:id} | delete | 参数增加、删除 |
datacenters/{datacenter:id} | update | 参数删除 |
datacenters/{datacenter:id}/clusters | add | 参数增加、删除、修改 |
datacenters/{datacenter:id}/clusters/{cluster:id} | update | 参数增加、删除、修改 |
datacenters/{datacenter:id}/storagedomains/{storagedomain:id}/disks | add | 参数增加、删除、修改 |
disks | add | 参数增加、修改、删除 |
hosts | add | 参数增加、修改、删除 |
hosts/{host:id} | delete | 参数增加、删除 |
hosts/{host:id} | get | 参数删除 |
hosts/{host:id} | update | 参数删除 |
hosts/{host:id}/deactivate | deactivate | 参数增加 |
hosts/{host:id}/install | install | 参数增加 |
hosts/{host:id}/networkattachments | add | 参数增加 |
hosts/{host:id}/networkattachments/{networkattachment:id} | update | 参数增加 |
hosts/{host:id}/nics | get | 参数增加、删除、修改 |
hosts/{host:id}/nics | add | 参数增加、删除、修改 |
hosts/{host:id}/nics/{nic:id} | get | 参数增加、删除、修改 |
hosts/{host:id}/nics/{nic:id} | update | 参数增加、删除、修改 |
hosts/{host:id}/nics/{nic:id} | delete | 参数增加、删除、修改 |
storageconnections/{storageconnection:id} | delete | 参数增加、删除 |
storagedomains | add | 参数增加、删除、修改 |
storagedomains/{storagedomain:id} | delete | 参数增加、删除 |
storagedomains/{storagedomain:id} | update | 参数增加、删除、修改 |
storagedomains/{storagedomain:id}/disks | add | 参数增加、删除、修改 |
storagedomains/{storagedomain:id}/vms/{vm:id}/import | import | 参数增加、删除、修改 |
storagedomains/{storagedomain:id}/vms/{vm:id}/register | register | 参数增加 |
templates | add | 参数增加、删除、修改 |
templates/{template:id} | update | 参数增加、删除、修改 |
templates/{template:id}/nics | add | 参数删除 |
templates/{template:id}/nics/{nic:id} | get | 参数删除 |
users/{user:id}/tags/{tag:id} | get | 参数增加、修改 |
vmpools/{vmpool:id} | update | 参数增加、修改 |
vms | add | 参数增加、删除 |
vms/{vm:id} | delete | 参数增加、删除 |
vms/{vm:id} | update | 参数增加、删除 |
vms/{vm:id}/migrate | migrate | 参数增加、删除 |
vms/{vm:id}/nics | add | 参数删除 |
vms/{vm:id}/nics/{nic:id} | update | 参数删除 |
vms/{vm:id}/start | start | 参数增加、修改 |