diff --git a/src/IDNT.AppBasics.Virtualization.Libvirt.csproj b/src/IDNT.AppBasics.Virtualization.Libvirt.csproj
index 6e51be3..ae95d23 100644
--- a/src/IDNT.AppBasics.Virtualization.Libvirt.csproj
+++ b/src/IDNT.AppBasics.Virtualization.Libvirt.csproj
@@ -1,6 +1,6 @@
- netstandard2;net47;net461;netcoreapp3.1
+ netstandard2;net47;net461;netcoreapp3.1;net9.0
IDNT.AppBasics.Virtualization.Libvirt
true
IDNT and the Livirt-dotnet contributors.
@@ -69,11 +69,12 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
- Always
+ Never
+ Never
diff --git a/src/Virtualization/Libvirt/LibvirtDomain.cs b/src/Virtualization/Libvirt/LibvirtDomain.cs
index 2b05ae2..878c43b 100644
--- a/src/Virtualization/Libvirt/LibvirtDomain.cs
+++ b/src/Virtualization/Libvirt/LibvirtDomain.cs
@@ -162,7 +162,7 @@ public void SetConsolePassword(string password)
case "qemu":
case "kvm":
string result = null;
- if (NativeVirQemu.MonitorCommand(_domainPtr, $"change vnc password \"{password}\"", ref result,
+ if (NativeVirQemu.MonitorCommand(_domainPtr, $"change vnc password \"{password}\"", out result,
VirDomainQemuMonitorCommandFlags.VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP) < 0)
throw new LibvirtException($"SetConsolePassword failed: {result}");
Trace.WriteLine($"set console output: '{result}'");
diff --git a/src/Virtualization/Libvirt/Native/NativeVirConnect.cs b/src/Virtualization/Libvirt/Native/NativeVirConnect.cs
index 73bcd6f..70dd3b8 100644
--- a/src/Virtualization/Libvirt/Native/NativeVirConnect.cs
+++ b/src/Virtualization/Libvirt/Native/NativeVirConnect.cs
@@ -570,6 +570,22 @@ public static extern int StoragePoolEventRegisterAny(IntPtr conn, IntPtr pool, i
[MarshalAs(UnmanagedType.FunctionPtr)] VirConnectStoragePoolGenericEventCallback cb,
IntPtr opaque, [MarshalAs(UnmanagedType.FunctionPtr)] VirFreeCallback ff);
+
+ ///
+ /// Adds a callback to receive notifications of graphics events.
+ ///
+ /// pointer to the connection
+ /// pointer to the domain or NULL for any
+ /// events to listen to
+ /// callback to the function handling domain events
+ /// opaque data to pass on to the callback
+ /// optional function to deallocate opaque when not used anymore
+ /// t shall take a reference to it, by calling virDomainRef. The reference can be released once the object is no longer required by calling virDomainFree. Returns 0 on success, -1 on failure
+ [DllImport("libvirt-0.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "virConnectDomainEventRegisterAny")]
+ public static extern int DomainEventGraphicsRegisterAny(IntPtr conn, IntPtr pool, VirDomainEventID eventId,
+ [MarshalAs(UnmanagedType.FunctionPtr)] VirConnectDomainEventGraphicsCallback cb,
+ IntPtr opaque, [MarshalAs(UnmanagedType.FunctionPtr)] VirFreeCallback ff);
+
///
/// Adds a callback to receive notifications of storage pool events.
///
diff --git a/src/Virtualization/Libvirt/Native/NativeVirDomain.cs b/src/Virtualization/Libvirt/Native/NativeVirDomain.cs
index a3162a9..b0b0501 100644
--- a/src/Virtualization/Libvirt/Native/NativeVirDomain.cs
+++ b/src/Virtualization/Libvirt/Native/NativeVirDomain.cs
@@ -744,6 +744,16 @@ public static int InterfaceStats(IntPtr dom, string path, out VirDomainInterface
[DllImport("libvirt-0.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "virDomainUndefine")]
public static extern int Undefine(IntPtr domain);
+ ///
+ /// Undefine a domain. If the domain is running, it's converted to transient domain, without stopping it. If the domain is inactive, the domain configuration is removed.
+ ///
+ /// pointer to a defined domain
+ /// an OR'ed set of virDomainUndefineFlags
+ /// 0 in case of success, -1 in case of error
+
+ [DllImport("libvirt-0.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "virDomainUndefineFlags")]
+ public static extern int UndefineFlags(IntPtr domain, VirDomainUndefineFlagsValues flags);
+
///
/// This function returns block device (disk) stats for block devices attached to the domain. The path parameter is the name of the block device. Get this by calling virDomainGetXMLDesc and finding the target dev='...' attribute within //domain/devices/disk. (For example, "xvda"). Domains may have more than one block device. To get stats for each you should make multiple calls to this function. Individual fields within the stats structure may be returned as -1, which indicates that the hypervisor does not support that particular statistic.
///
diff --git a/src/Virtualization/Libvirt/Native/NativeVirQemu.cs b/src/Virtualization/Libvirt/Native/NativeVirQemu.cs
index e2c74f2..97840fa 100644
--- a/src/Virtualization/Libvirt/Native/NativeVirQemu.cs
+++ b/src/Virtualization/Libvirt/Native/NativeVirQemu.cs
@@ -31,24 +31,34 @@ namespace IDNT.AppBasics.Virtualization.Libvirt.Native
///
/// class for libvirt qemu specific methods
///
- public class NativeVirQemu
+ public static class NativeVirQemu
{
- private const int MaxStringLength = 1024;
+ [DllImport("libvirt-qemu.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "virDomainQemuMonitorCommand")]
+ private static extern int virDomainQemuMonitorCommand(
+ IntPtr domain,
+ [MarshalAs(UnmanagedType.LPUTF8Str)] string cmd,
+ out IntPtr result,
+ VirDomainQemuMonitorCommandFlags flags);
- [DllImport("libvirt-qemu-0.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "virDomainQemuMonitorCommand")]
- private static extern int MonitorCommandImpl(IntPtr domain, string cmd, [Out] StringBuilder result, uint flags);
+ [DllImport("libvirt.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "virFree")]
+ private static extern int virFree(IntPtr ptr);
- public static int MonitorCommand(IntPtr domain, [MarshalAs(UnmanagedType.LPStr)]string cmd, ref string result, VirDomainQemuMonitorCommandFlags flags)
+ public static int MonitorCommand(IntPtr domain, string cmd, out string result, VirDomainQemuMonitorCommandFlags flags)
{
- var sb = new StringBuilder();
- //IntPtr buf = Marshal.AllocCoTaskMem(MaxStringLength + 1);
- //Marshal.WriteByte(buf, MaxStringLength, 0);
- //IntPtr buf2 = buf;
- int ret = MonitorCommandImpl(domain, cmd, sb, (uint)flags);
- if (ret == 0)
- result = sb.ToString();
- //result = MarshalHelper.ptrToString(buf);
- //Marshal.FreeCoTaskMem(buf);
+ IntPtr resultPtr;
+ int ret = virDomainQemuMonitorCommand(domain, cmd, out resultPtr, flags);
+
+ if (ret < 0 || resultPtr == IntPtr.Zero)
+ {
+ result = null;
+ return ret;
+ }
+
+ result = Marshal.PtrToStringUTF8(resultPtr);
+
+ // Free memory allocated by libvirt
+ NativeFunctions.Free(resultPtr);
+
return ret;
}
}
diff --git a/src/Virtualization/Libvirt/Native/VirConnectDomainEventCallback.cs b/src/Virtualization/Libvirt/Native/VirConnectDomainEventCallback.cs
index 1e81b98..8486665 100644
--- a/src/Virtualization/Libvirt/Native/VirConnectDomainEventCallback.cs
+++ b/src/Virtualization/Libvirt/Native/VirConnectDomainEventCallback.cs
@@ -39,4 +39,23 @@ namespace IDNT.AppBasics.Virtualization.Libvirt.Native
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void VirConnectDomainEventCallback(IntPtr conn, IntPtr dom, [MarshalAs(UnmanagedType.I4)] VirDomainEventType evt, int detail, IntPtr opaque);
+
+ ///
+ /// The callback signature to use when registering for an event of type VIR_DOMAIN_EVENT_ID_GRAPHICS with virConnectDomainEventRegisterAny()
+ ///
+ /// virConnect connection
+ /// The domain on which the event occured
+ /// The specific phase of the graphics event
+ /// Local address information
+ /// Remote address information
+ /// Authentication scheme used
+ /// Subject of the event
+ /// Opaque user data
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void VirConnectDomainEventGraphicsCallback(IntPtr conn, IntPtr dom, VirDomainEventGraphicsPhase phase,
+ ref VirDomainEventGraphicsAddress local,
+ ref VirDomainEventGraphicsAddress remote,
+ [MarshalAs(UnmanagedType.LPStr)] string authScheme,
+ ref VirDomainEventGraphicsSubject subject,
+ IntPtr opaque);
}
diff --git a/src/Virtualization/Libvirt/Native/VirDomainEventGraphicsPhase.cs b/src/Virtualization/Libvirt/Native/VirDomainEventGraphicsPhase.cs
new file mode 100644
index 0000000..030fb8a
--- /dev/null
+++ b/src/Virtualization/Libvirt/Native/VirDomainEventGraphicsPhase.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+
+namespace IDNT.AppBasics.Virtualization.Libvirt.Native
+{
+ public enum VirDomainEventGraphicsPhase
+ {
+
+ ///
+ /// Initial socket connection established
+ ///
+ VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
+
+ ///
+ /// Authentication & setup completed
+ ///
+ VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE = 1,
+ ///
+ /// Client disconnected
+ ///
+ VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT = 2,
+ ///
+ /// Final socket disconnection
+ ///
+ VIR_DOMAIN_EVENT_GRAPHICS_LAST = 3
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct VirDomainEventGraphicsAddress
+ {
+ public int family;
+
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string node;
+
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string service;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct VirDomainEventGraphicsSubjectIdentity
+ {
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string type;
+
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string name;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct VirDomainEventGraphicsSubject
+ {
+ public int nidentity;
+ public IntPtr identities; // pointer to virDomainEventGraphicsSubjectIdentity
+ }
+}
\ No newline at end of file
diff --git a/src/Virtualization/Libvirt/Native/virDomainUndefineFlagsValues.cs b/src/Virtualization/Libvirt/Native/virDomainUndefineFlagsValues.cs
new file mode 100644
index 0000000..848518c
--- /dev/null
+++ b/src/Virtualization/Libvirt/Native/virDomainUndefineFlagsValues.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace IDNT.AppBasics.Virtualization.Libvirt.Native
+{
+ ///
+ /// VirDomainUndefineFlagsValues
+ ///
+ [Flags]
+ public enum VirDomainUndefineFlagsValues
+ {
+ ///
+ /// Also remove any managed save
+ ///
+ VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1,
+
+ ///
+ /// If last use of domain, then also remove any snapshot metadata
+ ///
+ VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = 2,
+ ///
+ /// Also remove any nvram file
+ ///
+ VIR_DOMAIN_UNDEFINE_NVRAM = 4,
+ ///
+ /// Keep nvram file
+ ///
+ VIR_DOMAIN_UNDEFINE_KEEP_NVRAM = 8,
+ ///
+ /// If last use of domain, then also remove any checkpoint metadata
+ ///
+ VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA = 16,
+ ///
+ /// Also remove any TPM state
+ ///
+ VIR_DOMAIN_UNDEFINE_TPM = 32,
+ ///
+ /// Keep TPM state Future undefine control flags should come here.
+ ///
+ VIR_DOMAIN_UNDEFINE_KEEP_TPM = 64,
+
+ }
+}
\ No newline at end of file