使用oracle oci-java-sdk管理Oracle Cl
Oracle Cloud Infrastructure(以下我们简称OCI)是Oracle公司提供的一套完整的云计算IaaS层服务,为用户提供了高性能的计算能力和存储能力。Oracle公司为了方便客户管理及使用OCI资源,为用户提供了不同语言版本的SDK以及命令行工具。详细内容可参考官方文档
本文主要是演示如何使用官方提供的Java SDK来管理Oracle Cloud Infrastructure资源。为了使用Java SDK,你必须满足如下要求:
- 去Oracle Cloud官网申请一个Oracle Cloud Infrastructure账号
- 在申请的OCI账号中创建用户,并分配合适的权限
- 为客户端调用API请求签名创建一对秘钥,将公钥上传至Oracle Cloud. 具体步骤可参考链接
- Java 8(如果是Java 7,可参考Java 7的配置)
接下来我们可以开始使用oci-java-sdk编写代码。由于oci-java-sdk没有发布到maven central仓库,我们目前只能把代码下载到本地,通过Maven工具编译到Maven本地仓库。如何使用Maven工具编译发布到本地可以自行百度或google。然后使用IDE创建一个Maven 工程,配置oci-java-sdk的dependency内容。
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-full</artifactId>
<version>1.3.3</version>
</dependency>
因为OCI提供很多种Cloud Service的服务,这里使用Block Volume演示资源的增删改查操作。
OCI SDK目前支持的service:
Audit
Container Engine for Kubernetes
Core Services (Networking, Compute, Block Volume)
Database
DNS
Email Delivery
File Storage
IAM
Load Balancing
Object Storage
Search
Key Management
- 首先,客户端访问OCI需要经过身份验证确认,才能对OCI资源进行访问操作。在OCI SDK中通过AuthenticationDetailsProvider接口提供身份验证服务, 它有两个实现类,SimpleAuthenticationDetailsProvider和ConfigFileAuthenticationDetailsProvider.
- SimpleAuthenticationDetailsProvider
该类通过建造者模式,把必要的参数通过方法显示的传入构造一个Authentication provider。
String tenancyOcid = "ocid1.tenancy.oc1..aaaaaaaadkoovy5roxsjqrvbw7eykpgsfm2tb6yxvbcvezsvugac6nnsifiq";
String userFingerprint = "09:e4:86:07:74:59:8a:94:5f:7f:06:4e:cc:ae:9e:16";
String userOcid = "ocid1.user.oc1..aaaaaaaaneia4mf6ftdjims3upmi3ycm5yamf6xr4u5j6b4iacvl4idiw2va";
String userPrivateKeyPath = "/Users/xin2012/.oci/oci_api_key.pem";
AuthenticationDetailsProvider provider = SimpleAuthenticationDetailsProvider.builder()
.tenantId(tenancyOcid)
.userId(userOcid)
.fingerprint(userFingerprint)
.privateKeySupplier(new SimplePrivateKeySupplier(userPrivateKeyPath))
.build();
- ConfigFileAuthenticationDetailsProvider
创建一个客户端的配置文件,通过读取改配置文件内容创建一个Authentication provider
String CONFIG_LOCATION = "~/.oci/config";
String CONFIG_PROFILE = "DEFAULT"
ConfigFile configFile = parse(configurationFilePath, profile);
AuthenticationDetailsProvider provider = new ConfigFileAuthenticationDetailsProvider(configFile);
config文件内容如下
[DEFAULT]
user=ocid1.user.oc1..aaaaaaaaccvkann2zmuo3vhjag7me5pxnliwf3uyq2qzmnxxsqraoewengba
fingerprint=1d:c4:ef:f9:f5:d9:fe:90:59:ee:07:28:d6:f0:3b:28
key_file=~/.oci/oci_api_key.pem
tenancy=ocid1.tenancy.oc1..aaaaaaaaeweu65zquhnahe4gprwnvytld6pimbnt5ul7muol7ew3bwqztrwq
region=us-ashburn-1
- 使用SDK管理Block Volume
在OCI SDK中,对于每种service都有相应的类,通过建造者模式来创建相对应的操作类,例如创建Storage Volume操作:
public void createVolume(String displayName, String availabilityDomain, String compartmentId, Long size) {
try {
//Create Volume
CreateVolumeResponse createVolumeResponse =
blockstorage.createVolume(
CreateVolumeRequest.builder()
.createVolumeDetails(
CreateVolumeDetails.builder()
.displayName(displayName)
.availabilityDomain(availabilityDomain)
.compartmentId(compartmentId)
.sizeInGBs(size)
.build())
.build());
Volume volume = createVolumeResponse.getVolume();
//Waite for volume creation complete
BlockstorageWaiters waiter = blockstorage.getWaiters();
GetVolumeResponse getVolumeResponse = waiter.forVolume(
GetVolumeRequest.builder().volumeId(volume.getId()).build(),
Volume.LifecycleState.Available)
.execute();
} catch (BmcException e) {
System.out.println("Failed during blockstorage creation");
} catch (Exception e) {
System.out.println("Failed while waiting block volume creation");
}
}
在上面的例子中我们可以看到,首先通过CreateVolumeDetails的builder来构造创建的Volume所需要的信息,然后通过CreateVolumeRequest.builder()的build方法,根据构造的VolumeDetail来创建create volume的请求。Block storage 客户端将创建Storage的request发送到OCI服务端创建Volume。
在OCI SDK提供的API中,对于其他资源的操作都是如此模式,如果你要对某个资源做操作,那么就有一个对应的资源造作的请求,例如创建 Volume ->CreateVolumeRequest, 列出Volume -> ListVolumesRequest,然后通过资源的client将请求发送到OCI server端处理。下面是一个完整的Storage Volume增删改查操作的例子。
package net.xin2012.oci;
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
import com.oracle.bmc.auth.SimplePrivateKeySupplier;
import com.oracle.bmc.core.Blockstorage;
import com.oracle.bmc.core.BlockstorageClient;
import com.oracle.bmc.core.BlockstorageWaiters;
import com.oracle.bmc.core.model.CreateVolumeDetails;
import com.oracle.bmc.core.model.UpdateVolumeDetails;
import com.oracle.bmc.core.model.Volume;
import com.oracle.bmc.core.requests.*;
import com.oracle.bmc.core.responses.CreateVolumeResponse;
import com.oracle.bmc.core.responses.GetVolumeResponse;
import com.oracle.bmc.core.responses.ListVolumesResponse;
import com.oracle.bmc.identity.Identity;
import com.oracle.bmc.identity.IdentityClient;
import com.oracle.bmc.identity.requests.ListAvailabilityDomainsRequest;
import com.oracle.bmc.model.BmcException;
public class BlockstorageExample {
private Blockstorage blockstorage;
public void setBlockstorage(Blockstorage blockstorage) {
this.blockstorage = blockstorage;
}
public Blockstorage getBlockstorage() {
return this.blockstorage;
}
public GetVolumeResponse createVolume(String displayName, String availabilityDomain, String compartmentId, Long size) {
try {
//Create Volume
CreateVolumeResponse createVolumeResponse =
blockstorage.createVolume(
CreateVolumeRequest.builder()
.createVolumeDetails(
CreateVolumeDetails.builder()
.displayName(displayName)
.availabilityDomain(availabilityDomain)
.compartmentId(compartmentId)
.sizeInGBs(size)
.build())
.build());
Volume volume = createVolumeResponse.getVolume();
//Waite for volume creation complete
return waitForVolumeActionToComplete(blockstorage, volume.getId(), Volume.LifecycleState.Available);
} catch (BmcException e) {
System.out.println("Error during blockstorage creation, detailed message is: \n " + e.getMessage());
} catch (Exception e) {
System.out.println("Failed while waiting block volume creation in creation stage, detailed message is : \n " + e.getMessage());
}
return null;
}
public void deleteVolume(String volumeId) throws Exception {
blockstorage.deleteVolume(
DeleteVolumeRequest.builder().volumeId(volumeId).build());
try {
waitForVolumeActionToComplete(blockstorage, volumeId, Volume.LifecycleState.Terminated);
} catch (Exception e) {
System.out.println("Error while waiting block volume creation in terminated stage, detailed message is: \n " + e.getMessage());
throw e;
}
}
public GetVolumeResponse updateVolume(String volumeId, Long updatedVolumeSize) throws Exception {
try {
blockstorage.updateVolume(UpdateVolumeRequest.builder()
.volumeId(volumeId)
.updateVolumeDetails(UpdateVolumeDetails.builder()
.sizeInGBs(updatedVolumeSize)
.build())
.build());
return waitForVolumeActionToComplete(blockstorage, volumeId, Volume.LifecycleState.Available);
} catch (BmcException e) {
System.out.println("Error during blockstorage update, detailed message is: \n " + e.getMessage());
throw e;
} catch (Exception e) {
System.out.println("Error while waiting blockstorage in available stage, detailed message is: \n " + e.getMessage());
throw e;
}
}
public ListVolumesResponse listVolumes(String compartmentId) {
try {
return blockstorage.listVolumes(ListVolumesRequest.builder().compartmentId(compartmentId).build());
} catch (BmcException e) {
System.out.println("Error during blockstorage list request, detailed message is: \n " + e.getMessage());
throw e;
}
}
private GetVolumeResponse waitForVolumeActionToComplete(
Blockstorage blockstorage,
String volumeId,
Volume.LifecycleState targetLifecycleState) throws Exception {
BlockstorageWaiters waiter = blockstorage.getWaiters();
return waiter.forVolume(
GetVolumeRequest.builder().volumeId(volumeId).build(),
targetLifecycleState)
.execute();
}
public String getAvailableDomain(Identity identity, String compartmentId) {
String availabilityDomain =
identity
.listAvailabilityDomains(
ListAvailabilityDomainsRequest.builder().compartmentId(compartmentId).build())
.getItems()
.stream()
.map(ad -> ad.getName())
.findAny()
.orElseThrow(() -> new RuntimeException("AD List cannot be empty"));
return availabilityDomain;
}
public static void main(String[] args) {
String tenancyOcid = "ocid1.tenancy.oc1..aaaaaaaadkoovy5roxsjqrvbw7eykpgsfm2tb6yxvbcvezsvugac6nnsifiq";
String userFingerprint = "09:e4:86:07:74:59:8a:94:5f:7f:06:4e:cc:ae:9e:16";
String userOcid = "ocid1.user.oc1..aaaaaaaaneia4mf6ftdjims3upmi3ycm5yamf6xr4u5j6b4iacvl4idiw2va";
String userPrivateKeyPath = "/Users/xin2012/.oci/oci_api_key.pem";
String compartmentid = "ocid1.tenancy.oc1..aaaaaaaadkoovy5roxsjqrvbw7eykpgsfm2tb6yxvbcvezsvugac6nnsifiq";
AuthenticationDetailsProvider provider = SimpleAuthenticationDetailsProvider.builder()
.tenantId(tenancyOcid)
.userId(userOcid)
.fingerprint(userFingerprint)
.privateKeySupplier(new SimplePrivateKeySupplier(userPrivateKeyPath))
.build();
Blockstorage blockstorage = new BlockstorageClient(provider);
BlockstorageExample blockstorageExample = new BlockstorageExample();
blockstorageExample.setBlockstorage(blockstorage);
Identity identity = new IdentityClient(provider);
String ad = blockstorageExample.getAvailableDomain(identity, compartmentid);
blockstorageExample.createVolume("displayName", ad, compartmentid, 50L);
}
}