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

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

GMOインターネットが提供するVPSサービス「ConoHa」のAPIを使って、オリジナルコマンドを使ったサーバー管理方法を3回に渡ってご紹介するレポート。Vol.2では、モジュールファイルの配置やサーバーの起動と停止コマンドをご紹介します。

モジュールファイルの配置

作成したPowerShellのオリジナルコマンドは、モジュール化して保存しておくことで自動的に読み込まれて利用することができるようになります。PowerShellのモジュールファイルについては以前紹介していますので、ここではモジュールファイルの配置と作成方法だけを簡単に説明することとします。

Hyper-Vで作るコンテナ 新しい仮想マシンの使い方-Vol.3 開発環境を整える

“C:\Users\\Documents\WindowsPowerShell\Modules”
このフォルダ内に”PSdeConoHa”フォルダを作成します。
さらにPSdeConoHaフォルダ内に”PSdeConoHa.psm1”モジュールファイルを作成します。この時、フォルダ名とファイル名は同じにする必要があります。

PowerShell ISEを管理者権限で実行して”C:\Users\\Documents\WindowsPowerShell\Modules\PSdeConoHa\PSdeConoHa.psm1″ファイルを開きます。前回作成した「PSdeConoHa.ps1」の中身をそのままコピーして貼り付けます。
適切な値を先頭の$apiUser、$password、$tenantIdに代入して「Remove-Module *」コマンドを実行してモジュールを初期化しておきます。これで、自動的にモジュールが読み込まれてコマンドを利用することができるようになります。モジュールを修正した場合は、再度「Remove-Module *」コマンドを実行するようにします。

前回作成した「Get-cVM」コマンドを実行してみましょう。ConoHa上のサーバー情報が取得できればモジュールの配置は成功です。

コマンドの作成:サーバーの起動

以後は、モジュールファイル「PSdeConoHa.psm1」に新しいコマンドを追加していきます。
最終的に作成するのは、今回はここまでです。

$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
    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
    }    
}

最初に作成するのはサーバーの起動コマンドです。
API解説ページを見てみましょう。

必要な情報としては、

ParameterValueStyleDescription
X-Auth-TokenUserトークンheaderトークンID
tenant_idURIテナントID
server_idServer IDplainサーバーID

となっています。

「Userトークン」と「テナントID」はサーバー一覧の取得と同じです。サーバーを特定するための「Server ID」が今回は必要となります。「Server ID」は実は前回作成した「Get-cVM」コマンドですでに取得できるようにしているので、ここから参照するようにします。PowerShellでは他のコマンドで取得した情報をそのまま再利用できるので非常に便利です。

curlコマンドのサンプルコードを見てみましょう。

curl -i -X POST \
-H "Accept: application/json" \
-H "X-Auth-Token: 35941e7df872405d84e5b026dba8323c" \
-d '{"os-start": null}' \
https://compute.tyo1.conoha.io/v2/1864e71d2deb46f6b47526b69c65a45d/servers/997d6052-4b17-4500-8d41-c08fb9667aae/action

今回はPOSTメソッドでリクエストURLに「テナントID」と「Server ID」を含めてAPIにサーバー情報を送信するので
https://compute.tyo1.conoha.io/v2/<テナントID>/servers/<サーバー ID>/action 
となります。
ポイントはPOSTメソッドでJSON形式のデータを送信するということです。curlコマンンドのサンプルで「-d ‘{“os-start”: null}’」となっている部分です。Invoke-RestMethodコマンドではPOSTするデータは「-Body」として取り扱います。
$body = ‘{“os-start”: null}’ としてJSON形式のデータを変数に格納しておきます。

起動する仮想マシンはConoHaのコントロールパネルであらかじめ停止させておき、Get-cVMコマンドでID(” fe3ec4d2-1af7-4800-a2f8-6ceadd00f8d8”)を確認しておきます。

PS C:\> Get-cVM vps-2017-12-07-21-28


ID : 0e3069ce-dee8-47b5-8009-990e065068f3
Name : vps-2017-12-07-21-28
State : SHUTOFF
Memory : 1
Disk : 50
vCPU : 2
IPAddress : 150.***.***.***

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

Function Start-cVM(){
  $serverId = “fe3ec4d2-1af7-4800-a2f8-6ceadd00f8d8”
  $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
}

モジュールファイルに書き込みます。一度Remove-Module * コマンドを実行して再読み込みをしてからテストしてみましょう。停止していた仮想マシンが起動状態になっていれば成功です。

