本篇记录ovirt java sdk的使用前准备与使用中的一些坑。


0、参考文档:

(1) Ovirt官方的Java-sdk文档:https://www.ovirt.org/develop/release-management/features/infra/java-sdk/

(2) Javadoc.io的org.ovirt.engine.sdk 3.6.0.0文档:https://javadoc.io/doc/org.ovirt.engine.sdk/ovirt-engine-sdk-java/3.6.0.0


1、下载ovirt java sdk的jar包

Maven地址:https://mvnrepository.com/artifact/org.ovirt.engine.sdk/ovirt-engine-sdk-java/3.6.0.0


2、下载org.ovirt.engine.sdk所需要的依赖包

在org.ovirt.enging.sdk下载页面下方,有着一个“Compile Dependencies”表格,是sdk的依赖包。

根据表格中的信息下载相应的版本的jar包。

图片.png

(1)commons-beanutils 1.8.3:https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils/1.8.3

(2)log4j 1.2.17:https://mvnrepository.com/artifact/log4j/log4j/1.2.17

(3)httpclient 4.2:https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient/4.0


3、测试使用org.ovirt.engine.sdk

import org.ovirt.engine.sdk.Api;
import org.ovirt.engine.sdk.exceptions.ServerException;
import org.ovirt.engine.sdk.exceptions.UnsecuredConnectionAttemptError;

import java.io.IOException;
import java.security.KeyManagementException;
import java.util.List;

public class SdkTest {
    private static final String URL = "https://host/api/";
    private static final String USERNAME = "123@hao.com";        // 普通用户账号
    private static final String PASSWORD = "123456";

    @SuppressWarnings("deprecation")
    public static void main(String[] args) throws ClientProtocolException, ServerException,  
                    UnsecuredConnectionAttemptError, IOException {

        Api api = new Api(URL, USERNAME, PASSWORD);
        
        List<VM> vm = api.getVMs().list();
        int len = vm.size();
        for (int i = 0; i < len; i ++) {
            System.out.printf("%s\n", vm.get(i).getName());
        }
        
        try {
            api.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
}

* 注意:“ClientProtocolException”异常是Api类必须的,而且是在org.apache.http.client.ClientProtocolException(httpclient 4.2)中。


4、不停的ClassNotFoundException

(1)照理来说,只要将这些jar包放入buildpath中,就可以正常使用sdk了,但是实际的运行结果:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/params/HttpParams
    at org.ovirt.engine.sdk.Api.<init>(Api.java:596)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:109)
    at SdkTest.main(SdkTest.java:22)
Caused by: java.lang.ClassNotFoundException: org.apache.http.params.HttpParams
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 3 more

显示缺少了org.apache.http.params.HttpParams,但是我并没有用到这个东西!?

org.apache.http.params.HttpParams ----->>> httpcore-4.2.jar

httpcore 4.2的Maven地址:https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore/4.2


(2)加入了httpcore之后,还没完:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    at org.apache.http.impl.conn.PoolingClientConnectionManager.<init>(PoolingClientConnectionManager.java:73)
    at org.apache.http.impl.conn.PoolingClientConnectionManager.<init>(PoolingClientConnectionManager.java:99)
    at org.apache.http.impl.conn.PoolingClientConnectionManager.<init>(PoolingClientConnectionManager.java:85)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.createPoolingClientConnectionManager(ConnectionsPoolBuilder.java:314)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.createDefaultHttpClient(ConnectionsPoolBuilder.java:257)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.build(ConnectionsPoolBuilder.java:437)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:607)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:109)
    at SdkTest.main(SdkTest.java:22)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 9 more

这次缺的是org.apache.commons.logging.LogFactory。有种没完没了的感觉。

org.apache.commons.logging.LogFactory ----->>> commons-logging-1.2.jar

commons-logging 1.2的Maven地址:https://mvnrepository.com/artifact/commons-logging/commons-logging/1.2


(3)又加了jar包,再次运行程序:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
    at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:186)
    at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:158)
    at org.apache.http.client.protocol.RequestAuthenticationBase.authenticate(RequestAuthenticationBase.java:125)
    at org.apache.http.client.protocol.RequestAuthenticationBase.process(RequestAuthenticationBase.java:83)
    at org.apache.http.client.protocol.RequestTargetAuthentication.process(RequestTargetAuthentication.java:80)
    at org.apache.http.protocol.ImmutableHttpProcessor.process(ImmutableHttpProcessor.java:109)
    at org.apache.http.protocol.HttpRequestExecutor.preProcess(HttpRequestExecutor.java:176)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:516)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at org.ovirt.engine.sdk.web.ConnectionsPool.execute(ConnectionsPool.java:97)
    at org.ovirt.engine.sdk.web.HttpProxy.execute(HttpProxy.java:114)
    at org.ovirt.engine.sdk.web.HttpProxyBroker.get(HttpProxyBroker.java:415)
    at org.ovirt.engine.sdk.web.HttpProxyBroker.get(HttpProxyBroker.java:394)
    at org.ovirt.engine.sdk.Api.getEntryPoint(Api.java:653)
    at org.ovirt.engine.sdk.Api.initResources(Api.java:665)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:615)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:109)
    at SdkTest.main(SdkTest.java:22)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 19 more

是真的没完没了!?又缺了包!这次是org.apache.commons.codec.binary.Base64。到底是哪里用到了这东西???

org.apache.commons.codec.binary.Base64 ----->>> commons-codec-1.10.jar

commons-codec 1.10的Maven地址:https://mvnrepository.com/artifact/commons-codec/commons-codec/1.10


5、创建Api代理过程中的错误

