1. 程式人生 > >openstack4j 原始碼分析(一) 入口

openstack4j 原始碼分析(一) 入口

g# openstack4j 原始碼分析之入口

背景

去年有個整合多個openstack平臺的專案,底層是華為、華3等不同平臺的openstack環境,應用管理層為java。雖然各平臺功能與原生openstack有所增加,但總體介面風格還是openstack的邏輯。由於openstack介面眾多,一個個去適配介面的工作量巨大,所以決定基於openstack的java sdk來開發。對比了幾種常見sdk,最後決定選用openstack4j來開發。

  • Apache jclouds apache的開源sdk,大而全、雜,可以對接所有常見的雲平臺,文件較少,使用maven引入。
  • openstack-java-sdk
    由愛好者開發及維護的sdk,更新很慢,github的demo已經不能成功連線最新的openstack版本。
  • openstack4j 官網資料、文件豐富,介面上手簡單,更新快。

結構

openstack4j下面包含2個包,分別為:

  • connectors 實現了不同型別的http請求
  • core openstack4j核心包
    而core下面又分了5個資料夾:
  • apiopenstack4j所有功能的介面
  • common 公共父類
  • model sdk中用到的所有model
  • core.transport 對於http請求的處理
  • openstack 呼叫openstack的具體功能實現

入口

openstack4j的官網demo給出的入口是

OSClient.OSClientV3 os = OSFactory.builderV3()
                  .endpoint("http://127.0.0.1:5000/v3")
                  .credentials("admin", "secret", Identifier.byName("Default"))
                  .scopeToProject(Identifier.byName("admin"))
                  .authenticate();

OSFactory是一個抽象類,通過它我們可以創建出不同的OSClient,而OSClient則是我們用來操作openstack的介面類。OSClient分為V2和V3版本,對應openstack V2 與 V3版本的認證模組(Keystone)。

OSClientV2 與 OSClientV3均為OSClient介面類的內部類,通過下面的程式碼可以看到,除了在認證模組有所區別外,其他模組沒有任何區別。

    interface OSClientV2 extends OSClient<OSClient.OSClientV2> {

        Access getAccess();

        org.openstack4j.api.identity.v2.IdentityService identity();

    }
    interface OSClientV3 extends OSClient<OSClient.OSClientV3> {

        Token getToken();


        org.openstack4j.api.identity.v3.IdentityService identity();

    }

OSFactory工廠類是使用建造者模式(Builder Pattern)來將複雜的物件構造過程和主類分離的,具體的物件構造行為是由OSClientBuilder來完成,其中包含了endpoint、credentials、scopeToProject等方法來接收外界傳入的登入所需資訊。

public abstract class OSClientBuilder<R, T extends IOSClientBuilder<R, T>> implements IOSClientBuilder<R, T> {

    String endpoint;
    String user;
    String password;

    public T endpoint(String endpoint) {
        this.endpoint = endpoint;
        return (T) this;
    }

    public T credentials(String user, String password) {
        this.user = user;
        this.password = password;
        return (T) this;
    }

登入資訊儲存在OSClientBuilder物件中,然後通過authenticate()方法,根據不同的版本進行認證。

public static class ClientV2 extends OSClientBuilder<OSClientV2, IOSClientBuilder.V2> implements IOSClientBuilder.V2 {

        @Override
        public OSClientV2 authenticate() throws AuthenticationException {
            if (tokenId != null) {
                checkArgument(tenantName != null || tenantId != null,
                        "TenantId or TenantName is required when using Token Auth");
                return (OSClientV2) OSAuthenticator.invoke(new TokenAuth(tokenId, tenantName, tenantId), endpoint, perspective,
                        config, provider);
            }

            if (raxApiKey) {
                return (OSClientV2) OSAuthenticator.invoke( new RaxApiKeyCredentials(user, password), endpoint, perspective, config, provider);
            }

            return (OSClientV2) OSAuthenticator.invoke( new Credentials(user, password, tenantName, tenantId), endpoint, perspective, config, provider);
        }

    }
public static class ClientV3 extends OSClientBuilder<OSClientV3, IOSClientBuilder.V3> implements IOSClientBuilder.V3 {

      @Override
      public OSClientV3 authenticate() throws AuthenticationException {
          if (tokenId != null && tokenId.length() > 0)
              return (OSClientV3) OSAuthenticator.invoke(new KeystoneAuth(tokenId, scope), endpoint, perspective, config,
                      provider);
          return (OSClientV3) OSAuthenticator.invoke(new KeystoneAuth(user, password, domain, scope), endpoint, perspective,
                  config, provider);
      }

}

入口處的程式碼主要關聯三個類(介面),OSFactory、OSClientBuilder(IOSClientBuilder)、OSClient,由OSFactory呼叫OSClientBuilder類構建OSClient物件,然後進行認證,完成了入口處的程式碼邏輯。

可以看到,為了避免由於openstack的認證方式更改而帶來的openstack4j認證物件的劇烈改動,入口類之間的耦合很低,易於擴充套件。使用建造者模式(Builder Pattern)生成認證資訊,將複雜的構建與其表示相分離,使得同樣的構建可以建立不同的表示。對於不同的認證方式,只需要增加或者減少部分組合方法即可。

而對於大版本之間的不同,如V2和V3,則使用工廠模式(Factory Pattern),IOSClientBuilder定義一個建立物件的介面,讓其子類自己決定例項化哪一個工廠類,工廠模式使其建立過程延遲到子類進行。當出現認證版本之間的差異時,只需要在IOSClientBuilder介面類中建立自己的靜態工廠介面類,就可以輕鬆完成認證過程的更改。我們對接華為、華3等平臺時,對於不同的認證方式,就是使用這種方式,大大減少了開發量。

類圖