目次

今回はSDKを使ってオブジェクトストレージを操作します。

OpenStackには様々な言語に合わせてSDKが用意されています。一覧は以下のリンクから確認できますが、今回使うのはPHP向けのphp-opencloudです。

SDKs – OpenStack
php-opencloud

php-opencloudを使う準備

php-opencloudを使うにはPHP5.3.3以降とcURL Extensionが必要になります。あらかじめインストールしておいてください。

SDKをインストールするには、composerを使ってインストールします。方法はオフィシャルのドキュメントにあるとおりです。適当な空のディレクトリを作成し、その中で以下のコマンドを実行してください。

# composerをインストール
 curl -sS https://getcomposer.org/installer | php

# SDKをインストール
 ./composer.phar require rackspace/php-opencloud:dev-master

これで準備完了です。

php-opencloudを使う

サンプルコードと一緒にご覧ください。今回もアカウント情報や認証URLなどはconfig.phpにまとめて定義されています。

container-list.php

// SDKをロード
require_once 'vendor/autoload.php';

// OpenCloudOpenstack名前空間を使う
use OpenCloudOpenstack;
use GuzzleHttpExceptionClientErrorResponseException;

// クライアントを作成
$client = new OpenStack(
    'https://ident-r1nd1001.cnode.jp/v2.0',
    array(
        'tenantName' => TENANT_NAME,
        'username' => USERNAME,
        'password' => PASSWORD
    )
);

名前空間をインポートして、OpenStackクラスのインスタンスを作成します。コンストラクタの第一引数には認証エンドポイントURL、第二引数には配列で認証情報を渡します。

Guzzleという見慣れないものが出てきました。これはPHPで書かれたHTTPクライアントで、イベント駆動な仕組みがあり、特にREST APIやOAuthなどWebサービスを扱う実装をする際に便利です。php-opencloudは内部的にGuzzleを使用しており、HTTPのレスポンスやHTTPエラーなどがGuzzleのオブジェクトで返ってくることがあります。

Guzzle

// Swiftサービスを取得する
try {
    $service = $client->objectStoreService('swift', 'RegionOne');

} catch(ClientErrorResponseException $ex) {
    // 認証に失敗するとHTTP 401エラーとなり、ClientErrorResponseExceptionが投げられる
    throw $ex;
}

OpenStackには様々なサービスが含まれています。$clientオブジェクトには、それぞれのサービスを扱うためのオブジェクトを取得するメソッドがあり、オブジェクトストレージを使う場合はobjectStoreService()です。

これらのメソッドを呼ぶと、ここで初めて認証処理が実行されます(これはSDK内部で自動的に行われます)。ユーザ名やパスワードが間違っていると、HTTP 401エラーとなり例外が投げられます。この認証処理はauthenticate()というメソッドに実装されていて、明示的に呼ぶこともできます。

// コンテナの一覧
$containers = $service->listContainers();
foreach($containers as $c) {
    echo $c->getName() . "n";
}

コンテナの一覧はlistContainers()メソッドで取得できます。

次にオブジェクトを取得するプログラムを見てみましょう。Swiftサービスを取得するところまでは共通です。

object-download.php

// コンテナを取得
$container = $service->getContainer('test-conoha');

// オブジェクトを取得
$object = $container->getObject('test.txt');

// オブジェクトのコンテンツ部分を取得
// $contentはGuzzleHttpEntityBodyオブジェクトです。
$object_content = $object->getContent();
$object_content->rewind();

$stream = $object_content->getStream();
$content = stream_get_contents($stream);
echo $content;

オブジェクトのコンテンツ部分を取得はすこし複雑です。GuzzleHttpEntityBodyオブジェクトからコンテンツを取得するときに、ストリームを扱う必要があるからです。ストリームはPHPのリソース型の変数で、fopen()などの返り値などがわかりやすい例です。要はファイルポインタです。rewind()してポインタの位置を先頭に移動させ、getStream()でストリームを取得 、stream_get_contents()でストリームの内容を変数に書き込みます。

次にオブジェクトのアップロードです。

object-upload.php

// オブジェクトをアップロード
$content = 'ConoHa_TEST';
$fp = tmpfile();
fwrite($fp, $content);
rewind($fp);
$container->uploadObject('test2.txt', $fp);

オブジェクトをアップロードする場合、一度ファイルに書き込んでからそのファイルポインタを渡します。tmpfile()は一時ファイルを作成してそのファイルポインタを返す、PHPの組み込み関数です。スクリプト終了時に処理系が一時ファイルを削除してくれます。

以上、3つのサンプルを通してSDKの使用例をご紹介しましたが、REST APIを意識することなく直感的に実装することができます。

