ConoHa APIを使ってPowerShellのオリジナルコマンドでサーバー管理

PowerShellでConoHaをどうにかしてみる-Vol.3

GMOインターネットが提供するVPSサービス「ConoHa」のAPIを使って、オリジナルコマンドを使ったサーバー管理方法を3回に渡ってご紹介するレポート。最終回のVol.3では、仮想マシンの作成コマンドについてご紹介します。

はじめに

引き続きConoHaをPowerShellでどうにかすべく、オリジナルコマンドを作成していきましょう。サーバー一覧の取得、サーバーの起動・停止コマンドが完成しているので、今回はサーバー(仮想マシン)の作成コマンドを作成しましょう。

$apiUser = "gncu12345678" 
$password = "paSSword123456#$%" 
$tenantId = "487727e3921d44e3bfe7ebb337bf085e" 
$script:token = "" 

Function Get-cTokenHeader(){
    $body = '{"auth":{"passwordCredentials":{"username":"' + $apiUser + '","password":"' + $password+'"},"tenantId":"' + $tenantId+'"}}'
    $tokenUrl = "https://identity.tyo1.conoha.io/v2.0/tokens"

    If($script:token){
        $expiresTime = Get-Date -Date $script:token.access.token.expires
        If ($expiresTime -lt (Get-Date)){
            $script:token = Invoke-RestMethod $tokenUrl -Method POST -Body $body        
        }    
    }Else{
        $script:token = Invoke-RestMethod $tokenUrl -Method POST -Body $body    
    }
    $tokenId = $script:token.access.token.id
    Return @{"X-Auth-Token" = $tokenId}
}

Function Get-cFlavor($flavorId){    
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/flavors/$flavorId"
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method GET
    If($flavorId -eq $null){
        $flavors = $result.flavors
        $objAry = @()
        ForEach($flavor in $flavors){
            $id = $flavor.id
            $name = $flavor.name
            $objPs = New-Object PSCustomObject
            $objPs | Add-Member -NotePropertyMembers @{ID = $id}
            $objPs | Add-Member -NotePropertyMembers @{Name = $name}
            $objAry += $objPs
        }
        Return $objAry
    }Else{
        Return $result.flavor
    }
}

