使用oracle oci-java-sdk管理Oracle Cloud Infrastructure资源

Oracle Cloud Infrastructure(以下我们简称OCI)是Oracle公司提供的一套完整的云计算IaaS层服务,为用户提供了高性能的计算能力和存储能力。Oracle公司为了方便客户管理及使用OCI资源,为用户提供了不同语言版本的SDK以及命令行工具。详细内容可参考官方文档

本文主要是演示如何使用官方提供的Java SDK来管理Oracle Cloud Infrastructure资源。为了使用Java SDK,你必须满足如下要求:

  1. Oracle Cloud官网申请一个Oracle Cloud Infrastructure账号
  2. 在申请的OCI账号中创建用户,并分配合适的权限
  3. 为客户端调用API请求签名创建一对秘钥,将公钥上传至Oracle Cloud. 具体步骤可参考链接
  4. 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

  1. 首先,客户端访问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
  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);
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容