Kaynağa Gözat

commit: add auto load/start from config

HOME 5 yıl önce
ebeveyn
işleme
61e8653d4a

+ 3 - 0
ISCSIConsole/ISCSIConsole.csproj

@@ -39,8 +39,10 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.Configuration" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Compile Include="AddTargetForm.cs">
     <Compile Include="AddTargetForm.cs">
@@ -72,6 +74,7 @@
     <Compile Include="MainForm.Designer.cs">
     <Compile Include="MainForm.Designer.cs">
       <DependentUpon>MainForm.cs</DependentUpon>
       <DependentUpon>MainForm.cs</DependentUpon>
     </Compile>
     </Compile>
+    <Compile Include="Mods\AutoLoadEntry.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Program.Log.cs" />
     <Compile Include="Program.Log.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

+ 26 - 16
ISCSIConsole/MainForm.Designer.cs

@@ -40,7 +40,7 @@ namespace ISCSIConsole
             this.listTargets = new System.Windows.Forms.ListBox();
             this.listTargets = new System.Windows.Forms.ListBox();
             this.statusStrip1 = new System.Windows.Forms.StatusStrip();
             this.statusStrip1 = new System.Windows.Forms.StatusStrip();
             this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel();
             this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel();
-            this.statusStrip1.SuspendLayout();
+            this.LoadConfigButton = new System.Windows.Forms.Button();
             this.SuspendLayout();
             this.SuspendLayout();
             // 
             // 
             // btnStart
             // btnStart
@@ -58,7 +58,7 @@ namespace ISCSIConsole
             this.lblPort.AutoSize = true;
             this.lblPort.AutoSize = true;
             this.lblPort.Location = new System.Drawing.Point(232, 17);
             this.lblPort.Location = new System.Drawing.Point(232, 17);
             this.lblPort.Name = "lblPort";
             this.lblPort.Name = "lblPort";
-            this.lblPort.Size = new System.Drawing.Size(53, 13);
+            this.lblPort.Size = new System.Drawing.Size(59, 12);
             this.lblPort.TabIndex = 1;
             this.lblPort.TabIndex = 1;
             this.lblPort.Text = "TCP Port:";
             this.lblPort.Text = "TCP Port:";
             // 
             // 
@@ -66,7 +66,7 @@ namespace ISCSIConsole
             // 
             // 
             this.txtPort.Location = new System.Drawing.Point(291, 14);
             this.txtPort.Location = new System.Drawing.Point(291, 14);
             this.txtPort.Name = "txtPort";
             this.txtPort.Name = "txtPort";
-            this.txtPort.Size = new System.Drawing.Size(53, 20);
+            this.txtPort.Size = new System.Drawing.Size(53, 21);
             this.txtPort.TabIndex = 2;
             this.txtPort.TabIndex = 2;
             this.txtPort.Text = "3260";
             this.txtPort.Text = "3260";
             // 
             // 
@@ -75,7 +75,7 @@ namespace ISCSIConsole
             this.lblIPAddress.AutoSize = true;
             this.lblIPAddress.AutoSize = true;
             this.lblIPAddress.Location = new System.Drawing.Point(12, 16);
             this.lblIPAddress.Location = new System.Drawing.Point(12, 16);
             this.lblIPAddress.Name = "lblIPAddress";
             this.lblIPAddress.Name = "lblIPAddress";
-            this.lblIPAddress.Size = new System.Drawing.Size(61, 13);
+            this.lblIPAddress.Size = new System.Drawing.Size(71, 12);
             this.lblIPAddress.TabIndex = 3;
             this.lblIPAddress.TabIndex = 3;
             this.lblIPAddress.Text = "IP Address:";
             this.lblIPAddress.Text = "IP Address:";
             // 
             // 
@@ -85,7 +85,7 @@ namespace ISCSIConsole
             this.comboIPAddress.FormattingEnabled = true;
             this.comboIPAddress.FormattingEnabled = true;
             this.comboIPAddress.Location = new System.Drawing.Point(79, 13);
             this.comboIPAddress.Location = new System.Drawing.Point(79, 13);
             this.comboIPAddress.Name = "comboIPAddress";
             this.comboIPAddress.Name = "comboIPAddress";
