public void LsFixedBlockChangedBlock(string snapmoref, int diskid, string timestamp, long blocksizekb) { ManagedObjectReference snapmor = new ManagedObjectReference(); snapmor.type = "VirtualMachineSnapshot"; snapmor.Value = snapmoref; ManagedObjectReference vmref = null; try { vmref = cb.getServiceUtil().GetMoRefProp(snapmor, "vm"); } catch { Console.WriteLine("Could not find snapshot"); } if (vmref != null) { var res = vimservice.QueryChangedDiskAreas(vmref, snapmor, diskid, 0, timestamp); if (res != null) { CBTQChangeCalc c = LsFixedBlockCalc(res, blocksizekb, false); System.Console.WriteLine(String.Format("Disk Offset : {0}", c.offset)); System.Console.WriteLine(String.Format("Disk Length : {0}", c.length)); System.Console.WriteLine("###########################"); if (c.cbtreal.Count > 0) { foreach (CBTQChangedBlock block in c.cbtreal) { System.Console.WriteLine("Start {0,-20} Length {1,-20} Flagged Fixed Blocks {2,-5}", block.offset, block.length, block.fiximpact); } System.Console.WriteLine("###########################"); System.Console.WriteLine(String.Format("Total Bytes CBT Flagged \t: {0}", c.cbtrealtotal)); System.Console.WriteLine(String.Format("Total Bytes CBT Flagged (MB)\t: {0}", c.cbtrealtotalmb)); System.Console.WriteLine("###########################"); foreach (CBTQChangedBlock block in c.cbtfix) { System.Console.WriteLine("Fix Blocks Start {0,-20} Length {1,-20} Fixed Blocks {2,-5}", block.offset, block.length, block.fiximpact); } System.Console.WriteLine("###########################"); System.Console.WriteLine(String.Format("Total Fixed CBT Flagged \t: {0}", c.cbtfixchangedblocks)); System.Console.WriteLine(String.Format("Total Fixed Bytes CBT Flagged \t: {0}", c.cbtfixtotal)); System.Console.WriteLine(String.Format("Total Fixed Bytes CBT Flagged (MB)\t: {0}", c.cbtfixtotalmb)); } else { System.Console.WriteLine("Could not find changed blocks"); } } } }
public void DiskMonPrint(CBTQChangeCalc c, string vmmoref, int display) { System.Console.WriteLine(String.Format("Disk Offset : {0,30} Length : {1,30}", c.offset, c.length)); if (c.cbtreal.Count > 0) { if (display == 1) { foreach (CBTQChangedBlock block in c.cbtreal) { System.Console.WriteLine("Start {0,-20} Length {1,-20} Flagged Fixed Blocks {2,-5}", block.offset, block.length, block.fiximpact); } System.Console.WriteLine(""); foreach (CBTQChangedBlock block in c.cbtfix) { System.Console.WriteLine("Fix Blocks Start {0,-20} Length {1,-20} Fixed Blocks {2,-5}", block.offset, block.length, block.fiximpact); } System.Console.WriteLine(""); } else if (display == 2) { MakePNG(c, vmmoref); } System.Console.WriteLine(String.Format( "{0,14} | {1,10} | {2,10} | {3,14} | {4,10}", "Bytes CBT", "MBytes CBT", "Blocks Fix", "Bytes Fix", "MBytes Fix" )); System.Console.WriteLine(String.Format( "{0,14} | {1,10} | {2,10} | {3,14} | {4,10}", c.cbtrealtotal, c.cbtrealtotalmb, c.cbtfixchangedblocks, c.cbtfixtotal, c.cbtfixtotalmb )); System.Console.WriteLine(""); } else { System.Console.WriteLine("Could not find changed blocks"); if (display == 2) { MakePNG(c, vmmoref); } } }
public void MakePNG(CBTQChangeCalc c, string vmmoref) { //mod here int widthblock = 5; int heightblock = 5; int spacer = 1; int blocksonrow = 128; int offsetx = 10; int offsety = 10; DateTime d = DateTime.UtcNow; String fixname = String.Format("fix-{0,4:D4}{1,2:D2}{2,2:D2}t{3,2:D2}{4,2:D2}{5,2:D2}z-{6}-{7}.png", d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, c.blocksize, vmmoref); DrawPNG(c.blocksize, c.length, c.cbtfixbitmap, c.cbtfixchangedblocks, fixname, widthblock, heightblock, spacer, blocksonrow, offsetx, offsety, true); if (c.cbtrealbitmap != null) { String cbtname = String.Format("cbt-{0,4:D4}{1,2:D2}{2,2:D2}t{3,2:D2}{4,2:D2}{5,2:D2}z-{6}-{7}.png", d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, c.cbtrealminblock, vmmoref); DrawPNG(c.cbtrealminblock, c.length, c.cbtrealbitmap, c.cbtrealchangedblocks, cbtname, widthblock, heightblock, spacer, blocksonrow, offsetx, offsety, true); } }
public void DiskMonExtended(string vmmoref, int diskid, long blocksizekb, int display) { var vr = GetVm(vmmoref); if (vr != null) { ManagedObjectReference csnap = null; DateTime cdate = new DateTime(0); String changeId = null; bool allok = true; while (allok) { var snapinfo = (VirtualMachineSnapshotInfo)cb.getServiceUtil().GetDynamicProperty(vr.Mor, "snapshot"); if (snapinfo != null) { ManagedObjectReference querycsnap = snapinfo.currentSnapshot; if (querycsnap != null) { VirtualMachineSnapshotTree info = FindSnapInfo(snapinfo.rootSnapshotList, querycsnap.Value);; if (info != null) { if (csnap != null) { if (!csnap.Value.Equals(querycsnap.Value) && info.createTime > cdate) { System.Console.WriteLine("New snapshot '" + info.name + "' detected, calculating diff"); Dictionary <long, CBTQListedDisk> disks = LsDiskExecute(querycsnap.Value); if (disks.ContainsKey(diskid)) { csnap = querycsnap; cdate = info.createTime; System.Console.WriteLine("New CBT Changeid " + disks[diskid].cbtTimestamp); var res = vimservice.QueryChangedDiskAreas(vr.Mor, csnap, diskid, 0, changeId); if (res != null) { CBTQChangeCalc c = LsFixedBlockCalc(res, blocksizekb, (display == 2)); DiskMonPrint(c, vmmoref, display); } changeId = disks[diskid].cbtTimestamp; } else { allok = false; System.Console.WriteLine("VM does not contain disk id, halting"); } } } else { System.Console.WriteLine("Detected First Reference Snap '" + info.name + "'"); Dictionary <long, CBTQListedDisk> disks = LsDiskExecute(querycsnap.Value); if (disks.ContainsKey(diskid)) { csnap = querycsnap; cdate = info.createTime; changeId = disks[diskid].cbtTimestamp; System.Console.WriteLine("CBT Changeid " + changeId); var res = vimservice.QueryChangedDiskAreas(vr.Mor, csnap, diskid, 0, "*"); if (res != null) { CBTQChangeCalc c = LsFixedBlockCalc(res, blocksizekb, (display == 2)); DiskMonPrint(c, vmmoref, display); } } else { allok = false; System.Console.WriteLine("VM does not contain disk id, halting"); } } if (info.name.Equals("stopdiskmon")) { System.Console.WriteLine("Detected 'stopdiskmon' snapshot"); allok = false; } } } } System.Threading.Thread.Sleep(500); } } else { System.Console.WriteLine("Could not find VM"); } }
public CBTQChangeCalc LsFixedBlockCalc(DiskChangeInfo res, long blocksizekb, bool makecbtbitmap) { CBTQChangeCalc calcinfo = null; if (res != null) { calcinfo = new CBTQChangeCalc(); long blocksize = blocksizekb * 1024; bool[] cbtfixbitmap = null; if (blocksize > 0) { //+1 for misalignment on the block level, normally does not happen but just in case cbtfixbitmap = new bool[(res.length / blocksize) + 1]; for (var i = 0; i < cbtfixbitmap.Length; i++) { cbtfixbitmap[i] = false; } } bool[] cbtbitmap = null; long cbtblocksizemin = 1099511627776; calcinfo.offset = res.startOffset; calcinfo.length = res.length; calcinfo.blocksize = blocksize; //when flagging, instead of jumper per block, we will jump per maxjumpblockopt except at the end //this should significantely speed up calculation of the bitmap //to big is also not good because at the end more subjump will have to occure long maxjumpblockopt = blocksize / 4; long endmaxjumpblockopt = 1024; if (res.changedArea != null && res.changedArea.Length > 0) { long changedarea = 0; for (var i = 0; i < res.changedArea.Length; i++) { if (res.changedArea[i].length < cbtblocksizemin) { cbtblocksizemin = res.changedArea[i].length; } } //make sure that jumps are smaller than the blocksize and the variable block size in CBT long oneforthblock = cbtblocksizemin / 4; if (oneforthblock < maxjumpblockopt) { maxjumpblockopt = oneforthblock; } System.Console.WriteLine("Jump size used: " + maxjumpblockopt); if (makecbtbitmap) { if (cbtblocksizemin != 1099511627776 && cbtblocksizemin > 0) { cbtbitmap = new bool[(res.length / cbtblocksizemin) + 1]; for (var i = 0; i < cbtbitmap.Length; i++) { cbtbitmap[i] = false; } } else { makecbtbitmap = false; System.Console.WriteLine("Unusual block size, should not happen"); } } for (var i = 0; i < res.changedArea.Length; i++) { var changedblock = res.changedArea[i]; var start = changedblock.start; var length = changedblock.length; if (blocksize > 0) { long end = (start + length); long flagged = 0; long cbtflagged = 0; //System.Console.WriteLine(fixstart); //System.Console.WriteLine(fixend); long prevtblock = -1; long prevcbttblock = -1; for (long m = start; m < end;) { long touchingblock = m / blocksize; if (touchingblock >= 0 && touchingblock < cbtfixbitmap.Length && touchingblock != prevtblock) { cbtfixbitmap[touchingblock] = true; flagged++; prevtblock = touchingblock; } if (makecbtbitmap) { long cbttblock = m / cbtblocksizemin; if (cbttblock >= 0 && cbttblock < cbtbitmap.Length && cbttblock != prevcbttblock) { cbtbitmap[cbttblock] = true; cbtflagged++; prevcbttblock = cbttblock; } } //big continious region jumping //if at the end, make sure we jump per 1kb to match the size at that point //should give the most accurate prediction long newm = m + maxjumpblockopt; if (newm < end) { m = newm; } else { m += endmaxjumpblockopt; } } //System.Console.WriteLine("Start {0,-20} Length {1,-20} Flagged Fixed Blocks {2,-5}", changedblock.start, changedblock.length, flagged); calcinfo.cbtreal.Add(new CBTQChangedBlock(changedblock.start, changedblock.length, flagged)); } else { calcinfo.cbtreal.Add(new CBTQChangedBlock(changedblock.start, changedblock.length, 0)); } changedarea += changedblock.length; } calcinfo.cbtrealtotal = changedarea; calcinfo.cbtrealtotalmb = Math.Round((((double)changedarea) / 1024 / 1024), 2); if (makecbtbitmap) { calcinfo.cbtrealminblock = cbtblocksizemin; calcinfo.cbtrealbitmap = cbtbitmap; long cbtrealflagged = 0; for (var i = 0; i < cbtbitmap.Length; i++) { if (cbtbitmap[i]) { cbtrealflagged++; } } calcinfo.cbtrealchangedblocks = cbtrealflagged; } if (blocksize > 0) { long fixedflagged = 0; for (var i = 0; i < cbtfixbitmap.Length; i++) { if (cbtfixbitmap[i]) { long begin = i * blocksize; for (; i < cbtfixbitmap.Length && cbtfixbitmap[i]; i++) { fixedflagged += 1; } ; long end = i * blocksize; calcinfo.cbtfix.Add(new CBTQChangedBlock(begin, (end - begin), (end - begin) / blocksize)); } } long fixedflaggedb = fixedflagged * blocksize; calcinfo.cbtfixtotal = fixedflaggedb; calcinfo.cbtfixtotalmb = Math.Round((((double)fixedflaggedb) / 1024 / 1024), 2); calcinfo.cbtfixchangedblocks = fixedflagged; calcinfo.cbtfixbitmap = cbtfixbitmap; } } else { calcinfo.cbtfixchangedblocks = 0; calcinfo.cbtfixtotal = 0; calcinfo.cbtfixtotalmb = 0; calcinfo.cbtfixbitmap = cbtfixbitmap; if (makecbtbitmap) { calcinfo.cbtrealminblock = 64 * 1024; calcinfo.cbtrealbitmap = new bool[res.length / calcinfo.cbtrealminblock]; for (var i = 0; i < calcinfo.cbtrealbitmap.Length; i++) { calcinfo.cbtrealbitmap[i] = false; } calcinfo.cbtrealtotal = 0; calcinfo.cbtrealtotalmb = 0; calcinfo.cbtrealchangedblocks = 0; } } } return(calcinfo); }