logo
关于我们

技术分享

技术分享 Hyper-v虚拟机备份与还原实现(二)

Hyper-v虚拟机备份与还原实现(二)

2020-09-08

上篇介绍备份和还原的整体流程,本骗具体介绍实现过程。

第一步 hyper-v虚拟机信息的获取 

     fd端获取所有hyper-v信息,同过dir给fd发送一个命令,fd端接收到命令字处理请求,调用一个system(“quryvm.exe”),在hyper-v端生成一个 hyper-v.conf文件,里面目前存放每一个hyper-v的三个主要参数,hyper-v虚拟机名,hyper-v虚拟机所在host名,hyper-v虚拟机硬盘文件路径;

若下图,hyper-v.conf 文件

big
HS22-3
C:/Users/Public/Documents/Hyper-V/Virtual Hard Disks/big.vhdx
418
SZY
C:/Users/Public/Documents/Hyper-V/Virtual Hard Disks/418.vhdx

对应的hyper-v管理界面如下图所示;

虚拟机big 在host为HS22-3的hyper-v服务器上 路径为 HS22-3的C:/Users/Public/Documents/Hyper-V/Virtual Hard Disks/big.vhdx

Hyper-v虚拟机备份与还原实现(二)

虚拟机418在host为SZY的hyper-v服务器上,路径为SZY的C:/Users/Public/Documents/Hyper-V/Virtual Hard Disks/418.vhdx

Hyper-v虚拟机备份与还原实现(二)

 

所有的信息都是通过quryvm.exe这个程序获得,下面请看quryvm.exe的源码

 

using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.IO;
using System.Text;
using System.Management;
using System.Text.RegularExpressions;
namespace queryvm
{
   #region Return Value of RequestStateChange Method of the Msvm_ComputerSystem Class
   //Return Value of RequestStateChange Method of the Msvm_ComputerSystem Class 
   //This method returns one of the following values.
   //Completed with No Error (0)
   //DMTF Reserved (7–4095) 
   //Method Parameters Checked - Transition Started (4096)
   //Failed (32768) 
   //Access Denied (32769) 
   //Not Supported (32770) 
   //Status is unknown (32771) 
   //Timeout (32772) 
   //Invalid parameter (32773) 
   //System is in use (32774) 
   //Invalid state for this operation (32775) 
   //Incorrect data type (32776) 
   //System is not available (32777) 
   //Out of memory (32778)
   #endregion

   public class VMManagement
   {
      private static string script = File.ReadAllText(@"C:\hyperv.ps1");
      private static void GetHyperPath(string vmname, string hhost)
      {
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("gethyperpath").AddParameters(
               new Dictionary<string, string>(){
                  {"name", vmname},
                  {"pcname", hhost}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
            }
         }
      }

      private static void Sethost(string hhost)
      {
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("sethost").AddParameters(
               new Dictionary<string, string>(){
                  {"hhost", hhost}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
            }
         }
      }

      private static void Clean(string clean)
      {
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("Clean").AddParameters(
               new Dictionary<string, string>(){
                  {"clean", clean}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
            }
         }
      }

      public static string ReadLineAddress()
      {
         String textFileName = @"C:\WINDOWS\system32\drivers\etc\hosts";
         TextReader tr = new StreamReader(textFileName);
         StringBuilder strtmp = new StringBuilder();
         string findstr = "";
         int i = 0;

         while (tr.Peek() > 0)
         {
            i++;
            findstr = tr.ReadLine();
            if (findstr.Contains("#"))
            {
               continue;
            }
            if (string.IsNullOrEmpty(findstr))
            {
               continue;
            }else{
               string temp = findstr;
               string[] words = Regex.Split(findstr, "\\s+", RegexOptions.IgnoreCase);
               strtmp.Append(words[1]);
               strtmp.Append("+");
            }
         }
         tr.Close();
         return strtmp.ToString();
      }

      public static int Main()
      {
         //Console.WriteLine("myxp");
         //return 0;
         
         try
         {
            //获取系统信息
            System.OperatingSystem osInfo = System.Environment.OSVersion;
            int versionMajor = osInfo.Version.Major;
            int versionMinor = osInfo.Version.Minor;

            string hostName = System.Net.Dns.GetHostName();
            string hhosts = hostName + "+" +ReadLineAddress();
            Console.WriteLine(hostName);
            string clean = "clean";
            Clean(clean);
            string vmNameSpace = @"\\{0}\root\virtualization\v2";
            string[] test = hhosts.Split('+');
            foreach (var ss in test)
            {
               if (string.IsNullOrEmpty(ss))
               {
                      continue;
               }
               Console.WriteLine(ss);
               ManagementScope manScope = new ManagementScope(string.Format(vmNameSpace, ss), null);
               manScope.Connect();
               //ObjectQuery queryObj = new ObjectQuery("SELECT * FROM Msvm_ComputerSystem where ProcessID >= 0");
               ObjectQuery queryObj = new ObjectQuery("SELECT * FROM Msvm_ComputerSystem where ElementName!=__SERVER");
               ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(manScope, queryObj);
               ManagementObjectCollection vmCollection = vmSearcher.Get();

               // loop through the machines
               foreach (ManagementObject vm in vmCollection)
               {
                  string vmname = vm["ElementName"].ToString();
                  Console.WriteLine("xuniji");
                  GetHyperPath(vmname,ss);
               }
            }
         }
         catch (Exception ex)
         {
            Console.WriteLine(ex.ToString());
            return -1;
         }
         return 0;
      }
   }
}