オブジェクトストレージのいろいろな機能

SDKを使えるようになったことで、オブジェクトストレージの操作がとても容易になりました。別の機能についてもご紹介します。

ラージオブジェクト

ConoHaオブジェクトストレージには、1オブジェクトあたりの上限サイズはありません。しかし、1オブジェクトが5GBを超える場合は、分割アップロードを行う必要があります。

php-opencloudを使うと、このオブジェクトの分割を内部的に行ってくれるので、特に意識することなく大きなオブジェクトを扱えます。

large-object-upload.php

// ラージオブジェクトをアップロードする
$options = array(
    // アップロードする名前
    'name' => 'large-object.dat',

    // アップロードするファイルのパス
    'path' => 'large-object'
);

$transfer = $container->setupObjectTransfer($options);
$transfer->upload();	

オブジェクトの有効期限を設定する

オブジェクトには有効期限を設定することが可能です。有効期限を設定したオブジェクトは、期限が切れると自動的にオブジェクトストレージ上から削除されます。

有効期限を設定するには、HTTPヘッダーのX-Delete-AtかX-Delete-Afterを使います。前者は指定した時刻にオブジェクトが削除され、後者は指定した秒数が経過した後にオブジェクトが削除されます。HTTPヘッダーはuploadObject()メソッドの第三引数に指定します。

expiring-object-upload.php

// 期限付きオブジェクトをアップロード
$expire = new DateTime();
$expire->add(new DateInterval('PT10S'));

$headers = array(
    // 指定した時刻に抹消されるされる
    'X-Delete-At'  => $expire->format('U')

    // 指定した秒数を経過すると削除される
    //'X-Delete-After'  => 30
);

$content = 'ConoHa_TEST';
$fp = tmpfile();
fwrite($fp, $content);
rewind($fp);
$container->uploadObject('test2.txt', $fp, $headers);

指定時間になると、コントロールパネルなどからオブジェクトが消えていることを確認できます。

フォルダを作る

本来、オブジェクトストレージには階層構造がありません。全てのオブジェクトはフラットに格納され、IDによって識別されます。しかし、擬似的なフォルダを作る機能も備わっており、既存のファイルシステムと同じような管理をすることもできます。ConoHaコントロールパネル上でも、一般的な階層構造として表示されます。

疑似フォルダを作るには、Content-Typeをapplication/directoryにして0バイトのオブジェクトをアップロードします。

folder-example.php

// 疑似フォルダを作成
$folder_name = 'test-folder';
$headers = array(
    'Content-Type' => 'application/directory'
);
$fp = tmpfile();
$container->uploadObject($folder_name, $fp, $headers);

// フォルダ内にオブジェクトをアップロード
$content = 'ConoHa_TEST';
$fp = tmpfile();
fwrite($fp, $content);
rewind($fp);
$container->uploadObject($folder_name . '/test3.txt', $fp);

コンテナやオブジェクトを公開する(HTTPアクセス)

今まで見てきたように、オブジェクトストレージ内のコンテナやオブジェクトにアクセスするには、ユーザ名/パスワードによる認証や、トークンを渡す必要があります。これはコンテナやオブジェクトに対し、デフォルトでアクセスコントロール(ACL)が設定されるためです。

コンテナを作成するときに個別にACLを設定することで、コンテナやオブジェクトへの認証なしでのアクセスを可能にできます。HTTPリクエストヘッダーにX-Web-ModeとX-Container-Readを設定します。rlistingsフラグを設定すると、コンテナに対するGETリクエストで、オブジェクトの一覧を返すようになります。

container-publicly.php

// コンテナを作成する。
// 認証無しでの読み取りを可能にする。
$headers = array(
    'X-Web-Mode' => 'true',
    'X-Container-Read' => '.r:*,.rlistings'
);
$url = $service->getUrl('pubcon');
$cli = $service->getClient();
$cli->put($url, $headers)
    ->send();

まとめ

SDKを使用すると、REST APIをそのまま実装するより、ずいぶんと少ないコード量で実装することができます。加えて、オブジェクトストレージの機能がメソッドとして抽象化されているので、より直感的にコードが書けます。ただ、応用的な使い方をすると、HTTPヘッダーをそのまま指定するところなどもあり、REST APIの理解が必要になってきます。

オブジェクトストレージには、単純にデータを保存する以外に、いろいろな機能があります。特にコンテナの公開機能は、Webアプリケーションやスマートフォンアプリのバックエンドで使うのに、とても有効な機能です。

問題は解決できましたか?

お役立ち情報

ConoHaではサポートコンテンツの他にも以下のようなお役立ち情報をご用意しております。ぜひご活用ください。