Browse Source

Create project, live console logging added.

HOME 1 year ago
parent
commit
379ae8da1e

+ 25 - 0
.dockerignore

@@ -0,0 +1,25 @@
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md

+ 31 - 0
NetBootServerCore.sln

@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33326.253
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetBootServerCore", "NetBootServerCore\NetBootServerCore.csproj", "{C8CC6A44-E299-40EF-AC8C-3C1C2D7D2EA3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetBootServerCore.BlazorWasm", "NetBootServerCore.BlazorWasm\NetBootServerCore.BlazorWasm.csproj", "{DBC28F8B-573F-41AA-A59B-B6797D04ECE0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{C8CC6A44-E299-40EF-AC8C-3C1C2D7D2EA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C8CC6A44-E299-40EF-AC8C-3C1C2D7D2EA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C8CC6A44-E299-40EF-AC8C-3C1C2D7D2EA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C8CC6A44-E299-40EF-AC8C-3C1C2D7D2EA3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DBC28F8B-573F-41AA-A59B-B6797D04ECE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DBC28F8B-573F-41AA-A59B-B6797D04ECE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DBC28F8B-573F-41AA-A59B-B6797D04ECE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DBC28F8B-573F-41AA-A59B-B6797D04ECE0}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {F5148C3A-92DD-4C0A-AB5C-5424A7D0E7A6}
+	EndGlobalSection
+EndGlobal

+ 3 - 0
NetBootServerCore.sln.DotSettings

@@ -0,0 +1,3 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:Boolean x:Key="/Default/UserDictionary/Words/=DHCP/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/UserDictionary/Words/=Tftp/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

+ 18 - 0
NetBootServerCore/Components/Nbs/DhcpServer.cs

@@ -0,0 +1,18 @@
+using NetBootServerCore.Components.UI.Cui;
+
+namespace NetBootServerCore.Components.Nbs
+{
+    public class DhcpServer : NbsComponentBase
+    {
+        public DhcpServer(LiveConsole lc) : base(lc.CreateLogger("DHCP"))
+        {
+
+
+        }
+
+        protected override void OnStart()
+        {
+            base.OnStart();
+        }
+    }
+}

+ 14 - 0
NetBootServerCore/Components/Nbs/TftpServer.cs

@@ -0,0 +1,14 @@
+using NetBootServerCore.Components.UI.Cui;
+
+namespace NetBootServerCore.Components.Nbs
+{
+    public class TftpServer : NbsComponentBase
+    {
+        public TftpServer(LiveConsole lc) : base(lc.CreateLogger("TFTP"))
+        {
+
+
+        }
+        // import Callisto82/tftp.net
+    }
+}

+ 20 - 0
NetBootServerCore/Components/Nbs/iPxeScriptProcessor.cs

@@ -0,0 +1,20 @@
+using NetBootServerCore.Components.UI.Cui;
+using NetBootServerCore.Components.UI.Http;
+
+namespace NetBootServerCore.Components.Nbs
+{
+    public class iPxeScriptProcessor : NbsComponentBase, IHttpRequestProcessor
+    {
+        public iPxeScriptProcessor(LiveConsole lc) : base(lc.CreateLogger("HTTP.iPXE"))
+        {
+
+
+        }
+
+        public bool ProcessRequest(HttpContext request)
+        {
+            //TODO: iPXE boot scripts
+            return false;
+        }
+    }
+}

+ 41 - 0
NetBootServerCore/Components/NbsComponentBase.cs

@@ -0,0 +1,41 @@
+using NetBootServerCore.Components.UI.Cui;
+using NetBootServerCore.Components.UI.Cui.Logging;
+
+namespace NetBootServerCore.Components
+{
+    public abstract class NbsComponentBase
+    {
+        protected LiveConsoleLogger Logger { get; }
+
+        protected NbsComponentBase(LiveConsoleLogger logger)
+        {
+            Logger = logger;
+            logger.LogVerbose("Create");
+        }
+
+
+
+        public void Start()
+        {
+            Logger.LogVerbose("Starting");
+            OnStart();
+            Logger.LogVerbose("Started");
+
+        }
+
+        public void Stop()
+        {
+            Logger.LogVerbose("Stopping");
+            OnStop();
+            Logger.LogVerbose("Stopped");
+        }
+
+        protected virtual void OnStart()
+        {
+        }
+
+        protected virtual void OnStop()
+        {
+        }
+    }
+}

+ 111 - 0
NetBootServerCore/Components/UI/Cui/LiveConsole.cs

@@ -0,0 +1,111 @@
+using NetBootServerCore.Components.UI.Cui.Logging;
+using Spectre.Console;
+using System.Collections.Concurrent;
+
+namespace NetBootServerCore.Components.UI.Cui
+{
+    public class LiveConsole : NbsComponentBase
+    {
+        public LiveConsole() : base(LiveConsoleLogger.Null)
+        {
+        }
+
+        private readonly BlockingCollection<LiveConsoleItem> _queue = new();
+
+        private int RequestsHandled = 0;
+        private int InBytes = 0;
+        private int OutBytes = 0;
+
+        private List<LogEntry> _logs = new();
+
+        public void Enqueue(LiveConsoleItem item)
+        {
+            if (!_queue.IsAddingCompleted) _queue.TryAdd(item);
+        }
+
+        public LiveConsoleLogger CreateLogger(string tag) => new(this, tag);
+
+        protected override void OnStart() => Task.Run(RunInternal);
+
+        protected override void OnStop()
+        {
+            _queue.CompleteAdding();
+
+            var wait = 0;
+            while (_queue.Count != 0 && wait < 10)
+            {
+                Thread.Sleep(500);
+                ++wait;
+            }
+        }
+
+        private void RunInternal()
+        {
+            Table tableMain;
+            TableColumn ct1UpTime;
+            TableColumn ct2RequestHandled;
+            {
+                tableMain = new Table() { Border = TableBorder.None, Expand = true };
+                var colMain = new TableColumn("");
+                tableMain.AddColumn(colMain);
+                var tableTitle = new Table();
+                {
+                    ct1UpTime = new TableColumn("");
+                    ct2RequestHandled = new TableColumn("");
+                    tableTitle.AddColumn(ct1UpTime);
+                    tableTitle.AddColumn(ct2RequestHandled);
+                }
+                colMain.Header = tableTitle;
+
+                tableMain.AddRow(new Panel("Logs Brrr"));
+            }
+
+            //init content
+            ct2RequestHandled.Header = new Text($"Reqs: {RequestsHandled} In: {InBytes} Out: {OutBytes}");
+
+            do
+            {
+                AnsiConsole.Clear();
+                var live = AnsiConsole.Live(tableMain);
+                live.Cropping(VerticalOverflowCropping.Bottom)
+                    .Start(ctx =>
+                    {
+                        var conW = Console.WindowWidth;
+                        var conH = Console.WindowHeight;
+                        do
+                        {
+                            void RefreshCycle()
+                            {
+                                var now = DateTime.Now;
+                                var up = now - NbsProgram.StartTime;
+                                ct1UpTime.Header = new Text($"UP: {(int)up.TotalDays:00}D {up.Hours:00}H {up.Minutes:00}M {up.Seconds:00}S {up.Milliseconds:000}");
+                                if (_logs.Any() && Console.WindowHeight > 4) tableMain.UpdateCell(0, 0, new Rows(_logs.TakeLast(conH - 4).Select(p => p.ToMarkup(conW))));
+                                ctx.Refresh();
+                            }
+
+                            if (conW != Console.WindowWidth || conH != Console.WindowHeight)
+                            {
+                                live.AutoClear = false;
+                                return;//Exit Live
+                            }
+
+                            if (_queue.TryTake(out var item, 1000))
+                            {
+                                switch (item.Type)
+                                {
+                                    case LiveConsoleItemType.Log:
+                                        _logs.Add(item.ToLog());
+                                        RefreshCycle();
+                                        break;
+                                }
+                            }
+                            else
+                            {
+                                RefreshCycle();
+                            }
+                        } while (_queue.IsAddingCompleted == false || _queue.Count > 0);
+                    });//End Live
+            } while (_queue.IsAddingCompleted == false || _queue.Count > 0);
+        }
+    }
+}

+ 19 - 0
NetBootServerCore/Components/UI/Cui/LiveConsoleItem.cs

@@ -0,0 +1,19 @@
+using NetBootServerCore.Components.UI.Cui.Logging;
+using LogLevel = NetBootServerCore.Components.UI.Cui.Logging.LogLevel;
+
+
+namespace NetBootServerCore.Components.UI.Cui;
+
+public class LiveConsoleItem
+{
+    public DateTime Time { get; } = DateTime.Now;
+    public LiveConsoleItemType Type { get; set; }
+    public string Text { get; set; }
+
+    public int Value32S { get; set; }
+    public long Value64S { get; set; }
+    public LogLevel LogLevel { get; set; }
+
+
+    public LogEntry ToLog() => new LogEntry { Time = Time, Level = LogLevel, Message = Text };
+}

+ 6 - 0
NetBootServerCore/Components/UI/Cui/LiveConsoleItemType.cs

@@ -0,0 +1,6 @@
+namespace NetBootServerCore.Components.UI.Cui;
+
+public enum LiveConsoleItemType
+{
+    Log
+}

+ 24 - 0
NetBootServerCore/Components/UI/Cui/Logging/LiveConsoleLogger.cs

@@ -0,0 +1,24 @@
+namespace NetBootServerCore.Components.UI.Cui.Logging
+{
+    public class LiveConsoleLogger
+    {
+        public static readonly LiveConsoleLogger Null = new (null, null);
+
+        private readonly LiveConsole _liveConsole;
+        public string Tag { get; }
+
+        public LiveConsoleLogger(LiveConsole liveConsole, string tag)
+        {
+            _liveConsole = liveConsole;
+            Tag = tag;
+        }
+
+        public void LogDebug(string message) => _liveConsole?.Enqueue(new LiveConsoleItem { Type = LiveConsoleItemType.Log, LogLevel = LogLevel.Debug, Text = $"[{Tag}] {message}" });
+        public void LogVerbose(string message) => _liveConsole?.Enqueue(new LiveConsoleItem { Type = LiveConsoleItemType.Log, LogLevel = LogLevel.Verbose, Text = $"[{Tag}] {message}" });
+        public void LogInfo(string message) => _liveConsole?.Enqueue(new LiveConsoleItem { Type = LiveConsoleItemType.Log, LogLevel = LogLevel.Info, Text = $"[{Tag}] {message}" });
+        public void LogWarn(string message) => _liveConsole?.Enqueue(new LiveConsoleItem { Type = LiveConsoleItemType.Log, LogLevel = LogLevel.Warn, Text = $"[{Tag}] {message}" });
+        public void LogError(string message) => _liveConsole?.Enqueue(new LiveConsoleItem { Type = LiveConsoleItemType.Log, LogLevel = LogLevel.Error, Text = $"[{Tag}] {message}" });
+        public void LogFatal(string message) => _liveConsole?.Enqueue(new LiveConsoleItem { Type = LiveConsoleItemType.Log, LogLevel = LogLevel.Fatal, Text = $"[{Tag}] {message}" });
+
+    }
+}

+ 71 - 0
NetBootServerCore/Components/UI/Cui/Logging/LogEntry.cs

@@ -0,0 +1,71 @@
+using Spectre.Console;
+using static Spectre.Console.Markup;
+
+namespace NetBootServerCore.Components.UI.Cui.Logging
+{
+    public class LogEntry
+    {
+        public DateTime Time { get; set; }
+        public LogLevel Level { get; set; }
+        public string Message { get; set; }
+
+        public Markup ToMarkup(int consoleWidth)
+        {
+            var color = "aqua";
+            var prefix = "UNKNOWN ";
+
+            switch (Level)
+            {
+                case LogLevel.Debug:
+                    color = "grey";
+                    prefix = "DEBG";
+                    break;
+
+                case LogLevel.Verbose:
+                    color = "aqua";
+                    prefix = "VERB";
+                    break;
+
+                case LogLevel.Info:
+                    color = "lime";
+                    prefix = "INFO";
+                    break;
+
+                case LogLevel.Warn:
+                    color = "yellow";
+                    prefix = "WARN";
+                    break;
+
+                case LogLevel.Error:
+                    color = "red";
+                    prefix = "ERRO";
+                    break;
+
+                case LogLevel.Fatal:
+                    color = "fuchsia";
+                    prefix = "FATL";
+                    break;
+            }
+
+            var ts = $"{Time:MMdd/HH:mm:ss.ff} ";
+            var len = ts.Length;
+
+            var pm = $"[bold {color}]{Escape(prefix)}[/] ";
+            len += prefix.Length + 1;
+
+            var msg = Message;
+            len += msg.Length;
+
+            if (consoleWidth < len + 3)
+            {
+                var sub = msg.Length - (len + 3 - consoleWidth);
+
+                msg = sub > 0
+                    ? msg.Substring(0, sub)
+                    : "";
+            }
+
+            return new Markup($" {Escape(ts)}{pm}{Escape(msg)}");
+        }
+    }
+}

+ 11 - 0
NetBootServerCore/Components/UI/Cui/Logging/LogLevel.cs

@@ -0,0 +1,11 @@
+namespace NetBootServerCore.Components.UI.Cui.Logging;
+
+public enum LogLevel
+{
+    Debug = 0,
+    Verbose = 1,
+    Info = 2,
+    Warn = 3,
+    Error = 4,
+    Fatal = 5,
+}

+ 37 - 0
NetBootServerCore/Components/UI/Http/HttpServer.cs

@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Http.Extensions;
+using NetBootServerCore.Components.UI.Cui;
+using NetBootServerCore.Components.UI.Cui.Logging;
+using System.Collections.Immutable;
+
+namespace NetBootServerCore.Components.UI.Http
+{
+    public class HttpServer : NbsComponentBase
+    {
+        private readonly LiveConsole _liveConsole;
+        private readonly IReadOnlyCollection<IHttpRequestProcessor> _processors;
+
+        public HttpServer(LiveConsole liveConsole, IEnumerable<IHttpRequestProcessor> processors) : base(liveConsole.CreateLogger("HTTP"))
+        {
+            _liveConsole = liveConsole;
+            _processors = processors.ToImmutableArray();
+        }
+
+        protected override void OnStart()
+        {
+            var builder = WebApplication.CreateBuilder();
+            var app = builder.Build();
+
+            app.Run(async context =>
+            {
+                context.Response.Headers.Server = nameof(NetBootServerCore);
+
+                if (_processors.Any(processor => processor.ProcessRequest(context))) return;
+
+                context.Response.StatusCode = 404;
+                Logger.LogWarn($"404 {context.Request.GetEncodedPathAndQuery()}");
+            });
+
+            app.RunAsync();
+        }
+    }
+}

+ 6 - 0
NetBootServerCore/Components/UI/Http/IHttpRequestProcessor.cs

@@ -0,0 +1,6 @@
+namespace NetBootServerCore.Components.UI.Http;
+
+public interface IHttpRequestProcessor
+{
+    bool ProcessRequest(HttpContext request);
+}

+ 17 - 0
NetBootServerCore/Components/UI/Http/StaticContent/StaticContentProcessor.cs

@@ -0,0 +1,17 @@
+using NetBootServerCore.Components.UI.Cui;
+
+namespace NetBootServerCore.Components.UI.Http.StaticContent
+{
+    public class StaticContentProcessor : NbsComponentBase, IHttpRequestProcessor
+    {
+        public StaticContentProcessor(LiveConsole liveConsole) : base(liveConsole.CreateLogger("HTTP.Static"))
+        {
+            
+        }
+        public bool ProcessRequest(HttpContext request)
+        {
+
+            return false;
+        }
+    }
+}

+ 23 - 0
NetBootServerCore/Components/UI/Http/WebApi/WebApiProcessor.cs

@@ -0,0 +1,23 @@
+using NetBootServerCore.Components.Nbs;
+using NetBootServerCore.Components.UI.Cui;
+
+namespace NetBootServerCore.Components.UI.Http.WebApi
+{
+    public class WebApiProcessor : NbsComponentBase, IHttpRequestProcessor
+    {
+        public WebApiProcessor(LiveConsole lc, DhcpServer dhcp) : base(lc.CreateLogger("HTTP.WebApi"))
+        {
+            
+
+        }
+
+        
+
+        public bool ProcessRequest(HttpContext request)
+        {
+            //TODO: Show DHCP Pool entries
+            return false;
+        }
+
+    }
+}

+ 21 - 0
NetBootServerCore/Dockerfile

@@ -0,0 +1,21 @@
+#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
+WORKDIR /src
+COPY ["NetBootServerCore/NetBootServerCore.csproj", "NetBootServerCore/"]
+RUN dotnet restore "NetBootServerCore/NetBootServerCore.csproj"
+COPY . .
+WORKDIR "/src/NetBootServerCore"
+RUN dotnet build "NetBootServerCore.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "NetBootServerCore.csproj" -c Release -o /app/publish /p:UseAppHost=false
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "NetBootServerCore.dll"]

+ 26 - 0
NetBootServerCore/NetBootServerCore.csproj

@@ -0,0 +1,26 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Spectre.Console" Version="0.46.1-preview.0.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="TftpRoot" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="iPxeBootScripts/Example-iSCSI.txt">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Update="TftpRoot/undionly.kpxe">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+
+</Project>

+ 98 - 0
NetBootServerCore/Program.cs

@@ -0,0 +1,98 @@
+using NetBootServerCore.Components.Nbs;
+using NetBootServerCore.Components.UI.Cui;
+using NetBootServerCore.Components.UI.Http;
+using NetBootServerCore.Components.UI.Http.StaticContent;
+using NetBootServerCore.Components.UI.Http.WebApi;
+
+namespace NetBootServerCore;
+
+public static class NbsProgram
+{
+    public static readonly DateTime StartTime;
+
+    static NbsProgram()
+    {
+        StartTime = DateTime.Now;
+    }
+
+    private static void Main(string[] args)
+    {
+        var lc = new LiveConsole();
+        var logger = lc.CreateLogger("APP");
+        Task.Run(lc.Start);
+
+        logger.LogDebug("Logger Init");
+        logger.LogVerbose("Logger Init");
+        logger.LogInfo("Logger Init");
+        logger.LogWarn("Logger Init");
+        logger.LogError("Logger Init");
+        logger.LogFatal("Logger Init");
+
+        logger.LogInfo("Load config");
+        var config = WebApplication.CreateBuilder(args).Configuration;
+        var httpPrefix = config.GetSection("Web")["Prefix"];
+        Console.Title = $"{nameof(NetBootServerCore)} at {httpPrefix}";
+        Environment.SetEnvironmentVariable("ASPNETCORE_URLS", httpPrefix);
+
+        logger.LogInfo("Create components");
+        var dhcp = new DhcpServer(lc);
+        var tftp = new TftpServer(lc);
+        var scriptServer = new iPxeScriptProcessor(lc);
+        var apiServer = new WebApiProcessor(lc, dhcp);
+        var staticServer = new StaticContentProcessor(lc);
+        var httpServer = new HttpServer(lc, new IHttpRequestProcessor[] { scriptServer, apiServer, staticServer });
+
+        logger.LogInfo("Start components");
+        dhcp.Start();
+        tftp.Start();
+        scriptServer.Start();
+        apiServer.Start();
+        staticServer.Start();
+        httpServer.Start();
+
+        logger.LogInfo("Running");
+
+        //Waiting until Control-C
+        {
+            CancellationTokenSource ctSource = new();
+            var ct = ctSource.Token;
+
+            void ExitHandler()
+            {
+                // You can add any arbitrary global clean up
+                logger.LogInfo("Exiting...");
+                ctSource.Cancel();
+            }
+
+            // Assign exit handler to be called when the process is terminated
+            // or the user hits CTRL+C
+            AppDomain.CurrentDomain.ProcessExit += (_, _) => ExitHandler();
+            Console.CancelKeyPress += (_, _) => ExitHandler();
+
+            // Then you can use the cancellation token to check for exit:
+            while (!ct.IsCancellationRequested)
+            {
+                try
+                {
+                    Task.Delay(1000, ct).Wait(ct);
+                }
+                catch (OperationCanceledException e)
+                {
+                    break;
+                }
+            }
+        }
+
+        //stop components
+        dhcp.Stop();
+        tftp.Stop();
+        apiServer.Stop();
+        scriptServer.Stop();
+        staticServer.Stop();
+        httpServer.Stop();
+
+        logger.LogInfo("Finished");
+        lc.Stop();
+
+    }
+}

+ 33 - 0
NetBootServerCore/Properties/launchSettings.json

@@ -0,0 +1,33 @@
+{
+  "profiles": {
+    "NetBootServerCore": {
+      "commandName": "Project",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      },
+      "dotnetRunMessages": true,
+      "applicationUrl": "http://localhost:5028"
+    },
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "Docker": {
+      "commandName": "Docker",
+      "launchBrowser": true,
+      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
+      "publishAllPorts": true
+    }
+  },
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:18075",
+      "sslPort": 0
+    }
+  }
+}

