Esempio n. 1
0
        /// <summary>
        /// Builds a "fake" layout containing 1 fake disk, having 1 fake partition,
        /// containing all the mounted available filesystems
        /// </summary>
        /// <returns>
        /// The storage layout.
        /// </returns>
        public StorageLayout BuildStorageLayout()
        {
            var layout = new StorageLayout();
            var disk   = new Disk {
                Path = "?"
            };
            var partition = new Partition {
                Path = "?"
            };

            foreach (FileSystem fs in FilesystemManager.Instance().GetAllDrives())
            {
                partition.AddChild(fs);
            }
            disk.AddChild(partition);
            layout.Entries.Add(disk);
            return(layout);
        }
        public void Test()
        {
            var c = new Partition(@"C");

            c.AddChild(new Directory(@"Program Files"));
            c.AddChild(new Directory(@"Program Files (x86)"));
            var users     = new Directory(@"Users");
            var johnSmith = new Directory("John Smith");
            var downloads = new Directory("Downloads");
            var email     = new ArchiveFile("email.zip", 84);
            var pictures  = new Directory("pictures");

            pictures.AddChild(new File("1.jpg", 28));
            pictures.AddChild(new File("2.jpg", 32));
            email.AddChild(pictures);
            email.AddChild(new File("report.docx", 52));
            downloads.AddChild(email);
            johnSmith.AddChild(downloads);
            users.AddChild(johnSmith);
            c.AddChild(users);
            var windows = new Directory(@"Windows");

            windows.AddChild(new Directory("System"));
            var system32 = new Directory("System32");

            system32.AddChild(new File("accessor.dll", 708));
            system32.AddChild(new File("accessibilitycpl.dll", 3725));
            system32.AddChild(new File("ActionCenter.dll", 874));
            windows.AddChild(system32);
            windows.AddChild(new File("explorer.exe", 2443));
            windows.AddChild(new File("regedit.exe", 151));
            c.AddChild(windows);

            CollectionAssert.AreEqual(new List <string>
            {
                @"C:\",
                @"| Program Files",
                @"| Program Files (x86)",
                @"| Users",
                @"| | John Smith",
                @"| | | Downloads",
                @"| | | | email.zip 84 KB",
                @"| | | | | pictures",
                @"| | | | | | 1.jpg 28 KB",
                @"| | | | | | 2.jpg 32 KB",
                @"| | | | | report.docx 52 KB",
                @"| Windows",
                @"| | System",
                @"| | System32",
                @"| | | accessor.dll 708 KB",
                @"| | | accessibilitycpl.dll 3725 KB",
                @"| | | ActionCenter.dll 874 KB",
                @"| | explorer.exe 2443 KB",
                @"| | regedit.exe 151 KB"
            }, c.Render());

            windows.RemoveChild(system32);

            CollectionAssert.AreEqual(new List <string>
            {
                @"C:\",
                @"| Program Files",
                @"| Program Files (x86)",
                @"| Users",
                @"| | John Smith",
                @"| | | Downloads",
                @"| | | | email.zip 84 KB",
                @"| | | | | pictures",
                @"| | | | | | 1.jpg 28 KB",
                @"| | | | | | 2.jpg 32 KB",
                @"| | | | | report.docx 52 KB",
                @"| Windows",
                @"| | System",
                @"| | explorer.exe 2443 KB",
                @"| | regedit.exe 151 KB"
            }, c.Render());
        }
