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-cImageID Name-- ----b2e06d42-4c68-4792-87c4-e6faff3c5c0c vmi-drupal-8.4.2-centos-7.4-amd64-20gbae172d73-d16c-42b7-bc32-41b40ca40e63 vmi-drupal-8.4.2-centos-7.4-amd649b70032f-c486-4fd9-9e00-e7899d336406 vmi-minecraft-1.12.2-centos-7.495450a81-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-cFlavorID Name-- ----294639c7-72ba-43a5-8ff2-513c8995b869 g-2gb3aa001cd-95b6-46c9-a91e-e62d6f7f06a3 g-16gb62e8fb4b-6a26-46cd-be13-e5bbf5614d15 g-4gb7eea7469-0d85-4f82-8050-6ae742394681 g-1gb965affd4-d9e8-4ffb-b9a9-624d63e2d83f g-8gba20905c6-3733-46c4-81cc-458c7dca1bae g-32gbc2a97b05-1b4b-4038-bbcb-343201659279 g-64gbd92b02ce-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も設定しておきましょう。
ParameterValueStyleDescriptionX-Auth-TokenUserトークンheaderトークンIDtenant_idURIテナントIDimageRefplainimage 参照先。対象 image の UUID を指定flavorRefplainVMプラン(flavor) の UUID を指定adminPass (Optional)plainVMのrootパスワード 詳細は vmのrootパスワードについて を参照key_name (Optional)ssh key nameplainSSHキーを利用する場合に指定するsecurity_groups (Optional)security_groupオブジェクトplainkeyに”name“を、valueにセキュリティグループ名を指定する(以下のRequestJson参照)metadata (Optional)plainmetadata の 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 された スタートアップスクリプトplainbase64 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 $resID : 2024b61d-51ae-4c39-b196-4b317493b356Name : myVM_01State : ACTIVEMemory : 2Disk : 50vCPU : 3IPAddress : 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