[ConoHa API] Java Scriptでサーバ一覧を取得する　その３

## サーバ詳細情報の取得

前回まではservers APIを使用していましたが、今回は[servers/detail](https://www.conoha.jp/docs/compute-get_vms_detail.html) APIを使用します。

```js
//
// servers detail API information
//
var servers_detail_url = "https://compute.tyo1.conoha.io/v2/" + tenant_id + "/servers/detail";
var servers_detail_data = {};
var servers_detail_type = "GET";
var serversDetailOnSuccess = function(data) {
  for (var i = 0; i < data.servers.length; i++) {
    var tr = $('<tr>');
    var td_index = $('<td>').text(i);
    var td_status = $('<td>').text(data.servers[i].status);
    var td_name = $('<td>').text(data.servers[i].metadata.instance_name_tag);
    tr.append(td_index).append(td_status).append(td_name);
    $('#server_table').append(tr);
  }
}
```

基本的な使い方はservers APIを同じですね。電源のステータスはstatus、ネームタグはmetadata.instance_name_tagで取得できます。

動作するコードは[ここ](https://github.com/OttyLab/ConoHa_sample/blob/master/servers03.html)にあります。


## 複数リージョンのサーバ情報取得

さて、今までは東京リージョンの情報を取得していましたが、シンガポールとアメリカのサーバ情報も取得してみましょう。

とりあえずシンガポールとアメリカにサーバを立ててAPIを叩くと…東京しか取得できませんね。しかもリージョン情報は一体どこに格納されて返ってくるのだろう。。。

と、小一時間悩んでいたところそもそもAPIのURLが異なるということに気づきました。API Documentationには書かれていないようですが、自身のアカウントでログイン --> API --> エンドポイントでリージョン毎のURLが記載されていますね。

基本的にURLは以下の構成になっているようです。

```
http://[type].[region].conoha.io/hogehoge
```

各リージョンの対応は以下のとおり。

|リージョン    |URL|
|:-----------|:---|
|東京         |tyo1|
|シンガポール  |sin1|
|アメリカ     |sjc1|

アメリカは[サンノゼ](https://www.google.co.jp/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%20sjc)にサーバがあるのでしょうか。


## 複数リージョンへの対応

URLが違うということで、これまでの方法を少し変えないといけなくなりました。

まずはリージョンとURLの対応を連想配列で定義します。連想配列を使用しているのは後ほどforループでくるくる回せるのではないかという目論見です。

```js
//
// Region
//
var regions = {
  "Tokyo"     : "tyo1",
  "Singapore" : "sin1",
  "US"        : "sjc1"
};
```

また、トークンの保存先も以下のようにします。

```js
window.localStorage['token_Tokyo'];
window.localStorage['token_Singapore'];
window.localStorage['token_US'];

```


次に、各APIのURLを変数から関数に変更します。regionを引数に取ることで、リージョン毎のURLを生成します。

```js
var getTokenUrl = function(region) {
  return "https://identity." + region + ".conoha.io/v2.0/tokens";
} 
```

```js
var getServersDetailUrl = function (region){ 
  return "https://compute." + region + ".conoha.io/v2/" + tenant_id + "/servers/detail";
};
```

さて、token APIのsuccessの処理において、リージョンごとにトークンの保存先を切り替える必要があります。だからといってリージョン毎の関数は作りたくありません。

幸い、$.ajaxはsuccess, error等の処理にthisとして任意の値を渡すcontextというパラメータが存在します。

```js
var access = function(url, data, type, onSuccess, key) {
    return $.ajax({
      url: url,
      data: JSON.stringify(data),
      type: type,
      headers: {
        'X-Auth-Token' : window.localStorage["token_" + key]
      },
      context: key,
      success: onSuccess,
      error: function() {
        console.log('$.ajax error. remove token in local storage.');
        window.localStorage.removeItem("token_" + key);
      }
    });
}
```

access関数にkey (= Tokyo, Singapore, USのいずれかの文字列が入る）を渡し、それをcontextに入れています。これによりsuccessの中でthisを使ってその値を取り出すことができます。

```js
var tokenOnSuccess = function(data) {
  window.localStorage["token_" + this] = data.access.token.id;
}
```

最後にaccessを呼び出す部分を変更します。期待通り、forループでぐるぐる回します。

```js
  for (key in regions) {
    if (window.localStorage["token_" + key] === undefined) {
      access(getTokenUrl(regions[key]), token_data, token_type, tokenOnSuccess, key).done(function(){
        access(getServersDetailUrl(regions[this]), servers_detail_data, servers_detail_type, serversDetailOnSuccess, this); 
      });
    } else {
      access(getServersDetailUrl(regions[key]), servers_detail_data, servers_detail_type, serversDetailOnSuccess, key); 
    }
  }
```

気をつけなければならないのが、.done()の中でkeyを引数として渡してはいけないということです。例えば東京のtokenアクセス中にforループの処理が進みUSまで回ったとします。その後、東京のdoneでkeyにアクセスするとkeyの値はUSになっています。

そこで、先ほどcontextで設定したthisに格納されたkeyの値を使用します。


以上、長かったですが以下のように無事各リージョンのサーバ情報が取得できました！

![servers04.png](https://qiita-image-store.s3.amazonaws.com/0/85105/4bc796df-4cd2-2816-291e-7c25dcb59f85.png)


動作するコードは[ここ](https://github.com/OttyLab/ConoHa_sample/blob/master/servers04.html)にあります。


## 次回

つぎはいよいよPhoneGapを使ってスマホ上で動かしてみます。