BIN
NetBootServerCore/TftpRoot/undionly.kpxe


+ 3 - 0
NetBootServerCore/appsettings.Development.json

@@ -0,0 +1,3 @@
+{
+
+}

+ 28 - 0
NetBootServerCore/appsettings.json

@@ -0,0 +1,28 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "None",
+      "Microsoft.AspNetCore": "None"
+    }
+  },
+  "AllowedHosts": "*",
+  "Web": {
+    "Prefix": "http://0.0.0.0:6880",
+    "BootScriptDir": "BootScripts"
+  },
+  "TFTP": {
+    "RootDir": "TftpRoot"
+  },
+  "DHCP": {
+    "ListenOn": "0.0.0.0",
+    "PoolStart": "192.168.233.154",
+    "PoolSize": 100,
+    "SubNet": "255.255.255.0",
+    "Gateway": "192.168.233.1",
+    "DNS": "192.168.233.53",
+    "BroadcastAddress": "192.168.233.255",
+    "Tftp": "192.168.233.133",
+    "BootFileName": "undionly.kpxe",
+    "BootFileName_iPXE": "http://192.168.233.133:6800/boot/ipxe"
+  }
+}

+ 28 - 0
NetBootServerCore/iPxeBootScripts/Example-iSCSI.txt

@@ -0,0 +1,28 @@
+#!ipxe
+
+################################
+set iscsi_target_name target-01
+set iscsi_target_host 192.168.233.233
+################################
+
+:label_start
+
+echo Script Started (${iscsi_target_name})
+
+:label_iscsi
+echo Setting up iSCSI iqn with mac...
+set initiator-iqn iqn.2010-04.org.ipxe:${mac:hexhyp}
+echo Connect to iSCSI target and booting...
+sanboot iscsi:${iscsi_target_host}::::iqn.1991-05.com.talaloni:${iscsi_target_name} || goto label_iscsi_fail
+
+################################
+goto label_eof
+################################
+
+:label_iscsi_fail
+
+prompt --key r iSCSI boot fail, press 'R' to retry iSCSI again && goto label_iscsi ||
+
+###############################
+:label_eof
+###############################