Posted in
Virtual Machine Manager,
Windows Server |
No Comment | 1,963 views | 09/06/2014 17:54
This is my notes and scripts for a Hyper-V Disaster Recovery with Storage Replication.
First script on Main Site, creates Volume identifiers under CSV Volumes. So after a Volume restore, we can restore Volume names with that index. Also scripts exports all virtual machine configs. That will make it easier to restore all Virtual Machines on Hyper-V.
On Main Site:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| ##################################################
# START ON MAIN SITE
##################################################
# Clear VM Config
$TestVMConfigPath = Test-Path -Path "C:\ClusterStorage\Volume1\VMExport.Config"
if ($TestVMConfigPath)
{
Clear-Content -Path "C:\ClusterStorage\Volume1\VMExport.Config"
}
# Export VM Config
$ClusterNodes = Get-Cluster | Get-ClusterNode
foreach ($ClusterNode in $ClusterNodes)
{
# Get Virtual Machines
$VMs = Get-VM -ComputerName $ClusterNode
# Export VM Config
foreach ($VM in $VMs)
{
# Get Virtual Machines
$VMConfigPath = $VM.ConfigurationLocation + "\Virtual Machines\" + $VM.Id + ".xml"
# Export to Config File
Add-Content -Value $VMConfigPath -Path "C:\ClusterStorage\Volume1\VMExport.Config"
}
}
# Read All CSV Directories
$CSVVolumes = Get-ChildItem "C:\ClusterStorage"
foreach ($CSVVolume in $CSVVolumes)
{
# Get CSV Volume Name
$CSVVolumeName = $CSVVolume.Name
# Get CSV Identifier Name
$CSVIdentifierName = $CSVVolumeName + ".CSV"
# Get CSV Path
$CSVPath = $CSVVolume.FullName
# Get CSV Identifier Path
$CSVIdentifierPath = $CSVPath + "\" + $CSVIdentifierName
# Test CSV Identifier Path
$TestCSVIdentifierPath = Test-Path $CSVIdentifierPath
if (!$TestCSVIdentifierPath)
{
# Create CSV Identifier
New-Item -Path "$CSVPath" -Name "$CSVIdentifierName" -ItemType File
}
} |
##################################################
# START ON MAIN SITE
##################################################
# Clear VM Config
$TestVMConfigPath = Test-Path -Path "C:\ClusterStorage\Volume1\VMExport.Config"
if ($TestVMConfigPath)
{
Clear-Content -Path "C:\ClusterStorage\Volume1\VMExport.Config"
}
# Export VM Config
$ClusterNodes = Get-Cluster | Get-ClusterNode
foreach ($ClusterNode in $ClusterNodes)
{
# Get Virtual Machines
$VMs = Get-VM -ComputerName $ClusterNode
# Export VM Config
foreach ($VM in $VMs)
{
# Get Virtual Machines
$VMConfigPath = $VM.ConfigurationLocation + "\Virtual Machines\" + $VM.Id + ".xml"
# Export to Config File
Add-Content -Value $VMConfigPath -Path "C:\ClusterStorage\Volume1\VMExport.Config"
}
}
# Read All CSV Directories
$CSVVolumes = Get-ChildItem "C:\ClusterStorage"
foreach ($CSVVolume in $CSVVolumes)
{
# Get CSV Volume Name
$CSVVolumeName = $CSVVolume.Name
# Get CSV Identifier Name
$CSVIdentifierName = $CSVVolumeName + ".CSV"
# Get CSV Path
$CSVPath = $CSVVolume.FullName
# Get CSV Identifier Path
$CSVIdentifierPath = $CSVPath + "\" + $CSVIdentifierName
# Test CSV Identifier Path
$TestCSVIdentifierPath = Test-Path $CSVIdentifierPath
if (!$TestCSVIdentifierPath)
{
# Create CSV Identifier
New-Item -Path "$CSVPath" -Name "$CSVIdentifierName" -ItemType File
}
}
Second Script on DR site, clears all old objects on Hyper-V and Failover Cluster. Restores volume names according to Volume Identifiers. After that imports all virtual machines by using our virtual machine exports.
On DR Site:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| ##################################################
# START ON DR SITE
##################################################
# Clear Failover Cluster Objects
$ClusterGroup = Get-ClusterGroup | Where GroupType -eq "VirtualMachine" | Remove-ClusterGroup -RemoveResources -Force
# Get All Cluster Nodes
$ClusterNodes = Get-Cluster | Get-ClusterNode
if ($ClusterNode in $ClusterNodes)
{
Invoke-Command -ComputerName $ClusterNode -ScriptBlock {
# Stop Hyper-V Management Service
Set-Service "vmms" -StartupType Disabled
Stop-Service "vmms"
# Clear Hyper-V Database
Get-ChildItem -Path "C:\ProgramData\Microsoft\Windows\Hyper-V\Virtual Machines" | Remove-Item
}
}
# Read All CSV Directories
$CSVVolumes = Get-ChildItem "C:\ClusterStorage"
# Clear Iteration
$i = 1;
foreach ($CSVVolume in $CSVVolumes)
{
# Create Time Guid
$TimeGuid = (Get-Date).ToString("ddMMyyyyhhmmss")
# Change CSV Volume Name
$CSVVolume | Rename-Item -NewName "CSVolume$TimeGuid$i"
# Update Iteration
$i++
}
# Read Updated CSV Directories
$CSVVolumes = Get-ChildItem "C:\ClusterStorage"
foreach ($CSVVolume in $CSVVolumes)
{
# Get CSV Volume Name
$CSVVolumeName = $CSVVolume.Name
# Get CSV Volume Filter
$CSVVolumeFilter = "*.CSV"
# Get CSV Path
$CSVPath = $CSVVolume.FullName
# Find CSV Identifier
$CSVIdentifier = $Null;
$CSVIdentifier = (Get-ChildItem "$CSVPath" -Filter "$CSVVolumeFilter" -Recurse).Name
$CSVIdentifier = $CSVIdentifier.Split(".")[0]
if ($CSVIdentifier)
{
# CSV Volume ID
$NewCSVVolumeName = "Volume" + $CSVIdentifier.Substring("0,6")
# Change CSV Volume Name
$CSVVolume | Rename-Item -NewName "$NewCSVVolumeName"
}
else
{
Write-Host "Error: Could not find CSV Identifier for $CSVVolume"
}
}
# Get All Cluster Nodes
$ClusterNodes = Get-Cluster | Get-ClusterNode
if ($ClusterNode in $ClusterNodes)
{
Invoke-Command -ComputerName $ClusterNode -ScriptBlock {
# Start Hyper-V Management Service
Set-Service "vmms" -StartupType Automatic
Start-Service "vmms"
}
}
# Get VM Import Config
$VMImportConfig = Get-Content "C:\ClusterStorage\Volume1\VMExport.Config"
foreach ($VM in $VMImportConfig)
{
# Import Virtual Machine
$ImportVM = Import-VM $VM
# Get Virtual Machine Name
$VMName = $ImportVM.Name
# Add VM to Failover Cluster
Add-VMToCluster $VMName
} |
##################################################
# START ON DR SITE
##################################################
# Clear Failover Cluster Objects
$ClusterGroup = Get-ClusterGroup | Where GroupType -eq "VirtualMachine" | Remove-ClusterGroup -RemoveResources -Force
# Get All Cluster Nodes
$ClusterNodes = Get-Cluster | Get-ClusterNode
if ($ClusterNode in $ClusterNodes)
{
Invoke-Command -ComputerName $ClusterNode -ScriptBlock {
# Stop Hyper-V Management Service
Set-Service "vmms" -StartupType Disabled
Stop-Service "vmms"
# Clear Hyper-V Database
Get-ChildItem -Path "C:\ProgramData\Microsoft\Windows\Hyper-V\Virtual Machines" | Remove-Item
}
}
# Read All CSV Directories
$CSVVolumes = Get-ChildItem "C:\ClusterStorage"
# Clear Iteration
$i = 1;
foreach ($CSVVolume in $CSVVolumes)
{
# Create Time Guid
$TimeGuid = (Get-Date).ToString("ddMMyyyyhhmmss")
# Change CSV Volume Name
$CSVVolume | Rename-Item -NewName "CSVolume$TimeGuid$i"
# Update Iteration
$i++
}
# Read Updated CSV Directories
$CSVVolumes = Get-ChildItem "C:\ClusterStorage"
foreach ($CSVVolume in $CSVVolumes)
{
# Get CSV Volume Name
$CSVVolumeName = $CSVVolume.Name
# Get CSV Volume Filter
$CSVVolumeFilter = "*.CSV"
# Get CSV Path
$CSVPath = $CSVVolume.FullName
# Find CSV Identifier
$CSVIdentifier = $Null;
$CSVIdentifier = (Get-ChildItem "$CSVPath" -Filter "$CSVVolumeFilter" -Recurse).Name
$CSVIdentifier = $CSVIdentifier.Split(".")[0]
if ($CSVIdentifier)
{
# CSV Volume ID
$NewCSVVolumeName = "Volume" + $CSVIdentifier.Substring("0,6")
# Change CSV Volume Name
$CSVVolume | Rename-Item -NewName "$NewCSVVolumeName"
}
else
{
Write-Host "Error: Could not find CSV Identifier for $CSVVolume"
}
}
# Get All Cluster Nodes
$ClusterNodes = Get-Cluster | Get-ClusterNode
if ($ClusterNode in $ClusterNodes)
{
Invoke-Command -ComputerName $ClusterNode -ScriptBlock {
# Start Hyper-V Management Service
Set-Service "vmms" -StartupType Automatic
Start-Service "vmms"
}
}
# Get VM Import Config
$VMImportConfig = Get-Content "C:\ClusterStorage\Volume1\VMExport.Config"
foreach ($VM in $VMImportConfig)
{
# Import Virtual Machine
$ImportVM = Import-VM $VM
# Get Virtual Machine Name
$VMName = $ImportVM.Name
# Add VM to Failover Cluster
Add-VMToCluster $VMName
}
After that, you will be able to start your virtual machines.