(1)执行上面的代码,没有ClassNotFoundException。但是出现了500服务器错误

Exception in thread "main"
code  : 500
reason: Internal Server Error

detail: <html><head><title>Error</title></head><body>Internal Server Error</body></html>
    at org.ovirt.engine.sdk.web.HttpProxy.execute(HttpProxy.java:120)
    at org.ovirt.engine.sdk.web.HttpProxyBroker.get(HttpProxyBroker.java:415)
    at org.ovirt.engine.sdk.web.HttpProxyBroker.get(HttpProxyBroker.java:394)
    at org.ovirt.engine.sdk.Api.getEntryPoint(Api.java:653)
    at org.ovirt.engine.sdk.Api.initResources(Api.java:665)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:615)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:109)
    at SdkTest.main(SdkTest.java:25)

不知道具体原因。代码中使用的是普通账号,但是该账号和密码在ovirt engine上能成功登录。

后来使用管理员账号登录绕过了这个问题。


(2)管理员账号登录失败,因为证书验证失败

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:641)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at org.ovirt.engine.sdk.web.ConnectionsPool.execute(ConnectionsPool.java:97)
    at org.ovirt.engine.sdk.web.HttpProxy.execute(HttpProxy.java:114)
    at org.ovirt.engine.sdk.web.HttpProxyBroker.get(HttpProxyBroker.java:415)


在这里采用的解决方法是将ovirt engine的证书添加到jre的证书库中。

首先将下载好的crt证书复制到jre的安装目录下的bin目录中。

图片.png

然后,在bin目录下打开cmd,执行命令:

D:\Software\Java\jre1.8\bin>keytool -import -v -trustcacerts -alias svcloud -file pki-resource.cer -storepass changeit -keystore D:/Software/Java/jre1.8/lib/sec
urity/cacerts
所有者: CN=svcloud.casvip.com.46215, O=casvip.com, C=US
发布者: CN=svcloud.casvip.com.46215, O=casvip.com, C=US
序列号: 1000
有效期为 Wed Sep 12 10:43:25 CST 2018 至 Sun Sep 10 10:43:25 CST 2028
证书指纹:
         MD5:  35:B2:6F:79:15:29:7C:C3:39:D3:89:BC:1B:CA:08:38
         SHA1: 05:62:9C:41:42:92:2D:ED:07:86:FF:01:AD:4F:49:1E:1C:83:F3:B2
         SHA256: 99:37:BF:A9:CC:0B:FA:3C:C1:76:34:DA:71:22:02:2B:32:93:D4:D9:8B:
46:30:C6:B7:CC:CB:D9:08:B9:60:BD
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3
。。。

是否信任此证书? [否]:  y
证书已添加到密钥库中
[正在存储D:/Software/Java/jre1.8/lib/security/cacerts]

如果没报错,那么证书添加完毕。


(3)404 Not Found

Exception in thread "main"
code  : 404
reason: Not Found

detail:
    at org.ovirt.engine.sdk.web.HttpProxy.execute(HttpProxy.java:120)
    at org.ovirt.engine.sdk.web.HttpProxyBroker.get(HttpProxyBroker.java:415)
    at org.ovirt.engine.sdk.common.CollectionDecorator.list(CollectionDecorator.java:180)
    at org.ovirt.engine.sdk.common.CollectionDecorator.list(CollectionDecorator.java:154)
    at org.ovirt.engine.sdk.decorators.VMs.list(VMs.java:75)
    at SdkTest.main(SdkTest.java:27)

把URL中的api最后的“/”去掉即可。并且URL一定是以“/api”结尾的。


(4)端口错误

Exception in thread "main" java.lang.IllegalArgumentException: Port is invalid: -1
    at org.apache.http.conn.scheme.Scheme.<init>(Scheme.java:90)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.createSchemeRegistry(ConnectionsPoolBuilder.java:381)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.createPoolingClientConnectionManager(ConnectionsPoolBuilder.java:312)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.createDefaultHttpClient(ConnectionsPoolBuilder.java:257)
    at org.ovirt.engine.sdk.web.ConnectionsPoolBuilder.build(ConnectionsPoolBuilder.java:437)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:607)
    at org.ovirt.engine.sdk.Api.<init>(Api.java:109)
    at SdkTest.main(SdkTest.java:24)

在URL中的host后面添加端口即可。如果使用的端口是8080,那么就是https://host:8080/api


6、org.ovirt.engine.sdk所需要的所有jar包

D:\Desktop\org.ovirt.engine及其依赖>dir
 驱动器 D 中的卷是 软件
 卷的序列号是 DA18-EBFA

 D:\Desktop\org.ovirt.engine及其依赖 的目录

2018-10-29  15:25    <DIR>          .
2018-10-29  15:25    <DIR>          ..
2018-10-29  11:25           232,019 commons-beanutils-1.8.3.jar
2018-10-29  14:55           284,184 commons-codec-1.10.jar
2018-10-29  14:05            61,829 commons-logging-1.2.jar
2018-10-29  11:25           424,648 httpclient-4.2.jar
2018-10-29  11:38           223,282 httpcore-4.2.jar
2018-10-29  11:21           489,884 log4j-1.2.17.jar
2018-10-29  10:19         1,085,280 ovirt-engine-sdk-java-3.6.0.0.jar
               7 个文件      2,801,126 字节
               2 个目录 63,892,709,376 可用字节


在最后的时候,才发现,原来后面缺少的jar包都是sdk的依赖包的依赖包。有点绕口,看图就知道了。

(1)commons-beanutils的依赖包

图片.png

(2)log4j的依赖包

图片.png

(3)httpclient的依赖包

图片.png