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

备份完还原就比较简单了;

第一步 dir管理端执行还原任务从数据库获取需要还原的hyperv虚拟机和host名;

不做过多说明;

第二步 fd端通过hyperv虚拟机名和host名 还原虚拟机

还原主要通过一个New-VM命令,fd通过调用system(“restore.exe”)来执行还原;

restore.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 restore
{

   public class Program
   {
      private static string script = File.ReadAllText(@"C:\hyperv.ps1");
      public static string ReadLineAddress()
      {
         String textFileName = @"C:\name.conf";
         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{
               strtmp.Append(findstr);
               strtmp.Append("+");
            }
         }
         tr.Close();
         return strtmp.ToString();
      }

      private static string  getmemory(string vmname, string hostname)
      {
         string ret="";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("getmemory").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname",hostname}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string getcpunum(string vmname,string hostname)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("getcpunum").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname",hostname}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string getnet(string vmname , string hostname)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("getnet").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname", hostname}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string getpath(string vmname, string hostname)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("getpath").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname", hostname}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string getVMtype(string vmname, string hostname)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("getvmtype").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname", hostname}
               }
            );

            foreach (PSObject result in ps.Invoke()) 
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string getvhdsize(string vmname, string hostname)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("getvhdsize").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname", hostname}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string setcpunum(string vmname, string hostname, string cpunum)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("setcpunum").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"hostname", hostname},
                  {"cpunum", cpunum}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string creatvm(string vmname, string vmtype,string hostname, string memory, string cpunum, string net, string path )
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("createvm").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"vmtype",vmtype},
                  {"hostname",hostname},
                  {"memory", memory},
                  {"cpunum", cpunum},
                  {"net", net},
                  {"path", path}
                  //{"vhdsize",vhdsize}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

      private static string creatvmtwo(string vmname, string vmtype, string hostname, string memory, string cpunum, string path)
      {
         string ret = "";
         using (Runspace runspace = RunspaceFactory.CreateRunspace())
         {
            runspace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runspace;
            ps.AddScript(script);
            ps.Invoke();
            ps.AddCommand("createvmtwo").AddParameters(
               new Dictionary<string, string>(){
                  {"vname", vmname},
                  {"vmtype",vmtype},
                  {"hostname",hostname},
                  {"memory", memory},
                  {"cpunum", cpunum},
                  {"path", path}
                  //{"vhdsize",vhdsize}
               }
            );

            foreach (PSObject result in ps.Invoke())
            {
               Console.WriteLine(result);
               ret = result.ToString();
            }
         }
         return ret;
      }

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

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

      public static int Main()
      {
         //restore vmname
         string name = ReadLineAddress();
         string[] temp = name.Split('+');
         string hostname = temp[1];
         string vname = temp[0];
         if (String.IsNullOrEmpty(hostname) || String.IsNullOrEmpty(vname))
         {
            Console.WriteLine("虚拟机名或Host为空\n");
            return 0;
         }
         string key = "C:";
         string newkey = @"C:\test\C";
         string memory =getmemory(vname,hostname);
         string cpunum =getcpunum(vname,hostname);
         string vhdpath=getpath(vname,hostname);
         //Console.WriteLine("1 chu");
        // Console.WriteLine( vhdpath);
         vhdpath.Replace(key,newkey);
         //Console.WriteLine("2 chu");
        // Console.WriteLine(vhdpath);
         StringBuilder sb = new StringBuilder(vhdpath);
         sb.Replace("C:", @"C:\test\C");
         Console.WriteLine("2 chu");
          Console.WriteLine(sb);
          vhdpath = sb.ToString();
         string vmtype = getVMtype(vname,hostname);
         string netcf = getnet(vname,hostname);
         string cleannanme = "cleanname";
         // string vhdsize = getvhdsize(name, hostname); 暂时不需要

         //必须参数为,虚拟机代数,vhd模板path,内存 创建后不能更改,其他参数都可以手动更改
         //getnet 获取网络连接,为空则默认选host第一个网络连接
         if (netcf.Equals("null"))
         {
            Console.WriteLine("if null\n");
            Console.WriteLine(vname);
            Console.WriteLine(vmtype);
            Console.WriteLine(hostname);
            Console.WriteLine(memory);
            Console.WriteLine(cpunum);
            Console.WriteLine(vhdpath);
            creatvmtwo(vname, vmtype, hostname, memory, cpunum, vhdpath);
         }else{
            creatvm(vname, vmtype, hostname, memory, cpunum, netcf, vhdpath);
         }
         Cleanname(cleannanme);
         return 0;
      }
   }
}

 

代码比较简单  其中用到(二)中hyper-v.ps1脚本,其中恢复时需要hyperv虚拟机名和host名 默认在name.conf中  这个文件时fd端生成的, 具体就是读到dir、传来的hyperv名称和host名写入name.conf 文件,还原完后会自动清空;

还原时 先将vhd还原的C:/test/原路径;相当于再路径追加了一级/test/防止覆盖原有路径的vhdx导致原虚拟机启动失败,最新修改的。

还原完后的效果

后续待优化的内容:

1 获取所有hyperv虚拟机信息,目前只在少数hyperv虚拟机情况下,hyper-v.conf文件会比较小,如果虚拟机数目很大,则dir端获取显示所有虚拟机时,会有比较大的延迟,参考文章,可以存成csv格式文件,用c或c++l解析这个比较快;

2 获取信息只存了hyperv虚拟机名称,和host,而且是在其他表中追加的参数,后期可以考虑单独建表,专门存hyperv虚拟机信息,cpu个数,代数,内存,vhd路径等其他信息,这样还原的时候就不需要再get一遍;

 

github 账号https://github.com/HHHSong 后续代码会传到github上。

以上内容均属原创,转载请注明出处。

 


版权声明:本文为weixin_40747106原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。