using DiskAccessLibrary; using DiskAccessLibrary.Mod; using ISCSI.Server; using System; using System.Collections.Generic; using System.Configuration; using System.Diagnostics; using System.Linq; using System.Xml; namespace ISCSIConsole.Mods { public class AutoLoadEntrySection : IConfigurationSectionHandler { public object Create(object parent, object configContext, XmlNode section) { var entries = new List(); foreach (XmlNode entryNode in section.ChildNodes) { Debug.Assert(entryNode.Attributes != null, "childNode.Attributes != null"); var entry = new AutoLoadEntry { Iqn = entryNode.Attributes[nameof(AutoLoadEntry.Iqn)].Value, Enable = entryNode.Attributes[nameof(AutoLoadEntry.Enable)].Value == "true", }; entry.Disks = new List(); foreach (XmlNode diskNode in entryNode.ChildNodes) { Debug.Assert(diskNode.Attributes != null, "diskNode.Attributes != null"); var disk = new AutoLoadDisk { Type = (AutoLoadDiskType)Enum.Parse(typeof(AutoLoadDiskType), diskNode.Attributes[nameof(AutoLoadDisk.Type)].Value), FilePath = diskNode.Attributes[nameof(AutoLoadDisk.FilePath)].Value, ReadOnly = "true" == diskNode.Attributes[nameof(AutoLoadDisk.ReadOnly)]?.Value, Enable = "true" == diskNode.Attributes[nameof(AutoLoadDisk.Enable)]?.Value }; entry.Disks.Add(disk); } entries.Add(entry); } return entries; } } internal class AutoLoadEntry { public bool Enable { get; set; } public string Iqn { get; set; } public List Disks { get; set; } public ISCSITarget CreateTarget() { var disks = new List(); var target = new ISCSITarget(Iqn, disks); foreach (var disk in Disks.Where(p=>p.Enable)) { disks.Add(disk.CreateDisk()); } return target; } } internal class AutoLoadDisk { public bool Enable { get; set; } public AutoLoadDiskType Type { get; set; } public string FilePath { get; set; } public bool ReadOnly { get; set; } public Disk CreateDisk() { switch (Type) { case AutoLoadDiskType.RamDiskFromFile: var bdd = new BlockDifferencingDiskImage(FilePath, true); try { bdd.OpenForRead(); if (false == bdd.IsNoBaseImage) throw new ConfigurationErrorsException("RamDiskFromFile: Only ** No Base Image Mode ** supported"); var ramDisk = new UnmanagedGigabyteBlockSeparatedRamDisk((int)Math.Ceiling(bdd.Size / (float)Consts.Gigabyte)); ramDisk.Allocate(); var buffer = new byte[bdd.BlockSize]; for (var i = 0; i < bdd.NumberOfBlocks; i++) { if (false == bdd.IsBlockAllocated[i]) continue; bdd.ReadBlock(buffer, 0, buffer.Length, i, 0); ramDisk.WriteData((long)i * bdd.BlockSize, buffer); } return ramDisk; } finally { bdd.CloseForRead(); } case AutoLoadDiskType.AttachFile: var diskImage = DiskImage.GetDiskImage(FilePath, ReadOnly); diskImage.ExclusiveLock(); return diskImage; default: throw new ArgumentOutOfRangeException($"Unknown type: {Type}"); } } } internal enum AutoLoadDiskType { RamDiskFromFile, AttachFile } }