Function Get-cVM(){  
    Param(        
        $Name
    )
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/servers/detail"    
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method GET
    $servers = $result.servers

    $objAry = @()
    ForEach($server in $servers){
        $id = $server.id
        $tagName = $server.metadata.instance_name_tag
        $state = $server.status
        $flavorId = $server.flavor.id
        $flavor = Get-cFlavor $flavorId
        $vcpu = $flavor.vcpus
        $ram = $flavor.ram / 1024
        $disk = $flavor.disk
        $ip = ($server.addresses.($server.addresses.PSObject.Properties.name) | ? version -eq 4).addr

        $objPs = New-Object PSCustomObject
        $objPs | Add-Member -NotePropertyMembers @{ID = $id}
        $objPs | Add-Member -NotePropertyMembers @{Name = $tagName}
        $objPs | Add-Member -NotePropertyMembers @{State = $state}
        $objPs | Add-Member -NotePropertyMembers @{vCPU = $vcpu}
        $objPs | Add-Member -NotePropertyMembers @{Disk = $disk}
        $objPs | Add-Member -NotePropertyMembers @{Memory = $ram}
        $objPs | Add-Member -NotePropertyMembers @{IPAddress = $ip}
        $objAry += ($objPs | Select-Object ID, Name, State, Memory, Disk, vCPU, IPAddress)       
    }	  
    
    $VM = $objAry
    If($Name -ne $null){
        $VM = $VM | ? Name -eq $Name
    } 
    If($VM -eq $null){  
        Write-Host ("""$Name"" という名前の仮想マシンが見つかりません。") -ForegroundColor Red
    }Else{
        Return $VM
    } 
}

Function Start-cVM(){
    Param(        
        [Parameter(ValueFromPipeline=$true)]$VM
    )
    Process{ 
        Switch($VM.GetType().Name){
            "PSCustomObject"{
                $serverId = $VM.ID
            }
            "String"{
                $serverId = (Get-cVM $VM).ID
            }           
        } 
        $tokenHeader = Get-cTokenHeader
        $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/servers/$serverId/action"
        $body = '{"os-start": null}'
        Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method POST -Body $body
    }
}

Function Stop-cVM(){
    Param(        
        [Parameter(ValueFromPipeline=$true)]$VM
    )
    Process{ 
        Switch($VM.GetType().Name){
            "PSCustomObject"{
                $serverId = $VM.ID
            }
            "String"{
                $serverId = (Get-cVM $VM).ID
            }           
        } 
        $tokenHeader = Get-cTokenHeader
        $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/servers/$serverId/action"
        $body = '{"os-stop": null}'
        Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method POST -Body $body
    }    
}

Function Get-cImage(){    
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/images/detail"
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method GET
    $images = $result.images
    $objAry = @()
    ForEach($image in $images){
        $id = $image.id
        $name = $image.name
        $objPs = New-Object PSCustomObject
        $objPs | Add-Member -NotePropertyMembers @{ID = $id}
        $objPs | Add-Member -NotePropertyMembers @{Name = $name}
        $objAry += $objPs       
    }
    Return $objAry
}

Function New-cVM($name, $imageId, $flavorId, $adminPass){
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/servers"   
    $body =     
@"
    {
        "server": {
            "imageRef" : "$imageId", 
            "flavorRef" : "$flavorId", 
            "adminPass" : "$adminPass",
            "metadata": {
                "instance_name_tag": "$name"
            }
        }
    }    
"@
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method POST -Body $body
    Return $name
}

モジュールファイル「PSdeConoHa.psm1」に新しいコマンドを追加していきます。

イメージ一覧の取得

サーバー作成のコマンドの前に、コマンドのパラメーターとして必要となるサーバーイメージIDを取得するコマンドを作成しておきましょう。

API解説ページでcurlコマンドのサンプルコードを見てみましょう。

curl -i -X GET \
-H "Accept: application/json" \
-H "X-Auth-Token: 35941e7df872405d84e5b026dba8323c" \
https://compute.tyo1.conoha.io/v2/1864e71d2deb46f6b47526b69c65a45d/images/detail

GETメソッドでリクエストURLに「テナントID」と「Server ID」を含めてAPIにサーバー情報を送信するだけなので簡単ですね。

PowerShellのInvoke-RestMethodコマンドで置き換えるとこのようになります。

Function Get-cImage(){    
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/images/detail"
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method GET
    $images = $result.images
    $objAry = @()
    ForEach($image in $images){
        $id = $image.id
        $name = $image.name
        $objPs = New-Object PSCustomObject
        $objPs | Add-Member -NotePropertyMembers @{ID = $id}
        $objPs | Add-Member -NotePropertyMembers @{Name = $name}
        $objAry += $objPs       
    }
    Return $objAry
}

$tokenHeader = Get-cTokenHeader:
これまでと同様にトークンヘッダー情報を取得します。

$requestUrl = https://compute.tyo1.conoha.io/v2/$tenantId/images/detail:
リクエストURLはこちらです。

$images = $result.images:
Invoke-RestMethodコマンドの実行結果imagesの中にイメージの一覧情報が格納されています。

ForEach($image in $images) ~ Return $objAry:
それぞれのイメージ情報からイメージIDとイメージ名を抜き出してPSCustomObjectに格納して戻り値としています。

実行すると、すべてのイメージ一覧が表示されます。サーバー作成時にはイメージのIDが必要となるので確認しておきましょう。

PS C:\> Get-cImage

ID Name
-- ----
b2e06d42-4c68-4792-87c4-e6faff3c5c0c vmi-drupal-8.4.2-centos-7.4-amd64-20gb
ae172d73-d16c-42b7-bc32-41b40ca40e63 vmi-drupal-8.4.2-centos-7.4-amd64
9b70032f-c486-4fd9-9e00-e7899d336406 vmi-minecraft-1.12.2-centos-7.4
95450a81-8194-4ff2-aab6-4f2595da56bb vmi-centos-7.4-amd64-20gb


プラン一覧の取得

サーバーを作成するコマンドにもう1つ必要なパラメーターとして、プランIDがあります。以前、サーバー情報を取得する「Get-cVM」コマンドを作成した際に「Get-cFlavor」コマンドを作成して、サーバーに割り当てられているプラン情報(CPU、メモリ、HDD)を取得しました。このコマンドをサーバー作成に利用できるプラン一覧を取得できるように修正しましょう。

API解説ページでcurlコマンドのサンプルコードを見てみましょう。

curl -i -X GET \
-H "Accept: application/json" \
-H "X-Auth-Token: 35941e7df872405d84e5b026dba8323c" \
https://compute.tyo1.conoha.io/v2/1864e71d2deb46f6b47526b69c65a45d/flavors

「Get-cFlavor」コマンドでは、URLの最後にサーバーIDを指定することで、割り当てられているプラン情報を取得していましたが、サーバーIDを指定しない場合は、プラン一覧を取得できるようです。
「Get-cFlavor」コマンドを以下のように修正します。

Function Get-cFlavor($flavorId){    
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/flavors/$flavorId"
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method GET
    If($flavorId -eq $null){
        $flavors = $result.flavors
        $objAry = @()
        ForEach($flavor in $flavors){
            $id = $flavor.id
            $name = $flavor.name
            $objPs = New-Object PSCustomObject
            $objPs | Add-Member -NotePropertyMembers @{ID = $id}
            $objPs | Add-Member -NotePropertyMembers @{Name = $name}
            $objAry += $objPs
        }
        Return $objAry
    }Else{
        Return $result.flavor
    }
}

If($flavorId -eq $null):
flavorIdを指定していない場合はプラン一覧を取得します。

$flavors = $result.flavors:
Invoke-RestMethodコマンドの実行結果flavorsの中にプラン一覧が格納されています。

ForEach($flavor in $flavors) ~ Return $objAry:
それぞれのプラン情報からプランIDとプラン名を抜き出してPSCustomObjectに格納して戻り値としています。

Return $result.flavor:
flavorIdが指定されている場合は、これまで同様該当するプラン情報を戻り値としています。

実行すると、すべてのプラン一覧が表示されます。サーバー作成時にはプランのIDが必要となるので確認しておきましょう。

PS C:\> Get-cFlavor

ID Name
-- ----
294639c7-72ba-43a5-8ff2-513c8995b869 g-2gb
3aa001cd-95b6-46c9-a91e-e62d6f7f06a3 g-16gb
62e8fb4b-6a26-46cd-be13-e5bbf5614d15 g-4gb
7eea7469-0d85-4f82-8050-6ae742394681 g-1gb
965affd4-d9e8-4ffb-b9a9-624d63e2d83f g-8gb
a20905c6-3733-46c4-81cc-458c7dca1bae g-32gb
c2a97b05-1b4b-4038-bbcb-343201659279 g-64gb
d92b02ce-9a4f-4544-8d7f-ae8380bc08e7 g-512mb

サーバーの作成

ConoHaのコントールパネルでは、「サーバーの追加」メニューを表示するといくつかの選択項目があり、細かくサーバーの仕様を決めることができるようになっています。

ConoHa コントールパネル

API解説ページを見てみましょう。

数多くのパラメーターがありますが、サーバーを作成する場合に必要な最低限の情報としては、X-Auth-Token、tenant_id、imageRef、flavorRef、adminPass となっています。トークンとテナントIDはこれまで同様なので、イメージID(imageRef)とプランID(flavorRef)、管理者のパスワードが必要となります。イメージIDとプランIDは先ほど作成した「Get-cImage」と「Get-cFlavor」コマンドで確認しておきましょう。さらに、作成するサーバー名を指定しておきたいので、instance_name_tagも設定しておきましょう。

ParameterValueStyleDescription
X-Auth-TokenUserトークンheaderトークンID
tenant_idURIテナントID
imageRefplainimage 参照先。対象 image の UUID を指定
flavorRefplain
VMプラン(flavor) の UUID を指定
adminPass (Optional)plain
VMのrootパスワード 詳細は vmのrootパスワードについて を参照
key_name (Optional)ssh key nameplainSSHキーを利用する場合に指定する
security_groups (Optional)security_groupオブジェクトplain
keyに”name“を、valueにセキュリティグループ名を指定する(以下のRequestJson参照)
metadata (Optional)plain
metadata の key:value ペア。
instance_name_tag (Optional)Default:VMに紐づくGlobalIPアドレスplain
ネームタグを入れる際に利用する。文字種:半角英数字、「 – 」、「 _ 」のみを許可。文字数:255文字以下
block_device_mapping (Optional)Arraydeviceは1つのみマッピングできる
volume_id (Optional)plainアタッチしたいVolumeのIDを指定する
vncKeymap (Optional)plainkeymap 設定
user_data (Optional)
base64 encode された スタートアップスクリプト
plain
base64 encoded Cloud-Init script

curlコマンドのサンプルコードを見てみましょう。サーバー名としてinstance_name_tagを使用する場合は、metadata指定時のJSON形式となるので、こちらとなります。

{
   "server": {
     "imageRef": "1f7bcc63-4a18-4371-85b1-bcdd4301ff31",
     "flavorRef": "b60acd11-3fd5-46e1-9387-aae4737d49aa",
     "adminPass":"72LY2hf38Kf84vCy4sUr",
     "metadata": {
       "instance_name_tag": "testtest"
     }
   }
}

POSTメソッドでリクエストURLに「テナントID」と「Server ID」を含めてAPIにサーバー情報を送信するので
https://compute.tyo1.conoha.io/v2/<テナントID>/servers/<サーバー ID>/servers
となります。
POSTメソッドで送信するJSON形式のデータは「-d ‘{“server”:・・・」となっている部分で、サーバー作成のパラメーターを指定しています。サーバーの起動コマンドなどと仕組みは同じです。instance_name_tagはmetadateに指定する必要があるので、子要素を追加して指定します。

以上を踏まえてサーバーを作成するコマンドはこのようになります。

Function New-cVM($name, $imageId, $flavorId, $adminPass){
    $tokenHeader = Get-cTokenHeader
    $requestUrl = "https://compute.tyo1.conoha.io/v2/$tenantId/servers"   
    $body =     
@"
    {
        "server": {
            "imageRef" : "$imageId", 
            "flavorRef" : "$flavorId", 
            "adminPass" : "$adminPass",
            "metadata": {
                "instance_name_tag": "$name"
            }
        }
    }    
"@
    $result = Invoke-RestMethod $requestUrl -Headers $tokenHeader -Method POST -Body $body
    Return $name
}

Function New-cVM($name, $imageId, $flavorId, $adminPass):
New-cVMというコマンド名で、引数として、サーバー名、イメージID、プランID、管理者パスワードを指定します。

$body:
POSTメソッドで送信するデータをJSON形式の文字列で指定します。必要最低限の情報は、今回はimageRef、flavorRef、adminPassの3つと、instance_name_tagとなります。

$result = Invoke-RestMethod:
Invoke-RestMethodコマンドを実行します。

Return $result.server.id:
サーバーが作成された場合のサーバー名を戻り値としています。

コマンドを実行してみましょう。

PS C:\> $res = New-cVM "myVM_01" "b2e06d42-4c68-4792-87c4-e6faff3c5c0c" "294639c7-72ba-43a5-8ff2-513c8995b869" "72LY2hf38Kf84vCy4sUr"

PS C:\> Get-cVM $res


ID : 2024b61d-51ae-4c39-b196-4b317493b356
Name : myVM_01
State : ACTIVE
Memory : 2
Disk : 50
vCPU : 3
IPAddress : 150.95.217.10

変数”$res”の中にはNew-cVMの実行結果として、サーバー名が取得できているので、そのままGet-cVMコマンドを使ってサーバーの状態を確認することができます。

コントロールパネルでもサーバーが作成されているのが確認できます。

ConoHa サーバーリスト

API解説ページにはこの他にも、「SSHキー指定時」や「追加ディスク指定時」のJSONデータのサンプルが記載されているので、必要に応じてコマンドのパラメーターを変更してより細かい設定でサーバーを作成も可能です。

以上がサーバーの作成コマンドとなります。

ConoHaにはこれまで見てきたような基本的な機能の他にも、様々なことができるAPIが用意されています。全てをPowerShellのコマンドに置き換えるのは大変ですが、自身の必要とする機能を選択してパイプラインやオブジェクトなどPowerShellならではの使いやすさで、ConoHaのサーバー管理を実現してみてはいかがでしょうか。

今後も、時間の許す限りPowerShellでConoHaをどうにかするべく、色々なコマンドを作成していきたいと考えています。

コードサンプルはGitHubにて公開しています。
https://github.com/InvokeV/PSdeConoHa

著書の紹介欄

Hyper-Vで本格的なサーバー仮想環境を構築。仮想環境を設定・操作できる!

できるPRO Windows Server 2016 Hyper-V

◇Hyper-Vのさまざまな機能がわかる ◇インストールからの操作手順を解説 ◇チェックポイントやレプリカも活用できる Windows Server 2016 Hyper-Vは、仮想化ソフトウェア基盤を提供する機能であり、クラウドの実現に不可欠のものです。 本書では、仮想化の基礎知識から、Hyper-Vでの仮想マシンや仮想スイッチの設定・操作、プライベートクラウドの構築、Azureとの連携などを解説します。

初めてのWindows Azure Pack本が発売

Windows Azure Pack プライベートクラウド構築ガイド

本書は、Windows Azure PackとHyper-Vを利用し、企業内IaaS(仮想マシン提供サービス)を構成するための、IT管理者に向けた手引書です。試用したサーバーは、最小限度の物理サーバーと仮想マシンで構成しています。Windows Azure Packに必要なコンポーネントのダウンロード、実際にプライベートクラウド構築する過程を、手順を追って解説しています。これからプライベートクラウドの構築を検討するうえで、作業負担の軽減に役立つ一冊です。

ブログの著者欄

樋口 勝一

GMOインターネット株式会社

1999年6月GMOインターネットに入社。Windows Serverをプラットフォームとしたサービス開発から運用・保守まで幅広く担当。講演登壇や出版、ネット記事連載などでマイクロソフト社と強い信頼関係を構築。2007年より「マイクロソフトMVPアワード」を受賞し、インターネットソリューションのスペシャリストとして活躍。

関連記事