Azure VMのディスク付け替え（管理ディスクから非管理ディスク）

###■初めに
前回、｢非管理ディスク間の差し替え｣をやりましたので今度は「管理ディスクから非管理ディスク」の取り換え方法になります
 ちなみにMSの推奨は管理ディスクですが｢SiteRecovery｣を使用する場合は[非管理ディスク]しかできません。筆者の環境では[SiteRecovery]が後付け導入することになったので本記事のように[管理ディスク]から[非管理ディスク]に変更するっていうレアなケースが発生しました

■｢非管理ディスク間の差し替え｣
いかにやり方書いてます

[Azure VMのDiskを取り換える方法（非管理ディスク間)](https://qiita.com/yo_dazy/items/67c88f38f2a270ae8a39)

■SiteRecovery
いかにやり方書いてます

[Azure SiteRecovery (AzureVMを災対環境へスムーズに移行)](https://qiita.com/yo_dazy/items/dbaab4e2ac3c56432445)


■使いどころ
　管理ディスクで作成したVMを内容そのままに非管理ディスクに変更する場合。あとから｢SiteRecovery｣使いたいとかになったとき。。。（たぶんめったにない）

■事前作業
・「Azure Powershell」のインストール
・ターゲット側に｢VNET｣,｢SUBNET｣,｢NSG｣の作成

■やり方：
・以下、PowerShellを開いてコマンド実行。もしくはコマンド部分と変数部分（適宜環境に置き換えたもの）を丸ごとコピーして実行

■手順
　今回はPowershellのプロンプトより実行する手順になります

■流れ
　【０】　Azure環境へのログインと変数格納
　【１】　ストレージアカウント作成
　【２】　BLOBストレージにエクスポート
　【３】　新規仮想マシン作成　
　【４】　注意
　
---

※起動させたパワーシェルは閉じないこと

###【０】　Azure環境へのログインと変数格納
　Azure環境へのログインと使用する変数に値を格納。

1).[PowerShell]を起動
2).Azureにログイン

```ruby:Powershell
Login-AzAccount
```

```ruby:Result
PS C:\Users\hoge> Login-AzAccount
account          : aaaa@aaaaaa
subscriptionName : bbbbb-bbbbb-bbbbb
subscriptionId   : xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx　←（コピー）
tenantId         : cccccc-ccccc-ccccc-ccccc
environment      : dddddddd

```

3).サブスクリプションのセット

```ruby:Powershell
Select-AzureRmSubscription -SubscriptionId "xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx"
```
```ruby:Result
PS C:\Users\hoge> Select-AzureRmSubscription -SubscriptionId "8d5fb7b6-d8be-4816-a6b6-8e60f85921ae"


Name             : [<Account>, xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx]
Account          : <Account>
SubscriptionName : <Subscriptionname>
TenantId         : <TenantId>
Environment      : <Environment>
PS C:\Users\hoge>
```

4).変数の格納
※ここで指定した変数は全部使います

```ruby:変数の値
$sourcerg = "ソースのリソースグループ"
$sourcedisk = "管理ディスク名称"
$sourcemachine = "ソース仮想マシン名"
$targetrg = "ターゲットのリソースグループ"
$targetmachine = "ターゲットの仮想マシン名"
$targetvn = "ターゲットVMに関連づけるVNET"
$targetsn = "ターゲットVMに関連づけるSUBNET"
$targetstoacc = "作成するストレージアカウント"
$targetcontainername = "作成するストレージアカウントコンテナ"
$targetlocation = "ターゲットの場所（リージョン）"
$targetVmSize = "ターゲットVMのサイズ"
$targetPublicIpName = "ターゲットPublicIPのリソース名"
$targetNIC = "ターゲットPublicIPのNIC名"
$destdiskname = "作成する非管理ディスクのファイル名（ディスク名に拡張子[.vhd]）"
$osdiskname = "作成する非管理ディスクのファイル名"
```

```ruby:Result
$sourcerg = "wsrg"
$sourcedisk = "hoge-c01_OsDisk_1_2fffcd291993444f9d5077e455e31b2c"
$sourcemachine = "hoge-c01"
$targetrg = "wsrg-2"
$targetmachine = "hoge-c02"
$targetvn = "wsrg-2-vnet"
$targetsn = "default"
$targetstoacc = "wsrg2stoaccdisk2"
$targetcontainername = "vhds"
$targetlocation = "japaneast"
$targetVmSize = "Standard_D2s_v3"
$targetPublicIpName = "hoge-c02-ip"
$targetNIC = "hoge-c02-private"
$destdiskname = "hogec01nomanage.vhd"
$osdiskname = "hogec01nomanage"
```