Esempio n. 3
0
        /// <summary>
        /// Snapshots the VM and gets its (maybe partial) StorageLayout
        /// </summary>
        /// <returns>
        /// The physical disks.
        /// </returns> retrieve a
        public StorageLayout BuildStorageLayout()
        {
            StorageLayout sl = new StorageLayout();

            // http://jo0ls-dotnet-stuff.blogspot.fr/2008/12/howto-get-physical-drive-string.html

            foreach (DriveInfo di in DriveInfo.GetDrives())
            {
                if (di.DriveType != DriveType.Fixed /*&& di.DriveType != DriveType.Network*/)
                {
                    continue;
                }
                string devicePath = @"\\.\" + di.RootDirectory.ToString().TrimEnd(new char[] { '\\' });
                Console.WriteLine("Mounted dev path=" + devicePath);


                IntPtr handle = Win32Api.CreateFile(devicePath, Win32Api.GENERIC_READ | Win32Api.GENERIC_WRITE,
                                                    Win32Api.FILE_SHARE_READ | Win32Api.FILE_SHARE_WRITE, IntPtr.Zero,
                                                    Win32Api.OPEN_EXISTING, 0 /*Win32Api.FILE_FLAG_BACKUP_SEMANTICS | (uint)Alphaleonis.Win32.Filesystem.FileSystemRights.SystemSecurity*/, IntPtr.Zero);
                openHandles.Add(handle);

                // Then query underlying partition(s)
                Win32Api.DiskExtents extents = new Win32Api.DiskExtents();

                int  size = 0;
                bool ok   = Win32Api.DeviceIoControl(handle, (uint)Win32Api.Ioctls.GetVolumeDiskExtents, IntPtr.Zero,
                                                     0, ref extents, Marshal.SizeOf(extents), out size, IntPtr.Zero);
                //Console.WriteLine ("DeviceIoControl : "+(new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())).Message);
                if (!ok)
                {
                    Console.WriteLine("DeviceIoControl failed : " + (new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())).Message);
                    int    blobSize = Marshal.SizeOf(typeof(Win32Api.DiskExtents)) + (extents.numberOfExtents - 1) * Marshal.SizeOf(typeof(Win32Api.DiskExtent));
                    IntPtr pBlob    = Marshal.AllocHGlobal(blobSize);
                    uint   dataSize = 0;
                    ok = Win32Api.DeviceIoControl(handle, (uint)Win32Api.Ioctls.GetVolumeDiskExtents, IntPtr.Zero, 0, pBlob, blobSize, out dataSize, IntPtr.Zero);
                    if (ok)
                    {
                        IntPtr pNext = new IntPtr(pBlob.ToInt32() + IntPtr.Size /*4*/);                        // is this always ok on 64 bit OSes? ToInt64?
                        for (int i = 0; i < extents.numberOfExtents; i++)
                        {
                            // DiskExtent diskExtentN = DirectCast(Marshal.PtrToStructure(pNext, GetType(DiskExtent)), DiskExtent)
                            Win32Api.DiskExtent diskExtentN = (Win32Api.DiskExtent)Marshal.PtrToStructure(pNext, typeof(Win32Api.DiskExtent));
                            // physicalDrives.Add("\\.\PhysicalDrive" & diskExtentN.DiskNumber.ToString)
                            Console.WriteLine("found multiple backing part disk=: " + diskExtentN.DiskNumber + ", offset=" + diskExtentN.StartingOffset + ", length=" + diskExtentN.ExtentLength);

                            pNext = new IntPtr(pNext.ToInt32() + Marshal.SizeOf(typeof(Win32Api.DiskExtent)));
                        }
                    }
                    else
                    {
                        Console.WriteLine("DeviceIoControl for multiple backing extents failed : " + (new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())).Message);
                    }
                }
                else
                {
                    Console.WriteLine("found part disk=: " + extents.first.DiskNumber + ", offset=" + extents.first.StartingOffset + ", length=" + extents.first.ExtentLength);
                }

                Disk disk = new Disk();
                disk.Path = @"\\.\PhysicalDrive" + extents.first.DiskNumber.ToString();              //+disk.Id;

                IntPtr physDiskHandle = Win32Api.CreateFile(disk.Path, Win32Api.GENERIC_READ | Win32Api.GENERIC_WRITE,
                                                            Win32Api.FILE_SHARE_READ | Win32Api.FILE_SHARE_WRITE, IntPtr.Zero,
                                                            Win32Api.OPEN_EXISTING, 0 /*Win32Api.FILE_FLAG_BACKUP_SEMANTICS | (uint)Alphaleonis.Win32.Filesystem.FileSystemRights.SystemSecurity*/, IntPtr.Zero);
                //Console.WriteLine ("CreateFile : "+(new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())).Message);
                openHandles.Add(physDiskHandle);
                disk.BlockStream = new FileStream(physDiskHandle, FileAccess.Read);
                disk.Id          = (string)extents.first.DiskNumber.ToString();

                // now get the disk geometry to obtain physical sector size
                Win32Api.DISK_GEOMETRY diskGeometry = new Win32Api.DISK_GEOMETRY();
                ok = Win32Api.DeviceIoControl(physDiskHandle, (uint)Win32Api.Ioctls.DiskGetDriveGeometry, IntPtr.Zero,
                                              0, ref diskGeometry, Marshal.SizeOf(diskGeometry), out size, IntPtr.Zero);

                Win32Api.MEDIA_SERIAL_NUMBER_DATA diskSerial = new Win32Api.MEDIA_SERIAL_NUMBER_DATA();
                ok = Win32Api.DeviceIoControl(physDiskHandle, (uint)Win32Api.Ioctls.GetMediaSerialNumber, IntPtr.Zero,
                                              0, ref diskSerial, Marshal.SizeOf(diskSerial), out size, IntPtr.Zero);
                Console.WriteLine("DeviceIoControl : " + (new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())).Message);

                disk.SectorSize = (uint)diskGeometry.BytesPerSector;
                if (diskSerial.SerialNumberData != null)
                {
                    disk.Id = System.Text.Encoding.Default.GetString(diskSerial.SerialNumberData);
                }

                disk.Size = diskGeometry.DiskSize;
                if (!sl.Entries.Contains(disk))
                {
                    sl.Entries.Add(disk);
                }

                Partition p = new Partition();
                p.Offset = (ulong)extents.first.StartingOffset / disk.SectorSize;
                p.Size   = extents.first.ExtentLength;

                FileSystem fs = new FileSystem();
                fs.Path               = devicePath;
                fs.DriveFormat        = fs.DriveFormat;
                fs.MountPoint         = di.RootDirectory.ToString();
                fs.OriginalMountPoint = di.RootDirectory.ToString();
                fs.AvailableFreeSpace = di.AvailableFreeSpace;
                fs.Size               = di.TotalSize;
                p.AddChild(fs);
                Console.WriteLine("created new FS, mnt=" + fs.MountPoint);
                foreach (IDiskElement de in sl.Entries)
                {
                    if (de is Disk && de.Id == disk.Id)
                    {
                        Console.WriteLine("adding new part to layout");
                        de.AddChild(p);
                    }
                }
            }


            return(sl);
        }