-            this.comboIPAddress.Size = new System.Drawing.Size(136, 21);
+            this.comboIPAddress.Size = new System.Drawing.Size(136, 20);
             this.comboIPAddress.TabIndex = 4;
             this.comboIPAddress.TabIndex = 4;
             // 
             // 
             // btnAddTarget
             // btnAddTarget
@@ -103,7 +103,7 @@ namespace ISCSIConsole
             this.lblTargets.AutoSize = true;
             this.lblTargets.AutoSize = true;
             this.lblTargets.Location = new System.Drawing.Point(12, 57);
             this.lblTargets.Location = new System.Drawing.Point(12, 57);
             this.lblTargets.Name = "lblTargets";
             this.lblTargets.Name = "lblTargets";
-            this.lblTargets.Size = new System.Drawing.Size(46, 13);
+            this.lblTargets.Size = new System.Drawing.Size(53, 12);
             this.lblTargets.TabIndex = 7;
             this.lblTargets.TabIndex = 7;
             this.lblTargets.Text = "Targets:";
             this.lblTargets.Text = "Targets:";
             // 
             // 
@@ -121,35 +121,45 @@ namespace ISCSIConsole
             // listTargets
             // listTargets
             // 
             // 
             this.listTargets.FormattingEnabled = true;
             this.listTargets.FormattingEnabled = true;
+            this.listTargets.ItemHeight = 12;
             this.listTargets.Location = new System.Drawing.Point(79, 57);
             this.listTargets.Location = new System.Drawing.Point(79, 57);
             this.listTargets.Name = "listTargets";
             this.listTargets.Name = "listTargets";
-            this.listTargets.Size = new System.Drawing.Size(265, 95);
+            this.listTargets.Size = new System.Drawing.Size(265, 88);
             this.listTargets.TabIndex = 9;
             this.listTargets.TabIndex = 9;
             this.listTargets.SelectedIndexChanged += new System.EventHandler(this.listTargets_SelectedIndexChanged);
             this.listTargets.SelectedIndexChanged += new System.EventHandler(this.listTargets_SelectedIndexChanged);
             // 
             // 
             // statusStrip1
             // statusStrip1
             // 
             // 
-            this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.lblStatus});
-            this.statusStrip1.Location = new System.Drawing.Point(0, 173);
+            this.statusStrip1.Location = new System.Drawing.Point(0, 159);
             this.statusStrip1.Name = "statusStrip1";
             this.statusStrip1.Name = "statusStrip1";
-            this.statusStrip1.Size = new System.Drawing.Size(474, 22);
+            this.statusStrip1.Size = new System.Drawing.Size(464, 22);
             this.statusStrip1.SizingGrip = false;
             this.statusStrip1.SizingGrip = false;
             this.statusStrip1.TabIndex = 10;
             this.statusStrip1.TabIndex = 10;
             this.statusStrip1.Text = "statusStrip1";
             this.statusStrip1.Text = "statusStrip1";
             // 
             // 
-            // lblActiveSessions
+            // lblStatus
             // 
             // 
-            this.lblStatus.Name = "lblActiveSessions";
+            this.lblStatus.Name = "lblStatus";
             this.lblStatus.Size = new System.Drawing.Size(0, 17);
             this.lblStatus.Size = new System.Drawing.Size(0, 17);
             // 
             // 
+            // LoadConfigButton
+            // 
+            this.LoadConfigButton.Location = new System.Drawing.Point(354, 122);
+            this.LoadConfigButton.Name = "LoadConfigButton";
+            this.LoadConfigButton.Size = new System.Drawing.Size(106, 23);
+            this.LoadConfigButton.TabIndex = 8;
+            this.LoadConfigButton.Text = "Load Config";
+            this.LoadConfigButton.UseVisualStyleBackColor = true;
+            this.LoadConfigButton.Click += new System.EventHandler(this.LoadConfigButton_Click);
+            // 
             // MainForm
             // MainForm
             // 
             // 
             this.AcceptButton = this.btnStart;
             this.AcceptButton = this.btnStart;
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
-            this.ClientSize = new System.Drawing.Size(474, 195);
+            this.ClientSize = new System.Drawing.Size(464, 181);
             this.Controls.Add(this.statusStrip1);
             this.Controls.Add(this.statusStrip1);
             this.Controls.Add(this.listTargets);
             this.Controls.Add(this.listTargets);
