Skip to content

Commit 313f861

Browse files
authored
Merge pull request #12 from sanderstad/Migrate-From-HyperV-to-DiskPart
Migrate from hyper-v to diskpart
2 parents c457689 + 81fdb80 commit 313f861

File tree

9 files changed

+105
-60
lines changed

9 files changed

+105
-60
lines changed

bin/PSDatabaseClone.dll

10 KB
Binary file not shown.

functions/clone/Get-PSDCClone.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@
207207
HostName = $result.HostName
208208
}
209209
}
210-
211210
}
212211

213212
end {

functions/clone/New-PSDCClone.ps1

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@
110110
)
111111

112112
begin {
113+
# Check if the setup has ran
114+
if (-not (Get-PSFConfigValue -FullName psdatabaseclone.setup.status)) {
115+
Stop-PSFFunction -Message "The module setup has NOT yet successfully run. Please run 'Set-PSDCConfiguration'"
116+
return
117+
}
118+
113119
# Get the information store
114120
$informationStore = Get-PSFConfigValue -FullName psdatabaseclone.informationstore.mode
115121

@@ -145,6 +151,9 @@
145151
if ($Disabled) {
146152
$active = 0
147153
}
154+
155+
# Set the location where to save the diskpart command
156+
$diskpartScriptFile = Get-PSFConfigValue -FullName psdatabaseclone.diskpart.scriptfile -Fallback "$env:APPDATA\psdatabaseclone\diskpartcommand.txt"
148157
}
149158