Esempio n. 4
0
        /// <summary>
        /// Snapshots the VM and gets its (maybe partial) StorageLayout
        /// </summary>
        /// <returns>
        /// The physical disks.
        /// </returns> retrieve a
        public StorageLayout BuildStorageLayout()
        {
            LogEvent(this, new LogEventArgs(700, Severity.INFO, "Connecting to hypervisor '" + proxyInfo.Hypervisor.Name + "' (" + proxyInfo.Hypervisor.Url + ")"));
            vmwh.Connect(proxyInfo.Hypervisor.Url, proxyInfo.Hypervisor.UserName, proxyInfo.Hypervisor.Password.Value);
            if (vmwh == null)
            {
                throw new Exception("IDiskDiscoverer '" + this.Name + "' hasn't been initialized");
            }

            List <Disk> vmDks = vmwh.GetDisks(proxyInfo.Node);

            if (vmDks.Count == 0)
            {
                return(null);
            }
            //if(vmDks.Count == 0) throw new Exception ("Storage discoverer '"+this.Name+"' didn't find any disk.");

            //Logger.Append(Severity.DEBUG, "Found "+vmDks.Count+" disks for Node #"+proxyInfo.Node.Id+" (VM "+proxyInfo.Node.InternalId+")");
            LogEvent(this, new LogEventArgs(0, Severity.DEBUG, "Found " + vmDks.Count + " disks for Node #" + proxyInfo.Node.Id + " (VM " + proxyInfo.Node.InternalId + ")"));

            // Now ask to snapshot
            snapName = vmwh.Snapshot(proxyInfo.Node, "test" /*"snap_test_"+DateTime.Now.ToString()*/);

            vddk.Connect(proxyInfo.Hypervisor.Url,
                         proxyInfo.Hypervisor.UserName,
                         proxyInfo.Hypervisor.Password.Value,
                         snapName,
                         vmwh.GetVmMMorefId(proxyInfo.Node),
                         "san:nbd:hotadd:nbdssl"            // make transport mode configurable
                         );

            StorageLayout sl        = new StorageLayout();
            List <string> diskNames = new List <string>();

            // open disk and read MBR
            foreach (Disk d in vmDks)
            {
                d.BlockStream = new VmdkStream(vddk.OpenPhysicalDisk(d.Path));

                //2013-05-29 - commented out to split vmware to separate disk discov plugin

                /*d.MbrBytes = new byte[512];
                 * d.BlockStream.Read(d.MbrBytes, 0, 512);
                 * MBR mbr = new MBR(d.MbrBytes);
                 * d.Signature = mbr.DiskSignature;*/


                diskNames.Add(d.Path);
                d.IsComplete = true;
                if (Environment.OSVersion.Platform == PlatformID.Unix)                // on Linux, get a loop Device mountpoint for the disk
                {
                    d.Type = DiskType.Loop;
                    try{
                        d.ProxiedPath = vddk.GetFuseHandle(d.Path);
                    }
                    catch (Exception e) {
                        LogEvent(this, new LogEventArgs(10, Severity.ERROR, "Could not attach disk '" + d.Path + "' to loopback device : " + e.ToString()));
                        //Logger.Append(Severity.ERROR, "Could not attach disk '"+d.Path+"' to loopback device : "+e.ToString());
                    }
                }
                sl.Entries.Add(d);
            }

            // At this point we have disk-->partitions rudimentary mapping, won't go further on a linux VM
            if (Environment.OSVersion.Platform == PlatformID.Unix)
            {
                return(sl);
            }

            //on windows, we can use vddk to mount them all Attribute once/
            // the read mounted registry hive to map partition <--->drive letter
            // we don't use vixmntapi mapping because it doesn't report partitions offset (thus making impossible to match
            // the disc raw MBR discovery with mounts)
            // Also, we can open all disks at one and benefit from the VDDK(s ability
            // to mount everything (NTFS-based) incuding Windows LDM volumes (spanned, raid...)
            List <FileSystem> disksFses = vddk.MountNTDrives(diskNames);
            List <Tuple <string, uint, ulong> > registryDrives = new List <Tuple <string, uint, ulong> >();

            foreach (FileSystem mountedFS in disksFses)
            {
                using (NTSystemRegistry nsr = new NTSystemRegistry()){
                    nsr.LogEvent += LogReceivedEvent;
                    if (nsr.MountSystemHive(mountedFS.MountPoint, 0))
                    {
                        List <Tuple <string, uint, ulong> > drives = nsr.GetMountPoints();
                        if (drives != null && drives.Count > 0)
                        {
                            registryDrives.AddRange(drives);
                        }
                        LogEvent(this, new LogEventArgs(0, Severity.TRIVIA, "Currently have " + registryDrives.Count + " drives from registry"));
                    }
                }
            }
            if (registryDrives == null)
            {
                LogEvent(this, new LogEventArgs(899, Severity.ERROR, "Couldn't retrieve mount information from NT registry. Drives count: " + registryDrives.Count));
                return(sl);
            }

            foreach (FileSystem mountedFS in disksFses)
            {
                //Console.WriteLine (Environment.NewLine+"@@@  FS2 '"+mountedFS.ToString());

                // does not have registry, or not a "mountable" fs

                foreach (Tuple <string, uint, ulong> driveInfo in registryDrives)
                {
                    Console.WriteLine("@@@  TUPLE '" + driveInfo.Item1 + ", sig=" + driveInfo.Item2 + ", offset=" + driveInfo.Item3);
                    if (mountedFS.OriginalMountPoint == null ||
                        (driveInfo.Item1.ToLower() != mountedFS.OriginalMountPoint.ToLower())
                        )
                    {
                        continue;
                    }
                    bool foundFsDisk = false;
                    foreach (Disk d in sl.Entries)
                    {
                        Console.WriteLine("@@@  DISK '" + d.ToString());
                        if (d.Signature != driveInfo.Item2)
                        {
                            continue;
                        }
                        // add new partition having the offset discovered by registry tuple
                        Console.WriteLine("@@@  PART  " + driveInfo.Item3);
                        Partition partialPart = new Partition();
                        partialPart.Offset = driveInfo.Item3;

                        partialPart.AddChild(mountedFS);
                        d.AddChild(partialPart);

                        Console.WriteLine("@@@     ADDED   new FS '" + mountedFS.MountPoint + "' to part " + partialPart.ToString());
                        foundFsDisk = true;
                    }                             // end foreach Disk

                    // If we couldn't find a matching disk & part for the FS, still add it to the layout root.
                    // This allows to backup FS items even if we know nothing about its backing device(s) layout.
                    // thus BMR won't be possible

                    /*if(!foundFsDisk)
                     *      sl.Entries.Add(mountedFS);*/
                }                         //end foreach registry drive

                //}// end using
            }

            return(sl);
        }