###【１】　ストレージアカウント作成
　ストレージアカウントをターゲットのリソースグループに作成

1).ストレージアカウントの作成

1-1).以下、コマンド実行

```ruby:Powershell
# ストレージアカウントの作成
New-AzureRmStorageAccount -ResourceGroupName $targetrg -name $targetstoacc -Location japaneast -SkuName Premium_LRS
```

```ruby:Result
PS C:\Users\hoge> New-AzureRmStorageAccount -ResourceGroupName $targetrg -name $targetstoacc -Location japaneast -SkuNa
e Premium_LRS


ResourceGroupName      : wsrg-2
StorageAccountName     :
Id                     :
Location               :
Sku                    :
Kind                   :
Encryption             :
AccessTier             :
CreationTime           :
CustomDomain           :
Identity               :
LastGeoFailoverTime    :
PrimaryEndpoints       :
PrimaryLocation        :
ProvisioningState      : Succeeded
SecondaryEndpoints     :
SecondaryLocation      :
StatusOfPrimary        : 
StatusOfSecondary      :
Tags                   : {}
EnableHttpsTrafficOnly : 
NetworkRuleSet         : 
Context                : 
ExtendedProperties     : {}

PS C:\Users\hoge> 
```

1-2).以下、コマンド実行

```ruby:Powershell-1
# アクセスキーの取得
$targetkey1 = $targetkey1 = Get-AzureRmStorageAccountKey -ResourceGroupName $targetrg -Name $targetstoacc
```

```ruby:Powershell-2
# コンテキストの作成
$targetctx = New-AzureStorageContext -StorageAccountName $targetstoacc -StorageAccountKey $targetkey1[0].Value
```

```ruby:Result
PS C:\Users\hoge> $targetkey1 = Get-AzureRmStorageAccountKey -ResourceGroupName $targetrg -Name $targetstoacc
PS C:\Users\hoge> $targetctx = New-AzureStorageContext -StorageAccountName $targetstoacc -StorageAccountKey $targetkey1[
0].Value
PS C:\Users\hoge> 
```
```ruby:Powershell-3
# ストレージアカウントのコンテナ作成
New-AzureStorageContainer -Name $targetcontainername -Context $targetctx
```
```ruby:Result
PS C:\Users\hoge> New-AzureStorageContainer -Name $targetcontainername -Context $targetctx


   Blob End Point: https://<ストレージアカウントパス>/

Name PublicAccess LastModified
---- ------------ ------------
<値$targetcontainername> Off          yyyy-mm-dd hh:mm:ssZ


PS C:\Users\hoge> 
```

2).｢Azure Portal｣よりコンテナが作成されていることの確認！
 ※Powershellは閉じないこと

---

###【２】　BLOBストレージにエクスポート
 管理ディスクを作成したBLOBストレージへエクスポートする
 ※本手順ではソースとなる仮想マシンのディスク割り当てを解除（VM停止）します。
　 ⇒ディスク割り当てを解除しないと作業を進めることができません。

1).以下、コマンド実行する

```ruby:Powershell-1
#仮想マシンの停止
Stop-AzureRmVM -ResourceGroupName $sourcerg -Name $sourcemachine -Force
```
```ruby:Result
PS C:\Users\hoge> Stop-AzureRmVM -ResourceGroupName $sourcerg -Name $sourcemachine -Force
OperationId :
Status      : Succeeded
StartTime   : 2/19/2018 5:01:58 AM
EndTime     : 2/19/2018 5:03:39 AM
Error       :
PS C:\Users\hoge> 
```

2).以下、コマンド実行し、管理ディスクのURLを発行する

```ruby:Powershell-1
# 管理ディスクURL発行
$SourceURL = Grant-AzureRmDiskAccess -ResourceGroupName $sourcerg -DiskName $sourcedisk -Access Read -DurationInSecond 3600

# 管理ディスクURLを変数に格納
$sourceSASurl = $SourceURL.AccessSAS
```

