1. 程式人生 > >Hyper-v虛擬機器備份與還原實現(三)

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上。

以上內容均屬原創,轉載請註明出處。