Add automatic connection handling and Test-ProxmoxConnection cmdlet

This commit is contained in:
Alphaeus Mote
2025-05-09 12:57:29 -04:00
parent f906f41364
commit d0433ae21f
12 changed files with 471 additions and 51 deletions
@@ -108,9 +108,11 @@ namespace PSProxmox.Cmdlets
Realm,
this);
// Return the actual connection object instead of the connection info
// Store the connection in a global variable for automatic use by other cmdlets
SessionState.PSVariable.Set(new PSVariable("DefaultProxmoxConnection", connection, ScopedItemOptions.AllScope));
// Return the connection object
WriteObject(connection);
SessionState.PSVariable.Set(new PSVariable("ProxmoxConnection", connection, ScopedItemOptions.Private));
}
catch (Exception ex)
{
@@ -34,6 +34,18 @@ namespace PSProxmox.Cmdlets
}
ProxmoxSession.Logout(Connection, this);
// Clear the global connection variable if it matches the disconnected connection
var globalConnection = SessionState.PSVariable.GetValue("DefaultProxmoxConnection") as ProxmoxConnection;
if (globalConnection != null &&
globalConnection.Server == Connection.Server &&
globalConnection.Port == Connection.Port &&
globalConnection.Username == Connection.Username)
{
SessionState.PSVariable.Remove("DefaultProxmoxConnection");
WriteVerbose("Cleared default connection");
}
WriteVerbose($"Disconnected from {Connection.Server}");
}
catch (Exception ex)
+5 -8
View File
@@ -28,13 +28,8 @@ namespace PSProxmox.Cmdlets
/// </summary>
[Cmdlet(VerbsCommon.Get, "ProxmoxVM")]
[OutputType(typeof(ProxmoxVM), typeof(string))]
public class GetProxmoxVMCmdlet : PSCmdlet
public class GetProxmoxVMCmdlet : ProxmoxCmdlet
{
/// <summary>
/// <para type="description">The connection to the Proxmox VE server.</para>
/// </summary>
[Parameter(Mandatory = true, Position = 0)]
public ProxmoxConnection Connection { get; set; }
/// <summary>
/// <para type="description">The ID of the virtual machine to retrieve.</para>
@@ -61,7 +56,9 @@ namespace PSProxmox.Cmdlets
{
try
{
var client = new ProxmoxApiClient(Connection, this);
var connection = GetConnection();
ValidateConnection(connection);
var client = new ProxmoxApiClient(connection, this);
string response;
if (VMID.HasValue)
@@ -193,7 +190,7 @@ namespace PSProxmox.Cmdlets
}
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "GetProxmoxVMError", ErrorCategory.OperationStopped, Connection));
WriteError(new ErrorRecord(ex, "GetProxmoxVMError", ErrorCategory.OperationStopped, null));
}
}
}
+61
View File
@@ -0,0 +1,61 @@
using System;
using System.Management.Automation;
using PSProxmox.Session;
namespace PSProxmox.Cmdlets
{
/// <summary>
/// Base class for Proxmox cmdlets that provides common functionality.
/// </summary>
public abstract class ProxmoxCmdlet : PSCmdlet
{
/// <summary>
/// <para type="description">The connection to the Proxmox VE server. If not specified, the current connection will be used.</para>
/// </summary>
[Parameter(Mandatory = false, Position = 0)]
public ProxmoxConnection Connection { get; set; }
/// <summary>
/// Gets the connection to use for the cmdlet.
/// </summary>
/// <returns>The connection to use.</returns>
protected ProxmoxConnection GetConnection()
{
// Use the specified connection if provided
if (Connection != null)
{
return Connection;
}
// Otherwise, try to get the default connection
var defaultConnection = SessionState.PSVariable.GetValue("DefaultProxmoxConnection") as ProxmoxConnection;
if (defaultConnection == null)
{
throw new PSArgumentException(
"No connection specified and no default connection found. Use Connect-ProxmoxServer first.",
nameof(Connection));
}
return defaultConnection;
}
/// <summary>
/// Validates that the connection is authenticated.
/// </summary>
/// <param name="connection">The connection to validate.</param>
protected void ValidateConnection(ProxmoxConnection connection)
{
if (connection == null)
{
throw new PSArgumentNullException(nameof(connection));
}
if (!connection.IsAuthenticated)
{
throw new PSArgumentException(
"The connection is not authenticated. Use Connect-ProxmoxServer first.",
nameof(connection));
}
}
}
}
@@ -0,0 +1,113 @@
using System;
using System.Management.Automation;
using PSProxmox.Client;
using PSProxmox.Session;
namespace PSProxmox.Cmdlets
{
/// <summary>
/// <para type="synopsis">Tests a connection to a Proxmox VE server.</para>
/// <para type="description">The Test-ProxmoxConnection cmdlet tests if a connection to a Proxmox VE server is valid and active.</para>
/// <example>
/// <para>Test the current connection</para>
/// <code>Test-ProxmoxConnection</code>
/// </example>
/// <example>
/// <para>Test a specific connection</para>
/// <code>Test-ProxmoxConnection -Connection $connection</code>
/// </example>
/// </summary>
[Cmdlet(VerbsDiagnostic.Test, "ProxmoxConnection")]
[OutputType(typeof(bool))]
public class TestProxmoxConnectionCmdlet : PSCmdlet
{
/// <summary>
/// <para type="description">The connection to test. If not specified, the current connection will be used.</para>
/// </summary>
[Parameter(Mandatory = false, Position = 0, ValueFromPipeline = true)]
public ProxmoxConnection Connection { get; set; }
/// <summary>
/// <para type="description">Return detailed connection information instead of a boolean.</para>
/// </summary>
[Parameter(Mandatory = false)]
public SwitchParameter Detailed { get; set; }
/// <summary>
/// Processes the cmdlet.
/// </summary>
protected override void ProcessRecord()
{
try
{
// Get the connection from the global variable if not specified
if (Connection == null)
{
var globalConnection = SessionState.PSVariable.GetValue("DefaultProxmoxConnection") as ProxmoxConnection;
if (globalConnection == null)
{
WriteError(new ErrorRecord(
new Exception("No connection specified and no default connection found. Use Connect-ProxmoxServer first."),
"NoConnectionFound",
ErrorCategory.ConnectionError,
null));
return;
}
Connection = globalConnection;
}
// Test the connection by making a simple API call
try
{
var client = new ProxmoxApiClient(Connection, this);
string response = client.Get("version");
if (Detailed.IsPresent)
{
// Return detailed connection information
var connectionInfo = new PSObject();
connectionInfo.Properties.Add(new PSNoteProperty("Server", Connection.Server));
connectionInfo.Properties.Add(new PSNoteProperty("Port", Connection.Port));
connectionInfo.Properties.Add(new PSNoteProperty("Username", Connection.Username));
connectionInfo.Properties.Add(new PSNoteProperty("Realm", Connection.Realm));
connectionInfo.Properties.Add(new PSNoteProperty("UseSSL", Connection.UseSSL));
connectionInfo.Properties.Add(new PSNoteProperty("IsAuthenticated", Connection.IsAuthenticated));
connectionInfo.Properties.Add(new PSNoteProperty("Status", "Connected"));
WriteObject(connectionInfo);
}
else
{
// Return a simple boolean
WriteObject(true);
}
}
catch (Exception ex)
{
if (Detailed.IsPresent)
{
// Return detailed connection information with error
var connectionInfo = new PSObject();
connectionInfo.Properties.Add(new PSNoteProperty("Server", Connection.Server));
connectionInfo.Properties.Add(new PSNoteProperty("Port", Connection.Port));
connectionInfo.Properties.Add(new PSNoteProperty("Username", Connection.Username));
connectionInfo.Properties.Add(new PSNoteProperty("Realm", Connection.Realm));
connectionInfo.Properties.Add(new PSNoteProperty("UseSSL", Connection.UseSSL));
connectionInfo.Properties.Add(new PSNoteProperty("IsAuthenticated", Connection.IsAuthenticated));
connectionInfo.Properties.Add(new PSNoteProperty("Status", "Error"));
connectionInfo.Properties.Add(new PSNoteProperty("Error", ex.Message));
WriteObject(connectionInfo);
}
else
{
// Return a simple boolean
WriteObject(false);
}
}
}
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "TestProxmoxConnectionError", ErrorCategory.ConnectionError, Connection));
}
}
}
}
+9
View File
@@ -93,5 +93,14 @@ namespace PSProxmox.Session
};
return connection;
}
/// <summary>
/// Returns a string representation of the connection.
/// </summary>
/// <returns>A string representation of the connection.</returns>
public override string ToString()
{
return $"Proxmox Connection: {Username}@{Realm} on {Server}:{Port} ({(IsAuthenticated ? "Authenticated" : "Not Authenticated")})";
}
}
}