Hyper-v虛擬機器備份與還原實現(三)
阿新 • • 發佈:2019-02-03
備份完還原就比較簡單了;
第一步 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上。
以上內容均屬原創,轉載請註明出處。