diff --git a/src/MaksIT.LTO.Backup/Application.cs b/src/MaksIT.LTO.Backup/Application.cs index d7ab5f5..dc5e917 100644 --- a/src/MaksIT.LTO.Backup/Application.cs +++ b/src/MaksIT.LTO.Backup/Application.cs @@ -1,42 +1,102 @@ using System.Text; using System.Text.Json; -using System.Diagnostics.CodeAnalysis; +using System.Net; + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using MaksIT.LTO.Core; using MaksIT.LTO.Backup.Entities; -using System.Net; +using MaksIT.LTO.Core.MassStorage; +using MaksIT.LTO.Core.Networking; + namespace MaksIT.LTO.Backup; + public class Application { private const string _descriptoFileName = "descriptor.json"; - private const string _configurationFileName = "configuration.json"; private readonly string appPath = AppDomain.CurrentDomain.BaseDirectory; private readonly string _tapePath; private readonly string _descriptorFilePath; - private Configuration _configuration; + private readonly ILogger _logger; + private readonly ILogger _tapeDeviceLogger; + private readonly ILogger _networkConnectionLogger; + + private readonly Configuration _configuration; + + public Application( + ILogger logger, + ILoggerFactory loggerFactory, + IOptions configuration + ) { + _logger = logger; + _tapeDeviceLogger = loggerFactory.CreateLogger(); + _networkConnectionLogger = loggerFactory.CreateLogger(); - public Application() { _descriptorFilePath = Path.Combine(appPath, _descriptoFileName); - LoadConfiguration(); + _configuration = configuration.Value; _tapePath = _configuration.TapePath; } - [MemberNotNull(nameof(_configuration))] - public void LoadConfiguration() { - var configFilePath = Path.Combine(appPath, _configurationFileName); - var configuration = JsonSerializer.Deserialize(File.ReadAllText(configFilePath)); - if (configuration == null) - throw new InvalidOperationException("Failed to deserialize configuration."); + public void Run() { + Console.OutputEncoding = Encoding.UTF8; - _configuration = configuration; + while (true) { + Console.WriteLine("MaksIT.LTO.Backup v0.0.1"); + Console.WriteLine("© Maksym Sadovnychyy (MAKS-IT) 2024"); + + Console.WriteLine("\nSelect an action:"); + Console.WriteLine("1. Load tape"); + Console.WriteLine("2. Backup"); + Console.WriteLine("3. Restore"); + Console.WriteLine("4. Eject tape"); + Console.WriteLine("5. Get device status"); + Console.WriteLine("6. Tape Erase (Short)"); + Console.WriteLine("7. Exit"); + Console.Write("Enter your choice: "); + + var choice = Console.ReadLine(); + + try { + switch (choice) { + case "1": + LoadTape(); + break; + case "2": + Backup(); + break; + case "3": + Restore(); + break; + case "4": + EjectTape(); + break; + case "5": + GetDeviceStatus(); + break; + case "6": + TapeErase(); + break; + case "7": + Console.WriteLine("Exiting..."); + return; + default: + Console.WriteLine("Invalid choice. Please try again."); + break; + } + } + catch (Exception ex) { + _logger.LogError(ex, $"An error occurred: {ex.Message}"); + } + } } public void LoadTape() { - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger, _tapePath); LoadTape(handler); } @@ -44,11 +104,11 @@ public class Application { handler.Prepare(TapeDeviceHandler.TAPE_LOAD); Thread.Sleep(2000); - Console.WriteLine("Tape loaded."); + _logger.LogInformation("Tape loaded."); } public void EjectTape() { - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger, _tapePath); EjectTape(handler); } @@ -56,11 +116,11 @@ public class Application { handler.Prepare(TapeDeviceHandler.TAPE_UNLOAD); Thread.Sleep(2000); - Console.WriteLine("Tape ejected."); + _logger.LogInformation("Tape ejected."); } public void TapeErase() { - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger, _tapePath); LoadTape(handler); handler.SetMediaParams(LTOBlockSizes.LTO5); @@ -80,16 +140,14 @@ public class Application { handler.SetPosition(TapeDeviceHandler.TAPE_REWIND); Thread.Sleep(2000); - Console.WriteLine("Tape erased."); + _logger.LogInformation("Tape erased."); } - public void GetDeviceStatus() { - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger, _tapePath); handler.GetStatus(); } - public void PathAccessWrapper(WorkingFolder workingFolder, Action myAction) { if (workingFolder.LocalPath != null) { @@ -117,7 +175,7 @@ public class Application { throw new InvalidOperationException("Network credentials are required for remote paths."); } - using (new NetworkConnection(smbPath, networkCredential)) { + using (new NetworkConnection(_networkConnectionLogger, smbPath, networkCredential)) { myAction(smbPath); } } @@ -175,8 +233,8 @@ public class Application { } private void ZeroFillBlocks(TapeDeviceHandler handler, int blocks, uint blockSize) { - Console.WriteLine($"Writing {blocks} zero-filled blocks to tape."); - Console.WriteLine($"Block Size: {blockSize}."); + _logger.LogInformation($"Writing {blocks} zero-filled blocks to tape."); + _logger.LogInformation($"Block Size: {blockSize}."); var writeError = 0; @@ -191,10 +249,10 @@ public class Application { public void WriteFilesToTape(WorkingFolder workingFolder, string descriptorFilePath, uint blockSize) { PathAccessWrapper(workingFolder, (directoryPath) => { - Console.WriteLine($"Writing files to tape from: {directoryPath}."); - Console.WriteLine($"Block Size: {blockSize}."); + _logger.LogInformation($"Writing files to tape from: {directoryPath}."); + _logger.LogInformation($"Block Size: {blockSize}."); - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger, _tapePath); LoadTape(handler); @@ -240,7 +298,7 @@ public class Application { writeError = handler.WriteData(buffer); if (writeError != 0) { - Console.WriteLine($"Failed to write file: {filePath}"); + _logger.LogInformation($"Failed to write file: {filePath}"); return; } @@ -284,10 +342,10 @@ public class Application { } public BackupDescriptor? FindDescriptor(uint blockSize) { - Console.WriteLine("Searching for descriptor on tape..."); - Console.WriteLine($"Block Size: {blockSize}."); + _logger.LogInformation("Searching for descriptor on tape..."); + _logger.LogInformation($"Block Size: {blockSize}."); - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger,_tapePath); LoadTape(handler); @@ -331,12 +389,12 @@ public class Application { try { var descriptor = JsonSerializer.Deserialize(json); if (descriptor != null) { - Console.WriteLine("Descriptor read successfully."); + _logger.LogInformation("Descriptor read successfully."); return descriptor; } } catch (JsonException ex) { - Console.WriteLine($"Failed to parse descriptor JSON: {ex.Message}"); + _logger.LogInformation($"Failed to parse descriptor JSON: {ex.Message}"); } @@ -352,10 +410,10 @@ public class Application { public void RestoreDirectory(BackupDescriptor descriptor, WorkingFolder workingFolder) { PathAccessWrapper(workingFolder, (restoreDirectoryPath) => { - Console.WriteLine("Restoring files to directory: " + restoreDirectoryPath); - Console.WriteLine("Block Size: " + descriptor.BlockSize); + _logger.LogInformation("Restoring files to directory: " + restoreDirectoryPath); + _logger.LogInformation("Block Size: " + descriptor.BlockSize); - using var handler = new TapeDeviceHandler(_tapePath); + using var handler = new TapeDeviceHandler(_tapeDeviceLogger,_tapePath); LoadTape(handler); @@ -397,10 +455,10 @@ public class Application { var fileHashString = BitConverter.ToString(fileHash).Replace("-", "").ToLower(); if (fileHashString != file.FileHash) { - Console.WriteLine($"Checksum mismatch for file: {filePath}"); + _logger.LogInformation($"Checksum mismatch for file: {filePath}"); } else { - Console.WriteLine($"Restored file: {filePath}"); + _logger.LogInformation($"Restored file: {filePath}"); } } } @@ -414,7 +472,7 @@ public class Application { public int CheckMediaSize(string ltoGen) { var descriptor = JsonSerializer.Deserialize(File.ReadAllText(_descriptorFilePath)); if (descriptor == null) { - Console.WriteLine("Failed to read descriptor."); + _logger.LogInformation("Failed to read descriptor."); return 1; } @@ -430,11 +488,11 @@ public class Application { var maxBlocks = LTOBlockSizes.GetMaxBlocks(ltoGen); if (totalBlocks > maxBlocks) { - Console.WriteLine("Backup will not fit on tape. Please use a larger tape."); + _logger.LogInformation("Backup will not fit on tape. Please use a larger tape."); return 1; } else { - Console.WriteLine("Backup will fit on tape."); + _logger.LogInformation("Backup will fit on tape."); } return 0; @@ -442,21 +500,21 @@ public class Application { public void Backup() { while (true) { - Console.WriteLine("\nSelect a backup to perform:"); + _logger.LogInformation("\nSelect a backup to perform:"); for (int i = 0; i < _configuration.Backups.Count; i++) { var backupInt = _configuration.Backups[i]; - Console.WriteLine($"{i + 1}. Backup Name: {backupInt.Name}, Bar code {(string.IsNullOrEmpty(backupInt.Barcode) ? "None" : backupInt.Barcode)}, Source: {backupInt.Source}, Destination: {backupInt.Destination}"); + _logger.LogInformation($"{i + 1}. Backup Name: {backupInt.Name}, Bar code {(string.IsNullOrEmpty(backupInt.Barcode) ? "None" : backupInt.Barcode)}, Source: {backupInt.Source}, Destination: {backupInt.Destination}"); } Console.Write("Enter your choice (or '0' to go back): "); var choice = Console.ReadLine(); if (choice == "0") { - return; // Go back to the main menu + return; } if (!int.TryParse(choice, out int index) || index < 1 || index > _configuration.Backups.Count) { - Console.WriteLine("Invalid choice. Please try again."); + _logger.LogInformation("Invalid choice. Please try again."); continue; } @@ -476,28 +534,28 @@ public class Application { WriteFilesToTape(backup.Source, _descriptorFilePath, blockSize); File.Delete(_descriptorFilePath); - Console.WriteLine("Backup completed."); - return; // Go back to the main menu after completing the backup + _logger.LogInformation("Backup completed."); + return; } } public void Restore() { while (true) { - Console.WriteLine("\nSelect a backup to restore:"); + _logger.LogInformation("\nSelect a backup to restore:"); for (int i = 0; i < _configuration.Backups.Count; i++) { var backupInt = _configuration.Backups[i]; - Console.WriteLine($"{i + 1}. Backup Name: {backupInt.Name}, Bar code {(string.IsNullOrEmpty(backupInt.Barcode) ? "None" : backupInt.Barcode)}, Source: {backupInt.Source}, Destination: {backupInt.Destination}"); + _logger.LogInformation($"{i + 1}. Backup Name: {backupInt.Name}, Bar code {(string.IsNullOrEmpty(backupInt.Barcode) ? "None" : backupInt.Barcode)}, Source: {backupInt.Source}, Destination: {backupInt.Destination}"); } Console.Write("Enter your choice (or '0' to go back): "); var choice = Console.ReadLine(); if (choice == "0") { - return; // Go back to the main menu + return; } if (!int.TryParse(choice, out int index) || index < 1 || index > _configuration.Backups.Count) { - Console.WriteLine("Invalid choice. Please try again."); + _logger.LogInformation("Invalid choice. Please try again."); continue; } @@ -505,21 +563,22 @@ public class Application { uint blockSize = LTOBlockSizes.GetBlockSize(backup.LTOGen); + // Step 1: Find Descriptor on Tape var descriptor = FindDescriptor(blockSize); if (descriptor != null) { var json = JsonSerializer.Serialize(descriptor, new JsonSerializerOptions { WriteIndented = true }); - Console.WriteLine(json); + _logger.LogInformation(json); } if (descriptor == null) { - Console.WriteLine("Descriptor not found on tape."); + _logger.LogInformation("Descriptor not found on tape."); return; } - // Step 3: Test restore from tape + // Step 2: Restore Files to Directory RestoreDirectory(descriptor, backup.Destination); - Console.WriteLine("Restore completed."); - return; // Go back to the main menu after completing the restore + _logger.LogInformation("Restore completed."); + return; } } } diff --git a/src/MaksIT.LTO.Backup/MaksIT.LTO.Backup.csproj b/src/MaksIT.LTO.Backup/MaksIT.LTO.Backup.csproj index 4de6d32..a76cc2f 100644 --- a/src/MaksIT.LTO.Backup/MaksIT.LTO.Backup.csproj +++ b/src/MaksIT.LTO.Backup/MaksIT.LTO.Backup.csproj @@ -7,6 +7,14 @@ enable + + + + + + + + diff --git a/src/MaksIT.LTO.Backup/Program.cs b/src/MaksIT.LTO.Backup/Program.cs index 64c7852..e248738 100644 --- a/src/MaksIT.LTO.Backup/Program.cs +++ b/src/MaksIT.LTO.Backup/Program.cs @@ -1,65 +1,35 @@ -namespace MaksIT.LTO.Backup; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using MaksIT.LTO.Core.Logging; + +namespace MaksIT.LTO.Backup; class Program { public static void Main() { - var app = new Application(); + // Set up configuration with reload support + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("configuration.json", optional: false, reloadOnChange: true) // Enable reload on change + .Build(); - Console.OutputEncoding = System.Text.Encoding.UTF8; + var serviceProvider = new ServiceCollection() + .Configure(configuration.GetSection("Configuration")) // Bind AppConfig directly + .AddSingleton(configuration) // Make IConfiguration available if needed + .AddLogging(builder => + { + builder.AddConfiguration(configuration.GetSection("Logging")); + builder.AddConsole(); + builder.AddFile(Path.Combine(Directory.GetCurrentDirectory(), "log.txt")); + }) + .AddTransient() + .BuildServiceProvider(); - while (true) { - // Console.Clear(); - Console.WriteLine("MaksIT.LTO.Backup v0.0.1"); - Console.WriteLine("© Maksym Sadovnychyy (MAKS-IT) 2024"); - Console.WriteLine("\nSelect an action:"); - Console.WriteLine("1. Load tape"); - Console.WriteLine("2. Backup"); - Console.WriteLine("3. Restore"); - Console.WriteLine("4. Eject tape"); - Console.WriteLine("5. Get device status"); - Console.WriteLine("6. Tape Erase (Short)"); - Console.WriteLine("7. Reload configurations"); - Console.WriteLine("8. Exit"); - Console.Write("Enter your choice: "); - - var choice = Console.ReadLine(); - - try { - switch (choice) { - case "1": - app.LoadTape(); - break; - case "2": - app.Backup(); - break; - case "3": - app.Restore(); - break; - case "4": - app.EjectTape(); - break; - case "5": - app.GetDeviceStatus(); - break; - case "6": - app.TapeErase(); - break; - case "7": - app.LoadConfiguration(); - break; - case "8": - Console.WriteLine("Exiting..."); - return; - default: - Console.WriteLine("Invalid choice. Please try again."); - break; - } - } - catch (Exception ex) { - Console.WriteLine($"An error occurred: {ex.Message}"); - } - } + // Get the App service and run it + var app = serviceProvider.GetRequiredService(); + app.Run(); } } diff --git a/src/MaksIT.LTO.Backup/configuration.json b/src/MaksIT.LTO.Backup/configuration.json index f41b3b3..d7e4f7e 100644 --- a/src/MaksIT.LTO.Backup/configuration.json +++ b/src/MaksIT.LTO.Backup/configuration.json @@ -1,41 +1,51 @@ { - "TapePath": "\\\\.\\Tape0", - "WriteDelay": 100, - "Backups": [ - { - "Name": "Normal test", - "Barcode": "", - "LTOGen": "LTO5", - "Source": { - "LocalPath": { - "Path": "F:\\LTO\\Backup" - } - }, - "Destination": { - "LocalPath": { - "Path": "F:\\LTO\\Restore" - } - } - }, - { - "Name": "Network test", - "Barcode": "", - "LTOGen": "LTO5", - "Source": { - "RemotePath": { - "Path": "\\\\nassrv0002.corp.maks-it.com\\data-1\\Users", - "PasswordCredentials": { - "Username": "", - "Password": "" - }, - "Protocol": "SMB" - } - }, - "Destination": { - "LocalPath": { - "Path": "F:\\LTO\\Restore" - } - } + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" } - ] + }, + + "Configuration": { + "TapePath": "\\\\.\\Tape0", + "WriteDelay": 100, + "Backups": [ + { + "Name": "Normal test", + "Barcode": "", + "LTOGen": "LTO5", + "Source": { + "LocalPath": { + "Path": "F:\\LTO\\Backup" + } + }, + "Destination": { + "LocalPath": { + "Path": "F:\\LTO\\Restore" + } + } + }, + { + "Name": "Network test", + "Barcode": "", + "LTOGen": "LTO5", + "Source": { + "RemotePath": { + "Path": "\\\\nassrv0002.corp.maks-it.com\\data-1\\Users", + "PasswordCredentials": { + "Username": "", + "Password": "" + }, + "Protocol": "SMB" + } + }, + "Destination": { + "LocalPath": { + "Path": "F:\\LTO\\Restore" + } + } + } + ] + } } \ No newline at end of file diff --git a/src/MaksIT.LTO.Core/LTOBlockSizes.cs b/src/MaksIT.LTO.Core/LTOBlockSizes.cs deleted file mode 100644 index 7261c2b..0000000 --- a/src/MaksIT.LTO.Core/LTOBlockSizes.cs +++ /dev/null @@ -1,60 +0,0 @@ - -namespace MaksIT.LTO.Core; - -public static class LTOBlockSizes { - public const uint LTO1 = 65536; // 64 KB - public const uint LTO2 = 65536; // 64 KB - public const uint LTO3 = 131072; // 128 KB - public const uint LTO4 = 131072; // 128 KB - public const uint LTO5 = 262144; // 256 KB - public const uint LTO6 = 262144; // 256 KB - public const uint LTO7 = 524288; // 512 KB - public const uint LTO8 = 524288; // 512 KB - public const uint LTO9 = 1048576; // 1 MB - - // Dictionary to store the total capacity for each LTO generation (in bytes) - private static readonly Dictionary TapeCapacities = new Dictionary - { - { "LTO1", 100UL * 1024 * 1024 * 1024 }, // 100 GB - { "LTO2", 200UL * 1024 * 1024 * 1024 }, // 200 GB - { "LTO3", 400UL * 1024 * 1024 * 1024 }, // 400 GB - { "LTO4", 800UL * 1024 * 1024 * 1024 }, // 800 GB - { "LTO5", 1500UL * 1024 * 1024 * 1024 }, // 1.5 TB - { "LTO6", 2500UL * 1024 * 1024 * 1024 }, // 2.5 TB - { "LTO7", 6000UL * 1024 * 1024 * 1024 }, // 6 TB - { "LTO8", 12000UL * 1024 * 1024 * 1024 },// 12 TB - { "LTO9", 18000UL * 1024 * 1024 * 1024 } // 18 TB - }; - - // Method to get the block size for a given LTO generation - // Method to get the block size for a given LTO generation - public static uint GetBlockSize(string ltoGen) { - return ltoGen switch { - "LTO1" => LTO1, - "LTO2" => LTO2, - "LTO3" => LTO3, - "LTO4" => LTO4, - "LTO5" => LTO5, - "LTO6" => LTO6, - "LTO7" => LTO7, - "LTO8" => LTO8, - "LTO9" => LTO9, - _ => throw new ArgumentException("Invalid LTO generation") - }; - } - - // Method to get the total capacity for a given LTO generation - public static ulong GetTapeCapacity(string ltoGen) { - if (TapeCapacities.TryGetValue(ltoGen, out var capacity)) { - return capacity; - } - throw new ArgumentException("Invalid LTO generation"); - } - - // Method to calculate the maximum number of blocks that can be written on the tape - public static ulong GetMaxBlocks(string ltoGen) { - var blockSize = GetBlockSize(ltoGen); - var tapeCapacity = GetTapeCapacity(ltoGen); - return tapeCapacity / blockSize; - } -} diff --git a/src/MaksIT.LTO.Core/Logging/FileLogger.cs b/src/MaksIT.LTO.Core/Logging/FileLogger.cs new file mode 100644 index 0000000..ff8009a --- /dev/null +++ b/src/MaksIT.LTO.Core/Logging/FileLogger.cs @@ -0,0 +1,37 @@ +using Microsoft.Extensions.Logging; + + +namespace MaksIT.LTO.Core.Logging; + +public class FileLogger : ILogger { + private readonly string _filePath; + private readonly object _lock = new object(); + + public FileLogger(string filePath) { + _filePath = filePath; + } + + public IDisposable? BeginScope(TState state) where TState : notnull => null; + + public bool IsEnabled(LogLevel logLevel) { + return logLevel != LogLevel.None; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { + if (!IsEnabled(logLevel)) + return; + + var message = formatter(state, exception); + if (string.IsNullOrEmpty(message)) + return; + + var logRecord = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{logLevel}] {message}"; + if (exception != null) { + logRecord += Environment.NewLine + exception; + } + + lock (_lock) { + File.AppendAllText(_filePath, logRecord + Environment.NewLine); + } + } +} diff --git a/src/MaksIT.LTO.Core/Logging/FileLoggerProvider.cs b/src/MaksIT.LTO.Core/Logging/FileLoggerProvider.cs new file mode 100644 index 0000000..9120b2d --- /dev/null +++ b/src/MaksIT.LTO.Core/Logging/FileLoggerProvider.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Logging; + +namespace MaksIT.LTO.Core.Logging; + +[ProviderAlias("FileLogger")] +public class FileLoggerProvider : ILoggerProvider { + private readonly string _filePath; + + public FileLoggerProvider(string filePath) { + _filePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); + } + + public ILogger CreateLogger(string categoryName) { + return new FileLogger(_filePath); + } + + public void Dispose() { } +} diff --git a/src/MaksIT.LTO.Core/Logging/LoggingBuilderExtensions.cs b/src/MaksIT.LTO.Core/Logging/LoggingBuilderExtensions.cs new file mode 100644 index 0000000..6b01f71 --- /dev/null +++ b/src/MaksIT.LTO.Core/Logging/LoggingBuilderExtensions.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace MaksIT.LTO.Core.Logging; + +public static class LoggingBuilderExtensions { + public static ILoggingBuilder AddFile(this ILoggingBuilder builder, string filePath) { + builder.Services.AddSingleton(new FileLoggerProvider(filePath)); + return builder; + } +} diff --git a/src/MaksIT.LTO.Core/MaksIT.LTO.Core.csproj b/src/MaksIT.LTO.Core/MaksIT.LTO.Core.csproj index c8734fc..e60b572 100644 --- a/src/MaksIT.LTO.Core/MaksIT.LTO.Core.csproj +++ b/src/MaksIT.LTO.Core/MaksIT.LTO.Core.csproj @@ -7,4 +7,9 @@ NTDDI_VERSION_05010000;NTDDI_WINXP_05010000 + + + + + diff --git a/src/MaksIT.LTO.Core/MassStorage/LTOBlockSizes.cs b/src/MaksIT.LTO.Core/MassStorage/LTOBlockSizes.cs new file mode 100644 index 0000000..6fcc272 --- /dev/null +++ b/src/MaksIT.LTO.Core/MassStorage/LTOBlockSizes.cs @@ -0,0 +1,65 @@ +namespace MaksIT.LTO.Core.MassStorage; + +public static class LTOBlockSizes +{ + public const uint LTO1 = 65536; // 64 KB + public const uint LTO2 = 65536; // 64 KB + public const uint LTO3 = 131072; // 128 KB + public const uint LTO4 = 131072; // 128 KB + public const uint LTO5 = 262144; // 256 KB + public const uint LTO6 = 262144; // 256 KB + public const uint LTO7 = 524288; // 512 KB + public const uint LTO8 = 524288; // 512 KB + public const uint LTO9 = 1048576; // 1 MB + + // Dictionary to store the total capacity for each LTO generation (in bytes) + private static readonly Dictionary TapeCapacities = new Dictionary + { + { "LTO1", 100UL * 1024 * 1024 * 1024 }, // 100 GB + { "LTO2", 200UL * 1024 * 1024 * 1024 }, // 200 GB + { "LTO3", 400UL * 1024 * 1024 * 1024 }, // 400 GB + { "LTO4", 800UL * 1024 * 1024 * 1024 }, // 800 GB + { "LTO5", 1500UL * 1024 * 1024 * 1024 }, // 1.5 TB + { "LTO6", 2500UL * 1024 * 1024 * 1024 }, // 2.5 TB + { "LTO7", 6000UL * 1024 * 1024 * 1024 }, // 6 TB + { "LTO8", 12000UL * 1024 * 1024 * 1024 },// 12 TB + { "LTO9", 18000UL * 1024 * 1024 * 1024 } // 18 TB + }; + + // Method to get the block size for a given LTO generation + // Method to get the block size for a given LTO generation + public static uint GetBlockSize(string ltoGen) + { + return ltoGen switch + { + "LTO1" => LTO1, + "LTO2" => LTO2, + "LTO3" => LTO3, + "LTO4" => LTO4, + "LTO5" => LTO5, + "LTO6" => LTO6, + "LTO7" => LTO7, + "LTO8" => LTO8, + "LTO9" => LTO9, + _ => throw new ArgumentException("Invalid LTO generation") + }; + } + + // Method to get the total capacity for a given LTO generation + public static ulong GetTapeCapacity(string ltoGen) + { + if (TapeCapacities.TryGetValue(ltoGen, out var capacity)) + { + return capacity; + } + throw new ArgumentException("Invalid LTO generation"); + } + + // Method to calculate the maximum number of blocks that can be written on the tape + public static ulong GetMaxBlocks(string ltoGen) + { + var blockSize = GetBlockSize(ltoGen); + var tapeCapacity = GetTapeCapacity(ltoGen); + return tapeCapacity / blockSize; + } +} diff --git a/src/MaksIT.LTO.Core/TapeDeviceHandler.cs b/src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandler.cs similarity index 95% rename from src/MaksIT.LTO.Core/TapeDeviceHandler.cs rename to src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandler.cs index dc4645b..9d646a8 100644 --- a/src/MaksIT.LTO.Core/TapeDeviceHandler.cs +++ b/src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandler.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using Microsoft.Extensions.Logging; using Microsoft.Win32.SafeHandles; // https://github.com/tpn/winsdk-10 @@ -8,11 +9,11 @@ using Microsoft.Win32.SafeHandles; namespace MaksIT.LTO.Core; public partial class TapeDeviceHandler : IDisposable { + + private readonly ILogger _logger; private string _tapeDevicePath; private SafeFileHandle _tapeHandle; - - private const uint GENERIC_READ = 0x80000000; private const uint GENERIC_WRITE = 0x40000000; private const uint OPEN_EXISTING = 3; @@ -67,7 +68,11 @@ public partial class TapeDeviceHandler : IDisposable { out uint lpNumberOfBytesRead, IntPtr lpOverlapped); - public TapeDeviceHandler(string tapeDevicePath) { + public TapeDeviceHandler( + ILogger logger, + string tapeDevicePath + ) { + _logger = logger; _tapeDevicePath = tapeDevicePath; OpenTapeDevice(GENERIC_READ | GENERIC_WRITE); } diff --git a/src/MaksIT.LTO.Core/TapeDeviceHandlerNtdstor.cs b/src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandlerNtdstor.cs similarity index 100% rename from src/MaksIT.LTO.Core/TapeDeviceHandlerNtdstor.cs rename to src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandlerNtdstor.cs diff --git a/src/MaksIT.LTO.Core/TapeDeviceHandlerNtdtape.cs b/src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandlerNtdtape.cs similarity index 100% rename from src/MaksIT.LTO.Core/TapeDeviceHandlerNtdtape.cs rename to src/MaksIT.LTO.Core/MassStorage/TapeDeviceHandlerNtdtape.cs diff --git a/src/MaksIT.LTO.Core/NetworkConnection.cs b/src/MaksIT.LTO.Core/Networking/NetworkConnection.cs similarity index 69% rename from src/MaksIT.LTO.Core/NetworkConnection.cs rename to src/MaksIT.LTO.Core/Networking/NetworkConnection.cs index e76a8c5..bec6dea 100644 --- a/src/MaksIT.LTO.Core/NetworkConnection.cs +++ b/src/MaksIT.LTO.Core/Networking/NetworkConnection.cs @@ -1,27 +1,23 @@ using System.Net; using System.Runtime.InteropServices; -namespace MaksIT.LTO.Core; +using Microsoft.Extensions.Logging; -//public void RestoreFilesFromSmbShare(string smbPath, string username, string password, string domain, string restoreDirectory) { -// var credentials = new NetworkCredential(username, password, domain); -// using (new NetworkConnection(smbPath, credentials)) { -// var files = Directory.GetFiles(smbPath, "*.*", SearchOption.AllDirectories); -// foreach (var file in files) { -// var relativePath = Path.GetRelativePath(smbPath, file); -// var destinationPath = Path.Combine(restoreDirectory, relativePath); -// Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); -// File.Copy(file, destinationPath, overwrite: true); -// Console.WriteLine($"Restored file: {file} to {destinationPath}"); -// } -// } -//} +namespace MaksIT.LTO.Core.Networking; public class NetworkConnection : IDisposable { + + private readonly ILogger _logger; private readonly string _networkName; - public NetworkConnection(string networkName, NetworkCredential credentials) { + public NetworkConnection( + ILogger logger, + string networkName, + NetworkCredential credentials) { + + _logger = logger; + _networkName = networkName; var netResource = new NetResource {