Пример #1
0
        /// <summary>
        /// Gets the sysfs partitions.
        /// </summary>
        /// <returns>
        /// The sysfs partitions.
        /// </returns>
        /// <param name='diskPath'>
        /// Disk path. (eg /sys/devices/virtual/block/loop0)
        /// </param>
        /// <param name='diskName'>
        /// Disk name. (eg loop0)
        /// </param>
        internal List <Partition> GetSysfsPartitions(string diskPath, string diskName)
        {
            List <Partition> parts = new List <Partition>();

            Mono.Unix.UnixDirectoryInfo diskDir = new Mono.Unix.UnixDirectoryInfo(diskPath);
            foreach (Mono.Unix.Native.Dirent part in diskDir.GetEntries(diskName + ".*"))
            {
                Partition p = new Partition();
                p.Path   = "/dev/" + part.d_name;
                p.Offset = ulong.Parse(File.ReadAllText(diskPath + "/" + part.d_name + "/start"));
                p.Size   = long.Parse(File.ReadAllText(diskPath + "/" + part.d_name + "/size"));
                parts.Add(p);
            }
            return(parts);
        }
Пример #2
0
 /// <summary>
 /// returns the partition name (sdX format) from any by-xxxx value (by-path, by-uuid...)
 /// </summary>
 /// <param name='partitionName'>
 /// Partition name.
 /// </param>/
 private string GetPartitionFromPathOrUuid(string partitionName)
 {
     string[] disksBy = new string[] { "by-uuid", "by-path", "by-label", "by-id" };
     foreach (string byType in disksBy)
     {
         Mono.Unix.UnixDirectoryInfo byUuidParts = new Mono.Unix.UnixDirectoryInfo("/dev/disk/" + byType);
         foreach (Mono.Unix.Native.Dirent d in byUuidParts.GetEntries())
         {
             //Console.WriteLine ("______GetPartitionFromPathOrUuid looking cur entry="+d.d_name+", type="+d.d_type);
             if (d.d_type == 10 /*Mono.Unix.FileTypes.SymbolicLink*/)
             {
                 string partOnlyName = "";
                 if (partitionName.LastIndexOf("/") >= 0)
                 {
                     partOnlyName = partitionName.Substring(partitionName.LastIndexOf("/") + 1);
                 }
                 else if (partitionName.IndexOf("UUID=") == 0)
                 {
                     partOnlyName = partitionName.Replace("UUID=", "");
                 }
                 else
                 {
                     partOnlyName = partitionName;
                 }
                 //Console.WriteLine ("______GetPartitionFromPathOrUuid :d_name="+d.d_name+", partonlyname="+partOnlyName);
                 if (d.d_name == partOnlyName)
                 {
                     Mono.Unix.UnixSymbolicLinkInfo devLink = new Mono.Unix.UnixSymbolicLinkInfo(byUuidParts + "/" + d.d_name);
                     //Console.WriteLine ("______GetPartitionFromPathOrUuid : "+partitionName+" --> /dev/"+devLink.ContentsPath.Substring(devLink.ContentsPath.LastIndexOf('/')+1));
                     return("/dev/" + devLink.ContentsPath.Substring(devLink.ContentsPath.LastIndexOf('/') + 1));
                 }
             }
         }
     }
     // partition was probably referenced by its devics (/dev/sdXX) path, nothing to do
     return(partitionName);
 }