150159
process {
@@ -161,12 +170,6 @@
161170

162171
# Setup the computer object
163172
$computer = [PsfComputer]$server.Name
164-
165-
# Check if Hyper-V enabled for the SQL instance
166-
if (-not (Test-PSDCHyperVEnabled -HostName $computer.ComputerName -Credential $Credential)) {
167-
Stop-PSFFunction -Message "Hyper-V is not enabled on host." -ErrorRecord $_ -Target $computer -Continue
168-
return
169-
}
170173
}
171174
catch {
172175
Stop-PSFFunction -Message "Could not connect to Sql Server instance $instance" -ErrorRecord $_ -Target $instance
@@ -357,9 +360,15 @@
357360
try {
358361
Write-PSFMessage -Message "Creating clone from $ParentVhd" -Level Verbose
359362

363+
$command = "create vdisk file='$Destination\$CloneName.vhdx' parent='$ParentVhd'"
364+
360365
# Check if computer is local
361366
if ($computer.IsLocalhost) {
362-
$vhd = New-VHD -ParentPath $ParentVhd -Path "$Destination\$CloneName.vhdx" -Differencing
367+
# Set the content of the diskpart script file
368+
Set-Content -Path $diskpartScriptFile -Value $command -Force
369+
370+
$script = [ScriptBlock]::Create("diskpart /s $diskpartScriptFile")
371+
$null = Invoke-PSFCommand -ScriptBlock $script
363372
}
364373
else {
365374
$command = [ScriptBlock]::Create("New-VHD -ParentPath $ParentVhd -Path `"$Destination\$CloneName.vhdx`" -Differencing")
@@ -372,7 +381,7 @@
372381

373382
}
374383
catch {
375-
Stop-PSFFunction -Message "Could not create clone" -Target $vhd -Continue
384+
Stop-PSFFunction -Message "Could not create clone" -Target $vhd -Continue -ErrorRecord $_
376385
}
377386
}
378387

@@ -384,14 +393,14 @@
384393
# Check if computer is local
385394
if ($computer.IsLocalhost) {
386395
# Mount the disk
387-
$null = Mount-VHD -Path "$Destination\$CloneName.vhdx" -NoDriveLetter
396+
$null = Mount-DiskImage -ImagePath "$Destination\$CloneName.vhdx"
388397

389398
# Get the disk based on the name of the vhd
390399
$disk = Get-Disk | Where-Object {$_.Location -eq "$Destination\$CloneName.vhdx"}
391400
}
392401
else {
393402
# Mount the disk
394-
$command = [ScriptBlock]::Create("Mount-VHD -Path `"$Destination\$CloneName.vhdx`" -NoDriveLetter")
403+
$command = [ScriptBlock]::Create("Mount-DiskImage -ImagePath `"$Destination\$CloneName.vhdx`"")
395404
$null = Invoke-PSFCommand -ComputerName $computer -ScriptBlock $command -Credential $Credential
396405

397406
# Get the disk based on the name of the vhd

functions/clone/Remove-PSDCClone.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,14 @@
224224
try {
225225

226226
if ($computer.IsLocalhost) {
227-
$null = Dismount-VHD -Path $item.CloneLocation -Credential $Credential
227+
$null = Dismount-DiskImage -ImagePath $item.CloneLocation
228228
}
229229
else {
230230
$command = [ScriptBlock]::Create("Test-Path -Path '$($item.CloneLocation)'")
231231
Write-PSFMessage -Message "Dismounting disk '$($item.CloneLocation)' from $($item.HostName)" -Level Verbose
232232
$result = Invoke-PSFCommand -ComputerName $item.HostName -ScriptBlock $command -Credential $Credential
233233
#if (-not $result) {
234-
$command = [scriptblock]::Create("Dismount-VHD -Path '$($item.CloneLocation)'")
234+
$command = [scriptblock]::Create("Dismount-DiskImage -ImagePath '$($item.CloneLocation)'")
235235
$null = Invoke-PSFCommand -ComputerName $item.HostName -ScriptBlock $command -Credential $Credential
236236
#}
237237
}

functions/disk/Initialize-PSDCVhdDisk.ps1

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,19 @@
8787
Write-PSFMessage -Message "Vhd is already mounted" -Level Warning
8888

8989
# retrieve the specific disk
90-
$disk = $disks | Where-Object {$_.Location -eq $Path}
90+
$disk = $disks | Where-Object Location -eq $Path
9191
}
9292
else {
93-
if ($PSCmdlet.ShouldProcess($disk, "Mounting disk")) {
93+
if ($PSCmdlet.ShouldProcess("Mounting disk")) {
9494
# Mount the vhd
9595
try {
9696
Write-PSFMessage -Message "Mounting disk $disk" -Level Verbose
9797

98-
$disk = Mount-VHD -Path $Path -PassThru | Get-Disk
98+
# Mount the disk
99+
Mount-DiskImage -ImagePath $Path
100+
101+
# Get the disk
102+
$disk = Get-Disk | Where-Object Location -eq $Path
99103
}
100104
catch {
101105
Stop-PSFFunction -Message "Couldn't mount vhd" -Target $Path -ErrorRecord $_ -Continue
@@ -123,7 +127,7 @@
123127
}
124128
catch {
125129
# Dismount the drive
126-
Dismount-VHD -Path $Path
130+
Dismount-DiskImage -DiskImage $Path
127131

128132
Stop-PSFFunction -Message "Couldn't create the partition" -Target $disk -ErrorRecord $_ -Continue
129133
}

functions/disk/New-PSDCVhdDisk.ps1

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@
1515
.PARAMETER FileName
1616
The file name of the VHD
1717
18+
.PARAMETER VhdType
19+
The type of the harddisk. This can either by VHD (version 1) or VHDX (version 2)
20+
The default is VHDX.
21+
1822
.PARAMETER Size
19-
The size of the VHD.
23+
The size of the VHD in MB.
24+
If no size is used the default will be set to the type of VHD.
25+
The default for VHD is 2 TB and for VHDX 64TB
2026
2127
.PARAMETER FixedSize
2228
Set the VHD to have a fixed size or not.
@@ -63,7 +69,9 @@
6369
[string]$Destination,
6470
[string]$Name,
6571
[string]$FileName,
66-
[uint64]$Size = 64TB,
72+
[ValidateSet('VHD', 'VHDX')]
73+
[string]$VhdType,
74+
[uint64]$Size,
6775
[switch]$FixedSize,
6876
[switch]$ReadOnly,
6977
[switch]$Force,
@@ -84,13 +92,42 @@
8492
}
8593
}
8694

95+
# Check the vhd type
96+
if (-not $VhdType) {
97+
Write-PSFMessage -Message "Setting vhd type to 'VHD" -Level Verbose
98+
$VhdType = 'VHDX'
99+
}
100+
101+
# Check the size of the file
102+
if (-not $Size) {
103+
switch ($VhdType) {
104+
'VHD' { $Size = 2TB }
105+
'VHDX' { $Size = 64TB }
106+
}
107+
108+
# Make sure the size in MB instead of some other version
109+
$Size = $Size / 1MB
110+
}
111+
else {
112+
if ($VhdType -eq 'VHD' -and $size -gt 2TB) {
113+
Stop-PSFFunction -Message "Size cannot exceed 2TB when using VHD type."
114+
}
115+
elseif ($VhdType -eq 'VHDX' -and $size -gt 64TB) {
116+
Stop-PSFFunction -Message "Size cannot exceed 64TB when using VHDX type."
117+
}
118+
119+
if ($Size -lt 3MB) {
120+
Stop-PSFFunction -Message "The size of the vhd cannot be smaller than 3MB" -Continue
121+
}
122+
}
123+
87124
# Check the name and file name parameters
88125
if (-not $Name -and -not $FileName) {
89126
Stop-PSFFunction -Message "Either set the Name or FileName parameter"
90127
}
91128
else {
92129
if (-not $FileName) {
93-
$FileName = "$Name.vhdx"
130+
$FileName = "$Name.$($VhdType.ToLower())"
94131
Write-PSFMessage -Message "Setting file name to $FileName" -Level Verbose
95132
}
96133
elseif ($FileName) {
@@ -112,13 +149,21 @@
112149

113150
# Check if the file does not yet exist
114151
if (Test-Path $vhdPath) {
115-
Stop-PSFFunction -Message "The vhd file already exists" -Continue
152+
if(-not $Force){
153+
Stop-PSFFunction -Message "The vhd file already exists" -Continue
154+
}
155+
else{
156+
try{
157+
Remove-Item -Path $vhdPath -Force:$Force
158+
}
159+
catch{
160+
Stop-PSFFunction -Message "Could not remove VHD '$vhdPath'" -Continue -ErrorRecord $_
161+
}
162+
}
116163
}
117164

118-
# Check the size of the file
119-
if ($Size -lt 3MB) {
120-
Stop-PSFFunction -Message "The size of the vhd cannot be smaller than 3MB" -Continue
121-
}
165+
# Set the location where to save the diskpart command
166+
$diskpartScriptFile = Get-PSFConfigValue -FullName psdatabaseclone.diskpart.scriptfile -Fallback "$env:APPDATA\psdatabaseclone\diskpartcommand.txt"
122167
}
123168

124169
process {
@@ -129,11 +174,18 @@
129174
# Check if the file needs to have a fixed size
130175
try {
131176
if ($FixedSize) {
132-
$null = New-VHD -Path $vhdPath -SizeBytes $Size -Fixed
177+
$command = "create vdisk file='$vhdPath' maximum=$Size type=fixed"
133178
}
134179
else {
135-
$null = New-VHD -Path $vhdPath -SizeBytes $Size -Dynamic
180+
$command = "create vdisk file='$vhdPath' maximum=$Size type=expandable"
136181
}
182+
183+
# Set the content of the diskpart script file
184+
Set-Content -Path $diskpartScriptFile -Value $command -Force
185+
186+
$script = [ScriptBlock]::Create("diskpart /s $diskpartScriptFile")
187+
Invoke-PSFCommand -ScriptBlock $script
188+
137189
}
138190
catch {
139191
Stop-PSFFunction -Message "Something went wrong creating the vhd" -ErrorRecord $_ -Continue
@@ -142,6 +194,9 @@
142194
}
143195

144196
end {
197+
# Clean up the script file for diskpart
198+
Remove-Item $diskpartScriptFile -Force
199+
145200
# Test if there are any errors
146201
if (Test-PSFFunctionInterrupt) { return }
147202

functions/image/New-PSDCImage.ps1

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,6 @@
300300
Stop-PSFFunction -Message "Please supply a database to create an image for" -Target $SourceSqlInstance -Continue
301301
}
302302

303-
# Check if Hyper-V is enabled
304-
if (-not (Test-PSDCHyperVEnabled -HostName $uriHost -Credential $DestinationCredential)) {
305-
Stop-PSFFunction -Message "Hyper-V is not enabled on the host." -ErrorRecord $_ -Target $uriHost
306-
return
307-
}
308-
309303
# Set time stamp
310304
$timestamp = Get-Date -format "yyyyMMddHHmmss"
311305

@@ -500,7 +494,7 @@
500494
$restore = Restore-DbaDatabase -SqlInstance $DestinationSqlInstance -SqlCredential $DestinationSqlCredential `
501495
-DatabaseName $tempDbName -Path $lastFullBackup `
502496
-DestinationDataDirectory $imageDataFolder `
503-
-DestinationLogDirectory $imageLogFolder
497+
-DestinationLogDirectory $imageLogFolder -WithReplace
504498
}
505499
catch {
506500
Stop-PSFFunction -Message "Couldn't restore database $db as $tempDbName on $DestinationSqlInstance" -Target $restore -ErrorRecord $_ -Continue
@@ -526,13 +520,13 @@
526520
# Check if computer is local
527521
if ($computer.IsLocalhost) {
528522
# Dismount the VHD
529-
$null = Dismount-VHD -Path $vhdPath
523+
$null = Dismount-DiskImage -ImagePath $vhdPath
530524

531525
# Remove the access path
532526
$null = Remove-Item -Path $accessPath -Force
533527
}
534528
else {
535-
$command = [ScriptBlock]::Create("Dismount-VHD -Path $vhdPath")
529+
$command = [ScriptBlock]::Create("Dismount-DiskImage -ImagePath $vhdPath")
536530
$null = Invoke-PSFCommand -ComputerName $computer -ScriptBlock $command -Credential $DestinationCredential
537531

538532
$command = [ScriptBlock]::Create("Remove-Item -Path $accessPath -Force")

functions/support/Set-PSDCConfiguration.ps1

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
# Set the variable for the information store
204204
$InformationStore = 'File'
205205
}
206+
206207
}
207208

208209
# Unregister any configurations
@@ -376,9 +377,6 @@
376377
Set-PSFConfig -Module PSDatabaseClone -Name informationstore.credential -Value $Credential
377378
}
378379

379-
# Set if Hyper-V is enabled
380-
Set-PSFConfig -Module PSDatabaseClone -Name hyperv.enabled -Value (Test-PSDCHyperVEnabled) -Validation bool
381-
382380
# Set the information store mode
383381
Set-PSFConfig -Module PSDatabaseClone -Name informationstore.mode -Value $InformationStore
384382

@@ -390,9 +388,9 @@
390388
Get-PSFConfig -FullName psdatabaseclone.database.server | Register-PSFConfig -Scope SystemDefault
391389
Get-PSFConfig -FullName psdatabaseclone.database.name | Register-PSFConfig -Scope SystemDefault
392390

393-
Get-PSFConfig -FullName psdatabaseclone.hyperv.enabled | Register-PSFConfig -Scope SystemDefault
394-
395-
#Get-PSFConfig -FullName psdatabaseclone.database.credential | Register-PSFConfig -Scope SystemDefault
391+
# Set the path to the diskpart script file
392+
Set-PSFConfig -Module PSDatabaseClone -Name diskpart.scriptfile -Value "$env:APPDATA\psdatabaseclone\diskpartcommand.txt" -Validation string
393+
Get-PSFConfig -FullName psdatabaseclone.diskpart.scriptfile | Register-PSFConfig -Scope SystemDefault
396394

397395
# Check if all the settings have been made
398396
if ($InformationStore -eq 'SQL') {
@@ -423,6 +421,8 @@
423421

424422
# Set the overall status in the configurations
425423
Get-PSFConfig -FullName psdatabaseclone.setup.status | Register-PSFConfig -Scope SystemDefault
424+
425+
426426
}
427427

428428
end {

internal/scripts/preimport.ps1

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Check if window is in elevated mode
22
$elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
33
if ( -not $elevated ) {
4-
Stop-PSFFunction -Message "Module requires elevation" -Target $elevated -FunctionName 'Pre Import'
4+
Stop-PSFFunction -Message "Module requires elevation" -Target $elevated -FunctionName 'Pre Import'
55
}
66

77
# Set the supported version of Windows
@@ -20,23 +20,7 @@ $osDetails = Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Desc
2020
# Check which version of windows we're dealing with
2121
if ($osDetails.Caption -notin $supportedVersions ) {
2222
if ($osDetails.Caption -like '*Windows 7*') {
23-
Stop-PSFFunction -Message "Module can not work on Windows 7" -Target $OSDetails -FunctionName 'Pre Import'
24-
}
25-
elseif ($osDetails.Caption -like '*Windows 10*') {
26-
$feature = Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-All' -Online
27-
if ($feature.State -ne "Enabled") {
28-
Write-PSFMessage -Message "Hyper-V is not enabled, the module can only be used remotely.`nTo use the module locally execute the following command: `"Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All`"" -Level Warning -FunctionName 'Test-PSDCConfiguration'
29-
}
30-
31-
Stop-PSFFunction -Message "Module can only work on Windows 10 Pro, Enterprise or Education" -Target $OSDetails -FunctionName 'Pre Import'
32-
}
33-
elseif ($osDetails.Caption -like '*Windows Server*') {
34-
$feature = Get-WindowsFeature -Name 'Hyper-V'
35-
if (-not $feature.Installed) {
36-
Write-PSFMessage -Message "Hyper-V is not enabled, the module can only be used remotely.`nTo use the module execute the following command:`n `"Install-WindowsFeature -Name Hyper-V`"`n`"Install-WindowsFeature -Name Hyper-V-PowerShell`"" -Level Warning -FunctionName 'Pre Import'
37-
}
38-
39-
Stop-PSFFunction -Message "Module can only work on Windows Server 2012 R2 and up, Enterprise or Education" -Target $OSDetails -FunctionName 'Pre Import'
23+
Stop-PSFFunction -Message "Module does not work on Windows 7" -Target $OSDetails -FunctionName 'Pre Import'
4024
}
4125
else {
4226
Stop-PSFFunction -Message "Unsupported version of Windows." -Target $OSDetails -FunctionName 'Pre Import'

0 commit comments

Comments
 (0)