```ruby:Result
PS C:\Users\hoge> $SourceURL = Grant-AzureRmDiskAccess -ResourceGroupName $sourcerg -DiskName $sourcedisk -Access Read -
DurationInSecond 3600
PS C:\Users\hoge> $sourceSASurl = $SourceURL.AccessSAS
PS C:\Users\hoge>
```

3).以下、コマンド実行し、管理ディスクをエクスポートする

```ruby:Powershell-1
# 管理ディスクエクスポート
$ops = Start-AzureStorageBlobCopy -AbsoluteUri $sourceSASurl -DestBlob $destdiskname -DestContainer $targetcontainer.Name -DestContext $targetctx
# 管理ディスクエクスポート
Get-AzureStorageBlobCopyState -Container $targetcontainer.Name -Blob $destdiskname -Context $targetctx -WaitForComplete
```

```ruby:Result
PS C:\Users\hoge> $ops = Start-AzureStorageBlobCopy -AbsoluteUri $sourceSASurl -DestBlob $destdiskname -DestContainer $t
argetcontainer.Name -DestContext $targetctx
PS C:\Users\hoge> Get-AzureStorageBlobCopyState -Container $targetcontainer.Name -Blob $destdiskname -Context $targetctx
 -WaitForComplete
CopyId                  : <CopyId>
CompletionTime          : <TimeStamp>
Status                  : <result>
Source                  : <source>
BytesCopied             : <BytesCopied>
TotalBytes              : <TotalBytes>
StatusDescription       :
DestinationSnapshotTime :
PS C:\Users\hoge> date

```

4).作成したターゲットのBLOBコンテナを開き、BLOBストレージを作成されていることを確認
   ※BLOBストレージが作成されていることを確認したらVMは起動させても問題ありません。
   ※作成したURLはキャンセルしておく事

---

###【３】　新規仮想マシン作成
　[BLOBストレージ]を使用する非管理ディスクを関連付ける「新規VM」を作成します。ここで作成するVMのリソースは[VM][NIC][PublicIP]のみとなりますので他のリソースはあらかじめ作成しておくことを推奨します。

1).以下の値を変数に格納

```ruby:変数の値
$targetdisk = <エクスポートしたBLOBストレージのURL>
```
```ruby:Result
$targetdisk = "https://wsrg2stoaccdisk.blob.core.windows.net/vhds/hogew01nomanage.vhd"
```

2).以下のリソースの情報を変数に格納

```ruby:PowerShell-1
$Vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $targetrg -Name $targetvn
```

```ruby:PowerShell-2
$Subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name $targetsn -VirtualNetwork $Vnet
```

```ruby:Result
PS C:\Users\hoge> $Vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $targetrg -Name $targetvn
PS C:\Users\hoge> $Subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name $targetsn -VirtualNetwork $Vnet
PS C:\Users\hoge> 
```

3).ターゲットVMの構成情報を変数に格納
※以下の手順は作成するOSがWindowsの場合（Linuxの場合は[4)]を行う）

```ruby:PowerShell-1
# VMの構成情報を格納
$VmConfig = New-AzureRmVMConfig -Name $targetmachine -VMSize $targetVmSize
$VmConfig = Set-AzureRmVMOSDisk -VM $VmConfig -VhdUri $targetdisk -Name $osdiskname -CreateOption attach -Windows -Caching ReadWrite
```

```ruby:Result
PS C:\Users\hoge> $VmConfig = New-AzureRmVMConfig -Name $targetmachine -VMSize $targetVmSize
PS C:\Users\hoge> $VmConfig = Set-AzureRmVMOSDisk -VM $VmConfig -VhdUri $targetdisk -Name $osdiskname -CreateOption attach -Windows -Caching ReadWrite
PS C:\Users\hoge> 
```

4).ターゲットVMの構成情報を変数に格納
※以下の手順は作成するOSがWindowsの場合（Linuxの場合は[4)]を行う）

```ruby:PowerShell-1
# VMの構成情報を格納
$VmConfig = New-AzureRmVMConfig -Name $targetmachine -VMSize $targetVmSize
$VmConfig = Set-AzureRmVMOSDisk -VM $VmConfig -VhdUri $targetdisk -Name $osdiskname -CreateOption attach -Windows -Caching ReadWrite
# ソースVMのプラン情報を構成情報に追加
# これやらないとエラーになる
$vmConfig = Set-AzureRmVMPlan -VM $vmConfig -Name "7_4" -Product "cloudera-centos-os" -Publisher "cloudera"
```