+            this.Controls.Add(this.LoadConfigButton);
             this.Controls.Add(this.btnRemoveTarget);
             this.Controls.Add(this.btnRemoveTarget);
             this.Controls.Add(this.lblTargets);
             this.Controls.Add(this.lblTargets);
             this.Controls.Add(this.btnAddTarget);
             this.Controls.Add(this.btnAddTarget);
@@ -167,8 +177,7 @@ namespace ISCSIConsole
             this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
             this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
             this.Text = "iSCSI Console";
             this.Text = "iSCSI Console";
             this.Load += new System.EventHandler(this.MainForm_Load);
             this.Load += new System.EventHandler(this.MainForm_Load);
-            this.statusStrip1.ResumeLayout(false);
-            this.statusStrip1.PerformLayout();
+            this.Shown += new System.EventHandler(this.MainForm_Shown);
             this.ResumeLayout(false);
             this.ResumeLayout(false);
             this.PerformLayout();
             this.PerformLayout();
 
 
@@ -187,5 +196,6 @@ namespace ISCSIConsole
         private System.Windows.Forms.ListBox listTargets;
         private System.Windows.Forms.ListBox listTargets;
         private System.Windows.Forms.StatusStrip statusStrip1;
         private System.Windows.Forms.StatusStrip statusStrip1;
         private System.Windows.Forms.ToolStripStatusLabel lblStatus;
         private System.Windows.Forms.ToolStripStatusLabel lblStatus;
+        private System.Windows.Forms.Button LoadConfigButton;
     }
     }
 }
 }

+ 87 - 41
ISCSIConsole/MainForm.cs

@@ -1,20 +1,20 @@
 /* Copyright (C) 2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
 /* Copyright (C) 2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
- * 
+ *
  * You can redistribute this program and/or modify it under the terms of
  * You can redistribute this program and/or modify it under the terms of
  * the GNU Lesser Public License as published by the Free Software Foundation,
  * the GNU Lesser Public License as published by the Free Software Foundation,
  * either version 3 of the License, or (at your option) any later version.
  * either version 3 of the License, or (at your option) any later version.
  */
  */
+
+using ISCSI.Server;
+using ISCSIConsole.Mods;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.ComponentModel;
+using System.Configuration;
+using System.Linq;
 using System.Net;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
 using System.Net.Sockets;
-using System.Text;
-using System.Threading;
 using System.Windows.Forms;
 using System.Windows.Forms;
-using ISCSI.Server;
-using DiskAccessLibrary;
 using Utilities;
 using Utilities;
 
 
 namespace ISCSIConsole
 namespace ISCSIConsole