Пример #3
0
        /// <summary>
        /// Snapshots the VM and gets its (maybe partial) StorageLayout
        /// </summary>
        /// <returns>
        /// The physical disks.
        /// </returns> retrieve a
        public StorageLayout BuildStorageLayout()
        {
            List <FileSystem> fsList = new List <FileSystem>();

            if (this.loopDevices == null)            // local layout
            {
                fsList = GetMountedFilesystems();
            }

            /*else
             *      fsList = MountLoopFilesystems();*/

            Mono.Unix.UnixDirectoryInfo ud = new Mono.Unix.UnixDirectoryInfo(sysfsRoot);

            foreach (Mono.Unix.Native.Dirent scsiDevice in ud.GetEntries())
            {
                if (this.IsLayoutLoop && !loopDevices.Contains(scsiDevice.d_name))
                {
                    continue;
                }

                Console.WriteLine("device subsystem name : " + scsiDevice.d_name);
                Disk   disk = new Disk();
                string path = "";
                if (this.IsLayoutLoop)
                {
                    path = sysfsRoot + "/" + scsiDevice;
                }
                else
                {
                    path = sysfsRoot + "/" + scsiDevice + "/device/block";
                }

                if (!Directory.Exists(path))
                {
                    disk.Enabled = false;
                }
                else
                {
                    disk.Enabled = true;
                }
                string diskName = "";
                if (this.IsLayoutLoop)
                {
                    diskName = scsiDevice.d_name;
                }
                else
                {
                    Mono.Unix.UnixDirectoryInfo scsiPath = new Mono.Unix.UnixDirectoryInfo(path);
                    diskName = scsiPath.GetEntries()[0].d_name;
                    path    += "/" + diskName;
                }
                disk.Path = "/dev/" + diskName;
                disk.Size = long.Parse(File.ReadAllText(path + "/size"));
                //disk.Enabled =  File.ReadAllText(path+"/removable").StartsWith("0");
                if (!File.ReadAllText(path + "/removable").StartsWith("0"))              // exclude removable devices (external drives, usb keys...)
                {
                    continue;
                }
                disk.Enabled    = true;
                disk.SectorSize = uint.Parse(File.ReadAllText(path + "/queue/hw_sector_size"));
                if (this.IsLayoutLoop)
                {
                    disk.Type = DiskType.Loop;
                }
                try{
                    disk.BlockStream = new FileStream(disk.Path, System.IO.FileMode.Open);
                }
                catch (Exception e) {
                    Console.WriteLine("ERROR : " + e.Message);
                }
                //MBR mbr = new MBR(disk.MbrBytes);

                // gather what MBR sees
                //disk.Children.AddRange(StorageLayoutManager.GetPartitionsFromMBR(disk));
                // now compare with what is inside sysfs and complete information
                List <Partition> sysfsParts = GetSysfsPartitions(path, diskName);

                foreach (Partition sysfsP in sysfsParts)
                {
                    //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions SYS current="+sysfsP.Offset+"  ("+sysfsP.Path+")");
                    //foreach(Partition p in disk.Children){
                    //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions MBR current="+p.Offset);
                    //if (p.Offset != sysfsP.Offset) continue;
                    //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions MATCHED MBR partition "+sysfsP.Path);
                    //p.Path = sysfsP.Path;
                    //p.Size = sysfsP.Size;

                    foreach (FileSystem f in fsList)
                    {
                        string fsDevName = GetPartitionFromPathOrUuid(f.Path);
                        //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions FS current="+f.Path+", mntpt="+f.MountPoint+", mapped="+fsDevName);
                        if (fsDevName == sysfsP.Path)
                        {
                            sysfsP.AddChild(f);
                            //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions FS MATCHED"+Environment.NewLine);
                        }
                    }
                    //break;
                    disk.AddChild(sysfsP);
                    //}
                }

                layout.Entries.Add(disk);
            }            // end foreach

            // if using loop devices, try to detect fses and mount only now that we have a complete view and access to disks and parts.
            // doing it so late allows to detect things like LVM volumes spread on multiple partitions or disks
            if (fsList.Count == 0)
            {
                //1- try to mount the loop partitions
                foreach (Partition p in layout.GetAllPartitions(null))
                {
                    // quick, hackish and dirty way to avoid mounting an 'extended' partition,
                    // which sould result in an endless loop while burning 100% cPU in zombie state. Yup. Kernel bug?
                    if (p.Size == 2)
                    {
                        continue;
                    }

                    FileSystem mountedFS = MountLoopFilesystem(p);
                    if (mountedFS != null)
                    {
                        p.AddChild(mountedFS);
                    }
                }
                // 2- try to access and read VM /etc/fstab, from there guess the original loop FS mountpoint
                Dictionary <string, string> originalMountpoints = TryGuessOriginalMountPoint(layout.GetAllFileSystems(null));
                foreach (FileSystem fs in layout.GetAllFileSystems(null))
                {
                    foreach (KeyValuePair <string, string> mp in originalMountpoints)
                    {
                        string fsBlockDevice = GetPartitionFromPathOrUuid(mp.Key);
                        //Console.WriteLine ("ORIGINAL LAYOUT FS: mountpoint key="+mp.Key+", value="+mp.Value+", fromuuid="+fsBlockDevice+", fs.path="+fs.Path+", fs.mountpoint="+fs.MountPoint);
                        if (fsBlockDevice == fs.Path)
                        {
                            fs.OriginalMountPoint = mp.Value;
                            if (LogEvent != null)
                            {
                                LogEvent(this, new LogEventArgs(0, Severity.DEBUG, "Filesystem at mountpoint '" + fs.MountPoint + "' was originally mounted as '" + fs.OriginalMountPoint + "'"));
                            }
                            break;;
                        }
                    }
                }
            }

            return(layout);
        }