none
Резервное копирование виртуальных машин в Windows Hyper-V Server 2008 R2 штатными средствами? RRS feed

  • Вопрос

  • Добрый вечер! Собственно, возможно ли резервное копирование виртуальных машин в Windows Hyper-V Server 2008 R2 штатными средствами? Если да, то какими? Или придется выполнять резервное копирование внутри каждой ВМ? Спасибо!
    12 октября 2011 г. 19:56

Ответы

  • http://support.microsoft.com/kb/958662

    http://technet.microsoft.com/en-us/windowsserver/dd775213

    Только стоит учесть ограничения. В частности так нельзя, например, резервировать контроллеры домены.

    Вообще, на мой взгляд, правильнее резервировать данные, как для обычной машины, нежели целиком виртуалку. Хотя все зависит от конкретной ситуации.

    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:32
    • Снята пометка об ответе B2BF 13 октября 2011 г. 20:32
    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:33
    13 октября 2011 г. 3:59
  • Это можно сделать, например, скриптом на PowerShell выполняемым по расписанию через планировщик заданий.

    Если возможно временное выключение (минут на 10-15) или приостановка работы виртуальных машин, то Powershell наиболее простой вариант.

    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:33
    13 октября 2011 г. 4:09
  • 1. Планировщик скорее всего можно настроить через команду schtasks или тот же PowerShell.

    2. Я для данных целей пользуюсь скриптами следующего содержания:

    --- Begin ExportVMs.ps1 ---

    $WBAdmin_Backup_Disk = "E:"
    $BackupFolder = "E:\Backups"
    $MaxKeepTime=30


    $VMHost = $env:ComputerName

    $VMBackupFolder = "$BackupFolder\VirtualMachines"
    $HostBackupFolder = "$BackupFolder\$VMHost"

    $CurrentDate = Get-Date -uformat "%Y-%m-%d"
    $CurrentDateTime = Get-Date -uformat "%Y-%m-%d_%H-%M"


    Function VMStart($GuestVM)
       {
          Write-Host "Starting $GuestVM"

          $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"
          While(!($VM.EnabledState -eq 2))
             {
                $VM.RequestStateChange(2)
                Start-Sleep -s 3
                $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"    
             }
       }


    Function VMShutdown($GuestVM)
       {
          Write-Host "Shutting down $GuestVM"

          $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"
          $VMName = $VM.Name
          $VMShutdown = GWMI -namespace root\virtualization -query "Select * FROM MSVM_ShutdownComponent WHERE SystemName='$VMName'"
          $Result = $VMShutdown.InitiateShutdown(1,"no comment")
          While (!($VM.EnabledState -eq 3) -and !($VM.EnabledState -eq 32769))
             {
                Start-Sleep -s 3
                $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"    
             }
       }

     


    If ($args[1] -match "Start")
       {
          $InputFile = Get-Content $args[0]
          ForEach ($Guest in $InputFile)
             {
                VMStart $Guest  
             }
       }


    If ($args[1] -match "Shutdown")
       {
          $InputFile = Get-Content $args[0]
          ForEach ($Guest in $InputFile)
             {
                VMShutdown $Guest
             }
       }


    If ($args[1] -match "Export")
       {
          $InputFile = Get-Content $args[0]
          ForEach ($Guest in $InputFile)
             {
                VMShutdown $Guest

                Start-Sleep -s 30
                Write-Host "Export VM: $guest"

                if (![IO.Directory]::Exists("$VMBackupFolder\$CurrentDate\$Guest"))
                   {
                      [IO.Directory]::CreateDirectory("$VMBackupFolder\$CurrentDate\$Guest")
                   }

                $BackCurrGuest = "$VMBackupFolder\Current\$Guest"
                if ([IO.Directory]::Exists("$BackCurrGuest"))
                   {               
                      Remove-Item -Recurse -Force -Path $BackCurrGuest
                   }
                [IO.Directory]::CreateDirectory("$BackCurrGuest")


                $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$Guest'"
                $VMExport = GWMI -namespace root\virtualization -query "Select * from MSVM_VirtualSystemManagementService where SystemName='$VMHost'"
                $Result = $VMExport.ExportVirtualSystem($VM,1,"$BackCurrGuest")
                if ($Result.ReturnValue -eq 4096)
                   {
                      $Job = [WMI]$Result.Job
                      while ($Job.JobState -eq 4)
                         {
                            Start-Sleep 3
                            $Job.PSBase.Get()
                         }
                      if ($Job.JobState -ne 7)
                         {
                            Write-Error $Job.ErrorDescription
                            Throw $Job.ErrorDescription
                         }
                   }
                elseif ($Result.ReturnValue -ne 0)
                   {
                      Throw $Result.ReturnValue
                   }

                Start-Sleep -s 30
                VMStart $Guest

                $ArchiveName="$VMBackupFolder\$CurrentDate\$Guest\$Guest"+"_"+"$CurrentDateTime"+".rar"

                &((Split-Path -parent $MyInvocation.MyCommand.Path) + "\rar.exe") a -rr5%% -ep1 -m5 -y -os "$ArchiveName" "$BackCurrGuest"
             }
       }


    If ($args[0] -match "VMRemoveOld")
       {
          ForEach ($SubDir in (dir $VMBackupFolder))
             {
                If (($SubDir.Attributes -eq "Directory") -and ($SubDir.Name -as [DateTime]))
                   {
                      If ([DateTime]::ParseExact($SubDir.Name,'yyyy-MM-dd',$null) -lt (Get-Date).AddDays(-($MaxKeepTime)))
                         {
                            Del $SubDir.FullName -Recurse -Force
                         }
                   }
             }
       }

     

    If ($args[0] -match "HostRemoveOld")
       {
          ForEach ($SubDir in (dir $HostBackupFolder))
             {
                If (($SubDir.Attributes -eq "Directory") -and ($SubDir.Name -as [DateTime]))
                   {
                      If ([DateTime]::ParseExact($SubDir.Name,'yyyy-MM-dd',$null) -lt (Get-Date).AddDays(-($MaxKeepTime)))
                         {
                            Del $SubDir.FullName -Recurse -Force
                         }
                   }
             }
       }


    If ($args[0] -match "BackupHost")
       {
          if (![IO.Directory]::Exists("$HostBackupFolder\$CurrentDate"))
             {
                [IO.Directory]::CreateDirectory("$HostBackupFolder\$CurrentDate")
             }

          &("WBAdmin") Start Backup -BackupTarget:"$WBAdmin_Backup_Disk" -AllCritical -SystemState -Quiet

          $ArchiveName="$HostBackupFolder\$CurrentDate\$VMHost"+"_"+"$CurrentDateTime"+".rar"

          &("C:\tasks\rar.exe") a -rr5%% -ep1 -m5 -y -os "$ArchiveName" "$WBAdmin_Backup_Disk\WindowsImageBackup"
       }

    --- End ExportVMs.ps1 ---

     

    --- Begin VMExport.cmd ---

    REM   Экспорт виртуальных машин по списку (VMList.txt):
    Powershell.exe "%~dp0ExportVMs.ps1" "%~dp0VMList.txt" Export

    REM   Удаление старых бэкапов:
    Powershell.exe "%~dp0ExportVMs.ps1" VMRemoveOld

    --- End VMExport.cmd ---

    Запускаться через планировщик должен VMExport.cmd. Ну а в файле VMList.txt должен храниться список виртуальных машин (в каждой строчке одно имя, такое же как и в консоли Hyper-V) подлежащих бэкапу.

    P.S: В моем все необходимые файлы (в том числе и консольный архиватор rar.) должны лежать в папке c:\tasks.
    • Изменено Evgenii Alekseev 13 октября 2011 г. 10:40
    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:33
    13 октября 2011 г. 10:39