@@ -33,14 +33,14 @@ namespace ISCSIConsole
 
 
         private void MainForm_Load(object sender, EventArgs e)
         private void MainForm_Load(object sender, EventArgs e)
         {
         {
-            Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
-            this.Text += " v" + version.ToString(3);
+            var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
+            Text += " v" + version.ToString(3);
             m_server.OnLogEntry += Program.OnLogEntry;
             m_server.OnLogEntry += Program.OnLogEntry;
 
 
-            List<IPAddress> localIPs = GetHostIPAddresses();
-            KeyValuePairList<string, IPAddress> list = new KeyValuePairList<string, IPAddress>();
+            var localIPs = GetHostIPAddresses();
+            var list = new KeyValuePairList<string, IPAddress>();
             list.Add("Any", IPAddress.Any);
             list.Add("Any", IPAddress.Any);
-            foreach (IPAddress address in localIPs)
+            foreach (var address in localIPs)
             {
             {
                 list.Add(address.ToString(), address);
                 list.Add(address.ToString(), address);
             }
             }
@@ -60,14 +60,14 @@ namespace ISCSIConsole
         {
         {
             if (!m_started)
             if (!m_started)
             {
             {
-                IPAddress serverAddress = (IPAddress)comboIPAddress.SelectedValue;
-                int port = Conversion.ToInt32(txtPort.Text, 0);
+                var serverAddress = (IPAddress)comboIPAddress.SelectedValue;
+                var port = Conversion.ToInt32(txtPort.Text, 0);
                 if (port <= 0 || port > UInt16.MaxValue)
                 if (port <= 0 || port > UInt16.MaxValue)
                 {
                 {
                     MessageBox.Show("Invalid TCP port", "Error");
                     MessageBox.Show("Invalid TCP port", "Error");
                     return;
                     return;
                 }
                 }
-                IPEndPoint endpoint = new IPEndPoint(serverAddress, port);
+                var endpoint = new IPEndPoint(serverAddress, port);
                 try
                 try
                 {
                 {
                     m_server.Start(endpoint);
                     m_server.Start(endpoint);
@@ -96,41 +96,45 @@ namespace ISCSIConsole
 
 
         private void btnAddTarget_Click(object sender, EventArgs e)
         private void btnAddTarget_Click(object sender, EventArgs e)
         {
         {
-            AddTargetForm addTarget = new AddTargetForm();
-            DialogResult addTargetResult = addTarget.ShowDialog();
+            var addTarget = new AddTargetForm();
+            var addTargetResult = addTarget.ShowDialog();
             if (addTargetResult == DialogResult.OK)
             if (addTargetResult == DialogResult.OK)
             {
             {
-                ISCSITarget target = addTarget.Target;
-                ((SCSI.VirtualSCSITarget)target.SCSITarget).OnLogEntry += Program.OnLogEntry;
-                target.OnAuthorizationRequest += new EventHandler<AuthorizationRequestArgs>(ISCSITarget_OnAuthorizationRequest);
-                target.OnSessionTermination += new EventHandler<SessionTerminationArgs>(ISCSITarget_OnSessionTermination);
-                m_targets.Add(target);
+                var target = addTarget.Target;
                 try
                 try
                 {
                 {
-                    m_server.AddTarget(target);
+                    AddTarget(target);
                 }
                 }
-                catch (ArgumentException ex)
+                catch (Exception ex)
                 {
                 {
                     MessageBox.Show(ex.Message, "Error");
                     MessageBox.Show(ex.Message, "Error");
-                    return;
                 }
                 }
-                listTargets.Items.Add(target.TargetName);
             }
             }
         }
         }
 
 
+        private void AddTarget(ISCSITarget target)
+        {
+            ((SCSI.VirtualSCSITarget)target.SCSITarget).OnLogEntry += Program.OnLogEntry;
+            target.OnAuthorizationRequest += ISCSITarget_OnAuthorizationRequest;
+            target.OnSessionTermination += ISCSITarget_OnSessionTermination;
+            m_targets.Add(target);
+            m_server.AddTarget(target);
+            listTargets.Items.Add(target.TargetName);
+        }
+
         private void btnRemoveTarget_Click(object sender, EventArgs e)
         private void btnRemoveTarget_Click(object sender, EventArgs e)
         {
         {
             if (listTargets.SelectedIndices.Count > 0)
             if (listTargets.SelectedIndices.Count > 0)
             {
             {
-                int targetIndex = listTargets.SelectedIndices[0];
-                ISCSITarget target = m_targets[targetIndex];
-                bool isTargetRemoved = m_server.RemoveTarget(target.TargetName);
+                var targetIndex = listTargets.SelectedIndices[0];
+                var target = m_targets[targetIndex];
+                var isTargetRemoved = m_server.RemoveTarget(target.TargetName);
                 if (!isTargetRemoved)
                 if (!isTargetRemoved)
                 {
                 {
                     MessageBox.Show("Could not remove iSCSI target", "Error");
                     MessageBox.Show("Could not remove iSCSI target", "Error");
                     return;
                     return;
                 }
                 }
-                List<Disk> disks = ((SCSI.VirtualSCSITarget)target.SCSITarget).Disks;
+                var disks = ((SCSI.VirtualSCSITarget)target.SCSITarget).Disks;
                 LockUtils.ReleaseDisks(disks);
                 LockUtils.ReleaseDisks(disks);
                 m_targets.RemoveAt(targetIndex);
                 m_targets.RemoveAt(targetIndex);
                 listTargets.Items.RemoveAt(targetIndex);
                 listTargets.Items.RemoveAt(targetIndex);
@@ -139,23 +143,23 @@ namespace ISCSIConsole
 
 
         private void ISCSITarget_OnAuthorizationRequest(object sender, AuthorizationRequestArgs e)
         private void ISCSITarget_OnAuthorizationRequest(object sender, AuthorizationRequestArgs e)
         {
         {
-            string targetName = ((ISCSITarget)sender).TargetName;
+            var targetName = ((ISCSITarget)sender).TargetName;
             m_usageCounter.NotifySessionStart(targetName);
             m_usageCounter.NotifySessionStart(targetName);
             UpdateUI();
             UpdateUI();
         }
         }
 
 
         private void ISCSITarget_OnSessionTermination(object sender, SessionTerminationArgs e)
         private void ISCSITarget_OnSessionTermination(object sender, SessionTerminationArgs e)
         {
         {
-            string targetName = ((ISCSITarget)sender).TargetName;
+            var targetName = ((ISCSITarget)sender).TargetName;
             m_usageCounter.NotifySessionTermination(targetName);
             m_usageCounter.NotifySessionTermination(targetName);
             UpdateUI();
             UpdateUI();
         }
         }
 
 
         private void UpdateUI()
         private void UpdateUI()
         {
         {
-            if (this.InvokeRequired)
+            if (InvokeRequired)
             {
             {
-                this.Invoke((MethodInvoker)UpdateUI);
+                Invoke((MethodInvoker)UpdateUI);
             }
             }
             else
             else
             {
             {
@@ -166,9 +170,9 @@ namespace ISCSIConsole
 
 
                 if (listTargets.SelectedIndices.Count > 0)
                 if (listTargets.SelectedIndices.Count > 0)
                 {
                 {
-                    int targetIndex = listTargets.SelectedIndices[0];
-                    ISCSITarget target = m_targets[targetIndex];
-                    bool isInUse = m_usageCounter.IsTargetInUse(target.TargetName);
+                    var targetIndex = listTargets.SelectedIndices[0];
+                    var target = m_targets[targetIndex];
+                    var isInUse = m_usageCounter.IsTargetInUse(target.TargetName);
                     btnRemoveTarget.Enabled = !isInUse;
                     btnRemoveTarget.Enabled = !isInUse;
                 }
                 }
                 else
                 else
@@ -180,13 +184,13 @@ namespace ISCSIConsole
 
 
         private static List<IPAddress> GetHostIPAddresses()
         private static List<IPAddress> GetHostIPAddresses()
         {
         {
-            List<IPAddress> result = new List<IPAddress>();
-            foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
+            var result = new List<IPAddress>();
+            foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
             {
             {
-                IPInterfaceProperties ipProperties = netInterface.GetIPProperties();
-                foreach (UnicastIPAddressInformation addressInfo in ipProperties.UnicastAddresses)
+                var ipProperties = netInterface.GetIPProperties();
+                foreach (var addressInfo in ipProperties.UnicastAddresses)
                 {
                 {
-                    if (addressInfo.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+                    if (addressInfo.Address.AddressFamily == AddressFamily.InterNetwork)
                     {
                     {
                         result.Add(addressInfo.Address);
                         result.Add(addressInfo.Address);
                     }
                     }
@@ -199,5 +203,47 @@ namespace ISCSIConsole
         {
         {
             UpdateUI();
             UpdateUI();
         }
         }
+
+        private void LoadConfigButton_Click(object sender, EventArgs e)
+        {
+            if (0 != m_targets.Count)
+            {
+                MessageBox.Show("Remove all targets before load config");
+                return;
+            }
+
+            LoadFromConfig();
+        }
+
+        private void LoadFromConfig()
+        {
+            var entries = ((List<AutoLoadEntry>)ConfigurationManager.GetSection("autoLoad")).Where(p => p.Enable).ToArray();
+            if (entries.Length != entries.Select(p => p.Iqn).Distinct().Count())
+            {
+                MessageBox.Show("Config error: Iqn should no duplicate");
+                return;
+            }
+
+            var arr = new ISCSITarget[entries.Length];
+
+            for (int i = 0; i < arr.Length; i++)
+            {
+
+                arr[i] = entries[i].CreateTarget();
+            }
+
+            foreach (var target in arr)
+            {
+                AddTarget(target);
+            }
+        }
+
+        private void MainForm_Shown(object sender, EventArgs e)
+        {
+            if (IPAddress.TryParse(ConfigurationManager.AppSettings["Listen"], out var ipAddress)) comboIPAddress.Text = ipAddress.ToString();
+            if (int.TryParse(ConfigurationManager.AppSettings["Port"], out var port)) txtPort.Text = port.ToString();
+            if ("true" == ConfigurationManager.AppSettings["AutoLoadConfig"]) LoadFromConfig();
+            if ("true" == ConfigurationManager.AppSettings["AutoStart"]) btnStart_Click(null, null);
+        }
     }
     }
 }
 }

+ 4 - 4
ISCSIConsole/MainForm.resx

@@ -112,15 +112,15 @@
     <value>2.0</value>
     <value>2.0</value>
   </resheader>
   </resheader>
   <resheader name="reader">
   <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   </resheader>
   <resheader name="writer">
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   </resheader>
-  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>17, 17</value>
     <value>17, 17</value>
   </metadata>
   </metadata>
-  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
     <value>
         AAABAAYAAAAAAAEAIAAoIAQAZgAAAICAAAABACAAKAgBAI4gBABAQAAAAQAgAChCAAC2KAUAMDAAAAEA
         AAABAAYAAAAAAAEAIAAoIAQAZgAAAICAAAABACAAKAgBAI4gBABAQAAAAQAgAChCAAC2KAUAMDAAAAEA

+ 121 - 0
ISCSIConsole/Mods/AutoLoadEntry.cs

@@ -0,0 +1,121 @@
+using DiskAccessLibrary;
+using DiskAccessLibrary.Mod;
+using ISCSI.Server;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics;
+using System.Xml;
+
+namespace ISCSIConsole.Mods
+{
+    public class AutoLoadEntrySection : IConfigurationSectionHandler
+    {
+        public object Create(object parent, object configContext, XmlNode section)
+        {
+            var entries = new List<AutoLoadEntry>();
+
+            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<AutoLoadDisk>();
+
+                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<AutoLoadDisk> Disks { get; set; }
+
+        public ISCSITarget CreateTarget()
+        {
+            var disks = new List<Disk>();
+            var target = new ISCSITarget(Iqn, disks);
+            foreach (var disk in Disks)
+            {
+                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
+                    {
+                        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));
+                        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.ReleaseLock();
+                    }
+
+                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
+    }
+}

+ 19 - 1
ISCSIConsole/app.config

@@ -1,3 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
 <configuration>
-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
+  <configSections>
+    <section name="autoLoad" type="ISCSIConsole.Mods.AutoLoadEntrySection,ISCSIConsole" />
+  </configSections>
+  <appSettings>
+    <add key="Listen" value="127.0.0.1" />
+    <add key="Port" value="3261" />
+    <add key="AutoLoadConfig" value="true" />
+    <add key="AutoStart" value="true" />
+  </appSettings>
+  <autoLoad>
+    <entry Enable="true" Iqn="iqn.1991-05.com.talaloni:LocalRamDisk">
+      <disk Enable="true" Type="RamDiskFromFile" FilePath="C:\Path\To\YourRamDisk.bdd" />
+    </entry>
+    <entry Enable="true" Iqn="iqn.1991-05.com.talaloni:LocalDisk">
+      <disk Enable="true" Type="AttachFile"  ReadOnly="true" FilePath="C:\Path\To\Your.img" />
+      <disk Enable="true" Type="AttachFile" FilePath="C:\Path\To\Your.bdd" />
+    </entry>
+  </autoLoad>
+</configuration>