このはちゃん可愛い!!
ディスク拡張とオブジェクトストレージ
ConohaのVPSプランは色々あるんですが、どのプランでもディスク容量は50Gです。遊び用として使うには十分な容量なんですが、画像とか動画を配信したいな~って思うと全く足りませんよね。ConohaはスケーラブルなVPSなので、あとから簡単に拡張出来ます。早速SSDを拡張しましょう
プラン | 月額 | 1時間あたり |
---|---|---|
200G | 2,500円 | 3.5円 |
500G | 4,500円 | 6.3円 |
面倒くさいことが嫌いな方、上記の値段と容量に満足できる方、お金で解決することを厭わない方は素直にディスク拡張しておきましょう。単純に楽です。
さて、オブジェクトストレージのプランを見てみましょう...
プラン | 月額 | 1時間あたり |
---|---|---|
100GB毎 | 450円 | 0.7円 |
安い!
この値段と容量にあっさり食いついた私でしたが、めっちゃ大変だったので備忘録を残しておきます...w
オブジェクトストレージってなんなの?
早見表
名前 | アクセス方法 | お値段 | 難易度 | FTP転送 |
---|---|---|---|---|
ディスク拡張 | ローカルアクセス | 高い | 簡単 | ○ |
オブジェクトストレージ | REST_API(OpenStack準拠) | 安い | 難しい | △(要専用ソフト) |
AWS触ったことがある人なら、バケットと言えば分かると思います。
簡単に言ってしまうと凄く高機能なクラウドストレージですね。何をするにもAPIを使ってアクセスするので、言語、環境、場所を問わずにデータアクセスが出来ます。
正直SSDの拡張とは何から何まで全く違うので、無理っぽいな...って思ったら辞めておいたほうが良いです。以後はそれでもConohaちゃんのオブジェクトストレージとダンスしたい紳士のための内容になっています。
前提条件
- Conohaオブジェクトストレージを契約していること
今回使う言語とかツールとか環境とか
- CentOS7
- python3.7
- python-swiftclient
やること
- マニュアルを見ながらやろう
- python-swiftclientのインストール
pip install python-swiftclient
- 環境変数の設定
- pythonでオブジェクトストレージを操作する
- アクセストークンの取得
- metadataの追加、削除
X-Container-Meta-Access-Control-Allow-Origin
- コンテナの取得
- オブジェクトの取得
マニュアルを見ながらやろう
conohaはドキュメントが少ないことで有名です
ドキュメントが用意されているので、それらを参照して作業を進めていきましょう。swift
コマンドのインストール、オブジェクトストレージへのアクセスまではドキュメントを見れば出来るはずです。
下手にググると古い情報が出てきて余計混乱する可能性があります(私のこと)。なるべく公式が用意しているものを参考にしましょう。OpenStackに準拠しているので、そちらのドキュメントも役に立ちます。
apiユーザ名、パスワード、エンドポイントなど
ログイン後、APIタブをクリック!
Conohaちゃん公式ドキュメント
- ConoHaのオブジェクトストレージについて(導入編)
- オブジェクトストレージを使う(Cyberduck編)
- オブジェクトストレージを使う(RESTful API編)
- オブジェクトストレージを使う(swiftコマンド編)
- オブジェクトストレージを使う(SDK+応用編)
- ConoHa API Documantation
-
旧ドキュメント
- 上のドキュメントには乗っていない情報がかなりあります。古いものなので今は使えない機能もあるのかもしれませんが、参考程度に。
OpenStack公式ドキュメント
- Object Storage API
-
CORS
-
X-Container-Meta-Access-Control-Allow-Origin
←超大事
-
MDN
ajaxとかCORSとかあやふやな方は読んでおくと良いです。preflightって美味いの?
python-swiftclientのインストール
pip install python-swiftclient
環境によってはpip
だとpython2系の方にインストールされるかもしれません。その場合はpip3
とかを試すと良いです。
環境変数の設定
オブジェクトストレージはオンライン上にあるので、当然認証情報が必要です。必要な情報はconohaにログイン後、APIの設定画面を開くと書いてあります。
以下の設定は~/.bashrc
に追記して下さい。
# export OS_AUTH_URL='[Identity Service]'
export OS_AUTH_URL='https://identity.tyo2.conoha.io/v2.0'
# export OS_TENANT_NAME='[テナント名]'
export OS_TENANT_NAME='gnct12345678'
# export OS_USERNAME='[ユーザ名]'
export OS_USERNAME='gncu12345678'
# export OS_PASSWORD='[APIユーザー作成時に設定したパスワード]'
export OS_PASSWORD='conohachanpassword'
追記できたら保存して再ログインもしくは以下のコマンドで再読込します。
source ~/.bashrc
確認
[kiwi@edge ~]$ swift stat
Account: nc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Containers: 2
Objects: 6016
Bytes: 17443618515
Containers in policy "policy-0": 2
Objects in policy "policy-0": 6016
Bytes in policy "policy-0": 17443618515
Meta Quota-Bytes: 107374182400
X-Timestamp: 1530874927.30163
Content-Type: text/plain; charset=utf-8
Accept-Ranges: bytes
X-Trans-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
インストール、環境変数の設定が出来ていればswift stat
コマンドが実行出来るようになるはず...
pythonでオブジェクトストレージを操作する
以下のクラスは私が個人で使用するために書いたやつです。
外部ライブラリを利用しているので、使用する場合は以下のコマンドでrequests
をインストールして下さい。
pip install requests
from requests import post
from requests import get
from json import loads
from os.path import join
from os import chmod
from subprocess import Popen, PIPE
class RestApi(object):
def __init__(self):
self.auth: dict = {
'tenant_name': 'gnct12345678',
'tenant_id': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'auth_url': 'https://identity.tyo2.conoha.io/v2.0/',
'endpoint_url': 'https://object-storage.tyo2.conoha.io/v1/nc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/',
'password_credentials': {
'username': 'gncu12345678',
'password': 'conohachanpassword',
},
'tempurl_key': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
}
def fetch_token(self) -> str:
"""
apiアクセスにはtoken取得が必要なので、事前にこの関数を実行して返り値を貰う必要があります。
"""
url: str = join(self.auth['auth_url'], 'tokens')
data: dict = {
"auth": {
'passwordCredentials': self.auth['password_credentials'],
'tenantId': self.auth['tenant_id'],
}
}
r = post(url=url, json=data)
if r.status_code == 200:
return loads(r.text, encoding='utf-8')['access']['token']['id']
else:
raise AuthorizedError()
def fetch(self, container: str = '', obj: str = ''):
"""
container, objが共に空なら、オブジェクトストレージ全体の情報を返します。
objのみが空なら対象オブジェクト内に存在するファイルをdictで返します。
container, objに文字列が渡されていれば、対象objectファイルのバイナリを返却します。
"""
url: str = join(self.auth['endpoint_url'], container, obj)
payload: dict = {
'X-Auth-Token': self.fetch_token(),
'Accept': 'application/json',
}
r = get(url=url, headers=payload)
if r.status_code == 200:
if obj:
return r.content
else:
return loads(r.text, encoding='utf-8')
else:
raise AuthorizedError()
def fetch_container(self) -> iter:
r = self.fetch()
return (i['name'] for i in r)
def create_tempurl(self, container: str, obj: str) -> str:
method: str = 'GET'
expires: str = "300"
path: str = join(self.auth['endpoint_url'], container, obj)
key: str = self.auth['tempurl_key']
command: list = f'swift tempurl {method} {expires} {path} {key}'.split(
' ')
std = Popen(command, shell=False, encoding='utf-8',
stdout=PIPE, stderr=PIPE)
outs, _ = std.communicate()
return outs
def register_for_metadata(self, payload: dict, container: str = "", obj: str = ""):
url: str = join(self.auth['endpoint_url'], container, obj)
r = post(url=url, headers=payload)
return r.status_code, r.headers, r.text
def remove_for_metadata(self, metaname: str, container: str = "", obj: str = ""):
metaname = metaname.title()
if metaname[:2] == 'X-':
metaname = metaname[2:]
url: str = join(self.auth['endpoint_url'], container, obj)
meta = 'X-Remove-' + metaname
payload: dict = {
'X-Auth-Token': self.fetch_token(),
meta: '',
}
r = post(url=url, headers=payload)
return r.status_code, r.headers, r.text
def write_token(self,
path: str = "./token.txt",
mode: str = 'wt',
encoding: str = 'utf-8'):
token: str = self.fetch_token()
try:
with open(file=path, mode=mode, encoding=encoding) as fp:
fp.write(token)
except (IOError, OSError, TypeError):
raise IOError
else:
chmod(path, 0o704)
class AuthorizedError(Exception):
pass
以後、上のクラスを利用してオブジェクトストレージを操作します。認証情報などは各々RestApi.auth
を書き換えて下さい。
storage.pyの使い方
アクセストークンを取得する
from storage import RestApi
api = RestApi()
print(api.fetch_token())
アクセストークンを./token.txt
に保存する
from storage import RestApi
api = RestApi()
api.write_token(path='./token.txt')
image
コンテナにmetadata
を追加する
from storage import RestApi
api = RestApi()
origin: str = "https://www.kiwi-bird.xyz"
payload: dict = {
'X-Auth-Token': api.fetch_token(),
'Accept': 'application/json',
'X-Container-Meta-Access-Control-Allow-Origin': origin, # CORS対策
}
api.register_for_metadata(payload=payload, container="image")
image
コンテナのmetanameX-Container-Read
を削除する
from storage import RestApi
api = RestApi()
metaname: str = 'X-Container-Read'
api.remove_for_metadata(metaname=metaname, container="image")
image
コンテナのtest.jpg
オブジェクトを取得する
from storage import RestApi
api = RestApi()
print(api.fetch(container='image', obj='test.jpg'))
終わり
以上!すぐに忘れるので備忘録として残しました。ConohaちゃんLOVE