Все ответы

  • http://support.microsoft.com/kb/958662

    http://technet.microsoft.com/en-us/windowsserver/dd775213

    Только стоит учесть ограничения. В частности так нельзя, например, резервировать контроллеры домены.

    Вообще, на мой взгляд, правильнее резервировать данные, как для обычной машины, нежели целиком виртуалку. Хотя все зависит от конкретной ситуации.

    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:32
    • Снята пометка об ответе B2BF 13 октября 2011 г. 20:32
    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:33
    13 октября 2011 г. 3:59
  • Это можно сделать, например, скриптом на PowerShell выполняемым по расписанию через планировщик заданий.

    Если возможно временное выключение (минут на 10-15) или приостановка работы виртуальных машин, то Powershell наиболее простой вариант.

    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:33
    13 октября 2011 г. 4:09
  • http://support.microsoft.com/kb/958662

    http://technet.microsoft.com/en-us/windowsserver/dd775213

    Только стоит учесть ограничения. В частности так нельзя, например, резервировать контроллеры домены.

    Вообще, на мой взгляд, правильнее резервировать данные, как для обычной машины, нежели целиком виртуалку. Хотя все зависит от конкретной ситуации.

    Контроллер Домена -- это как раз наш случай :(

    Резервировать данные внутри ВМ -- это обязательно! Но хотелось бы и сам образ ВМ иметь в запасе. Тем более, что это будет единственный Контроллер Домена (не охота каждый раз поднимать Домен, забивать учетки, а еще и инфраструктуру PKI настраивать...). Собственно, ВМ будет 2 -- Windows Server и Linux. В дальнейшем возможно еще несколько ВМ с Windows Server добавятся, но каждая из них будет Контроллером Домена и между собой они пересекаться не будут.

     

    13 октября 2011 г. 9:43
  • Это можно сделать, например, скриптом на PowerShell выполняемым по расписанию через планировщик заданий.

    Если возможно временное выключение (минут на 10-15) или приостановка работы виртуальных машин, то Powershell наиболее простой вариант.


    В принципе, раз в неделю можно запланировать остановку ВМ и копирование образа...

    Тут несколько вопросов:

    - Как настроить планировщик в Windows Hyper-V Server?

    - как скриптом остановить машину, скопировать образ и запустить машину?

    13 октября 2011 г. 9:45
  • 1. Планировщик скорее всего можно настроить через команду schtasks или тот же PowerShell.

    2. Я для данных целей пользуюсь скриптами следующего содержания:

    --- Begin ExportVMs.ps1 ---

    $WBAdmin_Backup_Disk = "E:"
    $BackupFolder = "E:\Backups"
    $MaxKeepTime=30


    $VMHost = $env:ComputerName

    $VMBackupFolder = "$BackupFolder\VirtualMachines"
    $HostBackupFolder = "$BackupFolder\$VMHost"

    $CurrentDate = Get-Date -uformat "%Y-%m-%d"
    $CurrentDateTime = Get-Date -uformat "%Y-%m-%d_%H-%M"


    Function VMStart($GuestVM)
       {
          Write-Host "Starting $GuestVM"

          $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"
          While(!($VM.EnabledState -eq 2))
             {
                $VM.RequestStateChange(2)
                Start-Sleep -s 3
                $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"    
             }
       }


    Function VMShutdown($GuestVM)
       {
          Write-Host "Shutting down $GuestVM"

          $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"
          $VMName = $VM.Name
          $VMShutdown = GWMI -namespace root\virtualization -query "Select * FROM MSVM_ShutdownComponent WHERE SystemName='$VMName'"
          $Result = $VMShutdown.InitiateShutdown(1,"no comment")
          While (!($VM.EnabledState -eq 3) -and !($VM.EnabledState -eq 32769))
             {
                Start-Sleep -s 3
                $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$GuestVM'"    
             }
       }

     


    If ($args[1] -match "Start")
       {
          $InputFile = Get-Content $args[0]
          ForEach ($Guest in $InputFile)
             {
                VMStart $Guest  
             }
       }


    If ($args[1] -match "Shutdown")
       {
          $InputFile = Get-Content $args[0]
          ForEach ($Guest in $InputFile)
             {
                VMShutdown $Guest
             }
       }


    If ($args[1] -match "Export")
       {
          $InputFile = Get-Content $args[0]
          ForEach ($Guest in $InputFile)
             {
                VMShutdown $Guest

                Start-Sleep -s 30
                Write-Host "Export VM: $guest"

                if (![IO.Directory]::Exists("$VMBackupFolder\$CurrentDate\$Guest"))
                   {
                      [IO.Directory]::CreateDirectory("$VMBackupFolder\$CurrentDate\$Guest")
                   }

                $BackCurrGuest = "$VMBackupFolder\Current\$Guest"
                if ([IO.Directory]::Exists("$BackCurrGuest"))
                   {               
                      Remove-Item -Recurse -Force -Path $BackCurrGuest
                   }
                [IO.Directory]::CreateDirectory("$BackCurrGuest")


                $VM = GWMI -namespace root\virtualization -query "Select * from MSVM_ComputerSystem where ElementName='$Guest'"
                $VMExport = GWMI -namespace root\virtualization -query "Select * from MSVM_VirtualSystemManagementService where SystemName='$VMHost'"
                $Result = $VMExport.ExportVirtualSystem($VM,1,"$BackCurrGuest")
                if ($Result.ReturnValue -eq 4096)
                   {
                      $Job = [WMI]$Result.Job
                      while ($Job.JobState -eq 4)
                         {
                            Start-Sleep 3
                            $Job.PSBase.Get()
                         }
                      if ($Job.JobState -ne 7)
                         {
                            Write-Error $Job.ErrorDescription
                            Throw $Job.ErrorDescription
                         }
                   }
                elseif ($Result.ReturnValue -ne 0)
                   {
                      Throw $Result.ReturnValue
                   }

                Start-Sleep -s 30
                VMStart $Guest

                $ArchiveName="$VMBackupFolder\$CurrentDate\$Guest\$Guest"+"_"+"$CurrentDateTime"+".rar"

                &((Split-Path -parent $MyInvocation.MyCommand.Path) + "\rar.exe") a -rr5%% -ep1 -m5 -y -os "$ArchiveName" "$BackCurrGuest"
             }
       }


    If ($args[0] -match "VMRemoveOld")
       {
          ForEach ($SubDir in (dir $VMBackupFolder))
             {
                If (($SubDir.Attributes -eq "Directory") -and ($SubDir.Name -as [DateTime]))
                   {
                      If ([DateTime]::ParseExact($SubDir.Name,'yyyy-MM-dd',$null) -lt (Get-Date).AddDays(-($MaxKeepTime)))
                         {
                            Del $SubDir.FullName -Recurse -Force
                         }
                   }
             }
       }

     

    If ($args[0] -match "HostRemoveOld")
       {
          ForEach ($SubDir in (dir $HostBackupFolder))
             {
                If (($SubDir.Attributes -eq "Directory") -and ($SubDir.Name -as [DateTime]))
                   {
                      If ([DateTime]::ParseExact($SubDir.Name,'yyyy-MM-dd',$null) -lt (Get-Date).AddDays(-($MaxKeepTime)))
                         {
                            Del $SubDir.FullName -Recurse -Force
                         }
                   }
             }
       }


    If ($args[0] -match "BackupHost")
       {
          if (![IO.Directory]::Exists("$HostBackupFolder\$CurrentDate"))
             {
                [IO.Directory]::CreateDirectory("$HostBackupFolder\$CurrentDate")
             }

          &("WBAdmin") Start Backup -BackupTarget:"$WBAdmin_Backup_Disk" -AllCritical -SystemState -Quiet

          $ArchiveName="$HostBackupFolder\$CurrentDate\$VMHost"+"_"+"$CurrentDateTime"+".rar"

          &("C:\tasks\rar.exe") a -rr5%% -ep1 -m5 -y -os "$ArchiveName" "$WBAdmin_Backup_Disk\WindowsImageBackup"
       }

    --- End ExportVMs.ps1 ---

     

    --- Begin VMExport.cmd ---

    REM   Экспорт виртуальных машин по списку (VMList.txt):
    Powershell.exe "%~dp0ExportVMs.ps1" "%~dp0VMList.txt" Export

    REM   Удаление старых бэкапов:
    Powershell.exe "%~dp0ExportVMs.ps1" VMRemoveOld

    --- End VMExport.cmd ---

    Запускаться через планировщик должен VMExport.cmd. Ну а в файле VMList.txt должен храниться список виртуальных машин (в каждой строчке одно имя, такое же как и в консоли Hyper-V) подлежащих бэкапу.

    P.S: В моем все необходимые файлы (в том числе и консольный архиватор rar.) должны лежать в папке c:\tasks.
    • Изменено Evgenii Alekseev 13 октября 2011 г. 10:40
    • Помечено в качестве ответа B2BF 13 октября 2011 г. 20:33
    13 октября 2011 г. 10:39