diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..18ff42a
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,3 @@
+PROXMOX_CLUSTER_URL=""
+PROXMOX_TOKEN_ID=""
+PROXMOX_TOKEN_SECRET=""
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..6313b56
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..921dd89
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+.vs/
+.vscode/*
+bin/
+obj/
+
+!.vscode/settings.json
+.DS_Store
+.DS_Store
+.env
+*.filters
+*.user
+desktop.ini
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000..d7cf64a
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,10 @@
+
+
+ true
+
+
+
+
+
+
+
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..292d951
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Tribufu. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/ProxmoxSharp.sln b/ProxmoxSharp.sln
new file mode 100644
index 0000000..86a497a
--- /dev/null
+++ b/ProxmoxSharp.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Proxmox", "src\Tribufu.Proxmox\Tribufu.Proxmox.csproj", "{A2756937-8D07-4164-9CB7-2C94E9FE0A08}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Proxmox.Tests", "src\Tribufu.Proxmox.Tests\Tribufu.Proxmox.Tests.csproj", "{0A59E867-1A89-4E07-ABE7-E7DC2FEE9317}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A2756937-8D07-4164-9CB7-2C94E9FE0A08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2756937-8D07-4164-9CB7-2C94E9FE0A08}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A2756937-8D07-4164-9CB7-2C94E9FE0A08}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A2756937-8D07-4164-9CB7-2C94E9FE0A08}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0A59E867-1A89-4E07-ABE7-E7DC2FEE9317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0A59E867-1A89-4E07-ABE7-E7DC2FEE9317}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0A59E867-1A89-4E07-ABE7-E7DC2FEE9317}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0A59E867-1A89-4E07-ABE7-E7DC2FEE9317}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/README.md b/README.md
index 2494351..e7923c6 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,20 @@
-# proxmox-sharp
\ No newline at end of file
+# Proxmox Sharp
+
+Proxmox C# API Client.
+
+[![MIT License][mit-badge]][mit-url]
+[![Discord Chat][discord-badge]][discord-url]
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/tribufu/proxmox-shar/blob/main/LICENSE.txt
+[discord-badge]: https://img.shields.io/discord/276504514616623104.svg?logo=discord&style=flat-square
+[discord-url]: https://www.tribufu.com/discord
+
+[Website](https://www.tribufu.com) |
+[Discord](https://www.tribufu.com/discord)
+
+## License
+
+This project is licensed under the [MIT License].
+
+[MIT License]: https://github.com/tribufu/proxmox-sharp/blob/main/LICENSE.txt
diff --git a/src/Tribufu.Proxmox.Tests/Program.cs b/src/Tribufu.Proxmox.Tests/Program.cs
new file mode 100644
index 0000000..8cb798a
--- /dev/null
+++ b/src/Tribufu.Proxmox.Tests/Program.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Tribufu. All Rights Reserved.
+// SPDX-License-Identifier: UNLICENSED
+
+using dotenv.net;
+
+namespace Tribufu.Proxmox.Tests
+{
+ public static class Program
+ {
+ public static async Task Main(string[] args)
+ {
+ DotEnv.Load(new DotEnvOptions(ignoreExceptions: true, envFilePaths: [".env", "../../.env"]));
+
+ var clusterUrl = Environment.GetEnvironmentVariable("PROXMOX_CLUSTER_URL");
+ var tokenId = Environment.GetEnvironmentVariable("PROXMOX_TOKEN_ID");
+ var tokenSecret = Environment.GetEnvironmentVariable("PROXMOX_TOKEN_SECRET");
+
+ var proxmox = new ProxmoxClient(clusterUrl, tokenId, tokenSecret);
+
+ var nodes = await proxmox.ListNodesAsync();
+ foreach (var node in nodes)
+ {
+ Console.WriteLine($"- {node.Name}");
+ }
+ }
+ }
+}
diff --git a/src/Tribufu.Proxmox.Tests/Tribufu.Proxmox.Tests.csproj b/src/Tribufu.Proxmox.Tests/Tribufu.Proxmox.Tests.csproj
new file mode 100644
index 0000000..f24d82e
--- /dev/null
+++ b/src/Tribufu.Proxmox.Tests/Tribufu.Proxmox.Tests.csproj
@@ -0,0 +1,14 @@
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/src/Tribufu.Proxmox/Interfaces/IProxmoxClient.cs b/src/Tribufu.Proxmox/Interfaces/IProxmoxClient.cs
new file mode 100644
index 0000000..cc05ad2
--- /dev/null
+++ b/src/Tribufu.Proxmox/Interfaces/IProxmoxClient.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Tribufu. All Rights Reserved.
+// SPDX-License-Identifier: MIT
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Tribufu.Proxmox.Models;
+
+namespace Tribufu.Proxmox.Interfaces
+{
+ public interface IProxmoxClient
+ {
+ Task LoginAsync(string username, string password);
+
+ Task> ListNodesAsync();
+
+ Task GetNodeStatusAsync(string node);
+
+ Task> ListVirtualMachinesAsync(string node);
+
+ Task GetVirtualMachineStatusAsync(string node, int vmid);
+
+ Task StartVirtualMachineAsync(string node, int vmid);
+
+ Task RebootVirtualMachineAsync(string node, int vmid);
+
+ Task ResetVirtualMachineAsync(string node, int vmid);
+
+ Task SuspendVirtualMachineAsync(string node, int vmid);
+
+ Task ResumeVirtualMachineAsync(string node, int vmid);
+
+ Task ShutdownVirtualMachineAsync(string node, int vmid);
+
+ Task StopVirtualMachineAsync(string node, int vmid);
+
+ Task> ListContainersAsync(string node);
+ }
+}
diff --git a/src/Tribufu.Proxmox/Models/ProxmoxBalloonInfo.cs b/src/Tribufu.Proxmox/Models/ProxmoxBalloonInfo.cs
new file mode 100644
index 0000000..c222377
--- /dev/null
+++ b/src/Tribufu.Proxmox/Models/ProxmoxBalloonInfo.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Tribufu. All Rights Reserved.
+// SPDX-License-Identifier: MIT
+
+using Newtonsoft.Json;
+
+namespace Tribufu.Proxmox.Models
+{
+ public class ProxmoxBalloonInfo
+ {
+ [JsonProperty("major_page_faults")]
+ public long MajorPageFaults { get; set; }
+
+ [JsonProperty("total_mem")]
+ public long TotalMem { get; set; }
+
+ [JsonProperty("mem_swapped_out")]
+ public long MemSwappedOut { get; set; }
+
+ [JsonProperty("minor_page_faults")]
+ public long MinorPageFaults { get; set; }
+
+ [JsonProperty("mem_swapped_in")]
+ public long MemSwappedIn { get; set; }
+
+ [JsonProperty("max_mem")]
+ public long MaxMem { get; set; }
+
+ [JsonProperty("last_update")]
+ public long LastUpdate { get; set; }
+
+ [JsonProperty("actual")]
+ public long Actual { get; set; }
+
+ [JsonProperty("free_mem")]
+ public long FreeMem { get; set; }
+ }
+}
diff --git a/src/Tribufu.Proxmox/Models/ProxmoxBlockStats.cs b/src/Tribufu.Proxmox/Models/ProxmoxBlockStats.cs
new file mode 100644
index 0000000..da9599d
--- /dev/null
+++ b/src/Tribufu.Proxmox/Models/ProxmoxBlockStats.cs
@@ -0,0 +1,107 @@
+// Copyright (c) Tribufu. All Rights Reserved.
+// SPDX-License-Identifier: MIT
+
+using Newtonsoft.Json;
+using System.Collections.Generic;
+
+namespace Tribufu.Proxmox.Models
+{
+ public class ProxmoxBlockStats
+ {
+ [JsonProperty("rd_operations")]
+ public long RdOperations { get; set; }
+
+ [JsonProperty("wr_total_time_ns")]
+ public long WrTotalTimeNs { get; set; }
+
+ [JsonProperty("wr_highest_offset")]
+ public long WrHighestOffset { get; set; }
+
+ [JsonProperty("flush_operations")]
+ public long FlushOperations { get; set; }
+
+ [JsonProperty("failed_zone_append_operations")]
+ public long FailedZoneAppendOperations { get; set; }
+
+ [JsonProperty("invalid_wr_operations")]
+ public long InvalidWrOperations { get; set; }
+
+ [JsonProperty("invalid_rd_operations")]
+ public long InvalidRdOperations { get; set; }
+
+ [JsonProperty("rd_bytes")]
+ public long RdBytes { get; set; }
+
+ [JsonProperty("invalid_zone_append_operations")]
+ public long InvalidZoneAppendOperations { get; set; }
+
+ [JsonProperty("account_invalid")]
+ public bool AccountInvalid { get; set; }
+
+ [JsonProperty("failed_rd_operations")]
+ public long FailedRdOperations { get; set; }
+
+ [JsonProperty("timed_stats")]
+ public List