```ruby:Result
PS C:\Users\hoge> $VmConfig = New-AzureRmVMConfig -Name $targetmachine -VMSize $targetVmSize
PS C:\Users\hoge> $VmConfig = Set-AzureRmVMOSDisk -VM $VmConfig -VhdUri $targetdisk -Name $osdiskname -CreateOption atta
ch -Windows -Caching ReadWrite
PS C:\Users\hoge> $vmConfig = Set-AzureRmVMPlan -VM $vmConfig -Name "7_4" -Product "cloudera-centos-os" -Publisher "cloudera"
PS C:\Users\hoge> 
```

5).以下コマンドを実行しNICとPublicIPを作成

```ruby:PowerShell-1
# PublicIPを作成
$Pip = New-AzureRmPublicIpAddress -ResourceGroupName $targetrg -Location $targetlocation -AllocationMethod Static -IdleTimeoutInMinutes 4 -Name $targetPublicIpName
# NICを作成し,PublicIPを関連付ける
$Nic12 = New-AzureRmNetworkInterface -Name $targetNIC -ResourceGroupName $targetrg -Location $targetlocation -SubnetId $subnet.id -PublicIpAddressId $Pip.Id
# NICの情報を取得
$Nic1 = Get-AzureRmNetworkInterface -ResourceGroupName $targetrg -Name $targetNIC
```

```ruby:Result
PS C:\Users\hoge> $Pip = New-AzureRmPublicIpAddress -ResourceGroupName $targetrg -Location $targetlocation -AllocationMethod Static -IdleTimeoutInMinutes 4 -Name $targetPublicIpName
警告: The output object type of this cmdlet will be modified in a future release.
PS C:\Users\hoge> $Nic12 = New-AzureRmNetworkInterface -Name $targetNIC -ResourceGroupName $targetrg -Location $targetlo
cation -SubnetId $subnet.id -PublicIpAddressId $Pip.Id
警告: The output object type of this cmdlet will be modified in a future release.
PS C:\Users\hoge> $Nic1 = Get-AzureRmNetworkInterface -ResourceGroupName $targetrg -Name $targetNIC
PS C:\Users\hoge> 
```

6).以下コマンドを実行しVMの構成情報にNIC情報を追加しプライマリNICに設定

```ruby:PowerShell-1
# NIC情報追加
$VmConfig = Add-AzureRmVMNetworkInterface -VM $VmConfig -NetworkInterface $Nic1
# プライマリNICに設定
$VmConfig.NetworkProfile.NetworkInterfaces.Item(0).Primary = $true
```
```ruby:Result
PS C:\Users\hoge> $VmConfig = Add-AzureRmVMNetworkInterface -VM $VmConfig -NetworkInterface $Nic1
PS C:\Users\hoge> $VmConfig.NetworkProfile.NetworkInterfaces.Item(0).Primary = $true
PS C:\Users\hoge> 
```

7).以下コマンドを実行しVMを新規作成

```ruby:PowerShell-1
New-AzureRmVM -ResourceGroupName $targetrg -Location $targetlocation -VM $VmConfig -Verbose
```
```ruby:Result
PS C:\Users\hoge> New-AzureRmVM -ResourceGroupName $targetrg -Location $targetlocation -VM $VmConfig -Verbose
警告: Since the VM is created using premium storage, existing standard storage account, wsrg2diag993, is used for boot
diagnostics.
詳細: 対象 "<hostname>" に対して操作 "New" を実行しています。

RequestId IsSuccessStatusCode StatusCode ReasonPhrase
--------- ------------------- ---------- ------------
                         True         OK OK

PS C:\Users\hoge> 

```

以上

---

###【４】　注意
・新規作成した仮想マシンには「仮想マシン名」が存在しません
・新規作成した仮想マシンのホストネームはソースマシンと同じです
・その他ディスク内容もソースマシンと同じです

---

###■最後に
　今回の手順はお気づきの方もいると思いますが、そっくりそのままPowerShellで実行可能です。変数の値だけを自前の環境に合わせる感じです。基本的にAzureはGUIでカチカチやるよりもPowerShellで管理したほうが楽です。