PS C:\> Start-cVM


PS C:\> Get-cVM vps-2017-12-07-21-28


ID : 0e3069ce-dee8-47b5-8009-990e065068f3
Name : vps-2017-12-07-21-28
State : ACTIVE
Memory : 1
Disk : 50
vCPU : 2
IPAddress : 150.***.***.**

ConoHaのREST APIを使ってInvoke-RestMethodコマンドからサーバーを起動することが確認できました。
では、PowerShellらしく、コマンドを組み合わせて利用できるように修正していきます。
このままではStart-cVMコマンドではサーバーIDを決め打ちして起動しているので、パラメーターを使って、任意のサーバーを起動できるようにしてみましょう。

Function Start-cVM(){
  Param(
    $VM
)
$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
}

パラメーターを使って、引数として$VMを定義してサーバー名を指定できるようにしておきます。指定されたサーバー名を元に、Get-cVMを利用して、サーバーIDを取得できるようにしました。
コマンドを実行してみましょう。

PS C:\> Start-cVM vps-2017-12-07-21-28


PS C:\> Get-cVM vps-2017-12-07-21-28


ID : 0e3069ce-dee8-47b5-8009-990e065068f3
Name : vps-2017-12-07-21-28
State : ACTIVE
Memory : 1
Disk : 50
vCPU : 2
IPAddress : 150.***.***.**

パラメーターを使うことで使い勝手がよくなりました。
さらに、PowerShellのコマンドであれば、パイプラインを利用できるようにしておきたいところです。パイプラインを利用することで、コマンドの実行結果をパラメーターとして受け取ることができるようになるので、コードが簡略化されます。

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
    }
}

3 :パラメーターの値をパイプラインから受け取るには、[Parameter(ValueFromPipeline=$True)]属性を変数にあらかじめ指定しておきます。

5-18 :パイプラインで渡される値が複数の場合もあるので、すべてに対してProcessブロックで1つずつ処理をしていきます。

6 :パイプラインでパラメーターに渡される値は文字列だけとは限りません。Get-cVMコマンドの実行結果であれば、PSCustomObject型の場合もあります。柔軟に対応できるようにSwitch文で分岐を作成しておきます。

7-8 : PSCustomObject型の場合は、$VM変数には各種サーバーのプロパティーが格納されています。サーバーIDは$VM.IDで取得可能です。

14-17 :String型(文字列)の場合はサーバー名ということで、これを引数としてGet-cVMコマンドを実行してサーバーIDを取得します。

85-88 :サーバーIDが取得できれば、これまで同様、Invoke-RestMethodコマンドでConoHa APIを使ってサーバーを起動します。

パイプラインを使った場合はこのように一度にサーバーを起動することができます。

PS C:\> Get-cVM vps-2017-10-03-16-52 | Start-cVM


PS C:\> Get-cVM vps-2017-10-03-16-52


ID : fe3ec4d2-1af7-4800-a2f8-6ceadd00f8d8
Name : vps-2017-10-03-16-52
State : ACTIVE
Memory : 4
Disk : 50
vCPU : 4
IPAddress : 150.***.***.**

コマンドの作成:サーバーの停止

サーバーの起動ができれば、もちろん停止コマンドも必要です。ConoHaにはサーバーの通常停止と強制停止があり、通常停止はシャットダウン処理、強制停止は電源OFFと同様のものになります。今回はサーバーの通常停止を行います。

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

必要な情報としては、

ParameterValueStyleDescription
X-Auth-TokenUserトークンheaderトークンID
tenant_idURIテナントID
server_idServer IDplainサーバID

となっています。

サーバーの起動を異なるのはPOSTするJSONデータが
{
“os-stop”: null
}
このようになるだけです。

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
    }    
}

16 :Start-cVMからこの部分を変更します。

PS C:\> Get-cVM vps-2017-10-03-16-52 | Stop-cVM


PS C:\> Get-cVM vps-2017-10-03-16-52


ID : fe3ec4d2-1af7-4800-a2f8-6ceadd00f8d8
Name : vps-2017-10-03-16-52
State : ACTIVE
Memory : 4
Disk : 50
vCPU : 4
IPAddress : 150.***.***.**

以上でパイプラインにも対応した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アワード」を受賞し、インターネットソリューションのスペシャリストとして活躍。

採用情報

関連記事