代码说明  先声明下小编是个C程序员,以前没有接触过任何C#程序

代码就比较简单了 这是通过c调system 函数调用queryvm.exe 而在 queryvm中调用了ps1脚本,其中cs代码中gethyperpath对应ps1中有相应函数,通过这个函数获取hyperv虚拟机系统,其他函数类似。获取所有虚拟机信息的思路 大致是这样的,通过一个循环,解析hosts文件中的hyperv服务器名,获取一个host然后获取 这个服务器上所有的虚拟机;本脚本只针对2012,(客户环境) 如果是03,08,16的话只需要修改相应ps1中的命令即可;

代码中hyper-v.psl如下

 

function gethyperpath
{
   param([string]$name,[string]$pcname)
   $name | Out-file -append -Encoding utf8 C:\hyper-v.conf
   $pcname | Out-file -append -Encoding utf8 C:\hyper-v.conf
   $b= Get-VM -VMName $name -ComputerName $pcname | Select-Object VMID
   $c= Get-VHD -VMID $b.VMID -ComputerName $pcname | Select-Object "Path"
   $c.Path.replace("\", "/") | Out-file -append -Encoding utf8 C:\hyper-v.conf
   return $name
}

function Clean
{
   param([string]$clean)
   Clear-Content C:\hyper-v.conf
   return $clean
}
function cleanname
{
   param([string]$cleanname)
   Clear-Content C:\name.conf
   return $cleanname
}

function getmemory
{
   param([string]$vname,[string]$hostname)
   $a=Get-VMMemory -VMName $vname -ComputerName $hostname
   return $a.Startup
}

function getcpunum
{
   param([string]$vname,[string]$hostname)
   $b=Get-VMProcessor -VMName $vname -ComputerName $hostname
   return $b.Count
}

function getnet
{
   param([string]$vname,[string]$hostname)
   $e=Get-VMNetworkAdapter $vname -ComputerName $hostname

   if([String]::IsNullOrEmpty($e.SwitchName))
   {
      $temp="null";
      return $temp
   }
   return $e.SwitchName
}

function getpath
{
   param([string]$vname,[string]$hostname)
   $b= Get-VM -VMName $vname -ComputerName $hostname | Select-Object VMID
   $c= Get-VHD -VMID $b.VMID -ComputerName $hostname | Select-Object "Path"
   return $c.Path
}

function getvmtype
{
   param([string]$vname,[string]$hostname)
   $d= Get-VM -VMName  $vname -ComputerName $hostname
   return $d.Generation
}

function createvm
{   param([string]$vname,[string]$vmtype,[string]$hostname,[string]$memory,[string]$cpunum,[string]$net,[string]$path)
   $vname
   $vmtype
   $hostname
   $memory
   $cpunum
   $net
   $path
   New-VM $vname -ComputerName $hostname -Generation $vmtype -MemoryStartupBytes $memory -VHDPath $path -SwitchName $net
   Set-VMProcessor -VMName $vname -ComputerName $hostname -Count $cpunum
   return 0
}
function createvmtwo
{  param([string]$vname,[string]$vmtype,[string]$hostname,[string]$memory,[string]$cpunum,[string]$path)
   $vname
   $vmtype
   $hostname
   $memory
   $cpunum
   $path.Trim()
   $svname= Get-VMSwitch -ComputerName $hostname
   if($svname.Name.Count -gt 1)
  {
     $net=$svname.Name[0];
  } else {
     $net=$svname.Name
   }
   $net
   New-VM $vname -ComputerName $hostname -Generation $vmtype -MemoryStartupBytes $memory -VHDPath $path  -SwitchName $net
   Set-VMProcessor -VMName $vname -ComputerName $hostname -Count $cpunum
   return 0
}

在获取完虚拟机名 host名,vhd路径后,fd端读取hyper-v.conf文件 ,通过一系列流程,回显给客户端页面,然后客户端勾选需要的虚拟机,勾选确定后,通过流程处理 ,将hyperv虚拟机名称host名称存入数据库,以备还原的时候用;

Hyper-v虚拟机备份与还原实现(二)

 

第二步 备份vhd文件

 第一步中选择备份的虚拟机时,可以将备份的vhdx路径记录下,然后同过备份软件 直接将vhd文件备份到指定的sd,涉及公司具体代码不做过多说明,以上代码纯个人开发的,转载请注明出处。

云祺备份软件,云祺容灾备份系统,虚拟机备份,数据库备份,文件备份,实时备份,勒索软件,美国,图书馆
  • 标签:
  • 容灾备份

您可能感兴趣的新闻 换一批

现在下载,可享30天免费试用

立即下载