diff --git a/server/src/libvirt-c.zig b/server/src/libvirt-c.zig new file mode 100644 index 0000000..ff0aad8 --- /dev/null +++ b/server/src/libvirt-c.zig @@ -0,0 +1,7 @@ +pub const c = @cImport({ + @cInclude("libvirt/libvirt.h"); + @cInclude("libvirt/libvirt-admin.h"); + @cInclude("libvirt/libvirt-lxc.h"); + @cInclude("libvirt/libvirt-qemu.h"); + @cInclude("libvirt/virterror.h"); +}); diff --git a/server/src/libvirt-connection.zig b/server/src/libvirt-connection.zig new file mode 100644 index 0000000..168aeaa --- /dev/null +++ b/server/src/libvirt-connection.zig @@ -0,0 +1,90 @@ +const std = @import("std"); +const mem = std.mem; +const heap = std.heap; + +const c = @import("libvirt-c.zig").c; + +ptr: c.virConnectPtr, +allocator: mem.Allocator, + +pub fn connect(uri: []const u8, allocator: mem.Allocator) VirError!Connection { + const connection = c.virConnectOpenAuth(@ptrCast(uri), c.virConnectAuthPtrDefault, 0); + if (connection) |conn| return .{ + .ptr = conn, + .allocator = allocator, + } else return handleError(); +} + +pub fn close(self: *const Connection) void { + _ = c.virConnectClose(self.ptr); +} + +// pub fn getURI(self: *const Connection) ![]u8 { +// const uri = c.virConnectGetURI(self.ptr); +// defer std.c.free(uri); +// const str = string(uri); +// return if (str.len == 0) handleError() else try self.allocator.dupe(u8, str); +// } +// pub fn freeURI(self: *const Connection, uri: []u8) void { +// self.allocator.free(uri); +// } + +// pub fn numOfPools(self: *const Connection) !u32 { +// return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfStoragePools); +// } +// pub fn numOfDefinedPools(self: *const Connection) !u32 { +// return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfDefinedStoragePools); +// } + +// pub fn iteratePools(self: *const Connection, flags: []const Pool.ListFlags) !Pool.PoolIterator { +// return Pool.PoolIterator.init( +// c.virConnect, +// Connection, +// Pool.ListFlags, +// self, +// flags, +// self.allocator, +// c.virConnectListAllStoragePools, +// ); +// } + +// pub fn createPool(self: *const Connection, xml: String, flags: []const Pool.CreateFlags) !Pool { +// const pool = c.virStoragePoolCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Pool.CreateFlags, flags)); +// return if (pool) |p| Pool.init(p, self.allocator) else handleError(); +// } +// pub fn definePoolFlags(self: *const Connection, xml: String, flags: []const Pool.DefineFlags) !Pool { +// const pool = c.virStoragePoolCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Pool.DefineFlags, flags)); +// return if (pool) |p| Pool.init(p, self.allocator) else handleError(); +// } + +// pub fn numOfDomains(self: *const Connection) !u32 { +// return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfDomains); +// } +// pub fn numOfDefinedDomains(self: *const Connection) !u32 { +// return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfDefinedDomains); +// } + +// pub fn iterateDomains(self: *const Connection, flags: []const Domain.ListFlags) !Domain.DomainIterator { +// return Domain.DomainIterator.init( +// c.virConnect, +// Connection, +// Domain.ListFlags, +// self, +// flags, +// self.allocator, +// c.virConnectListAllDomains, +// ); +// } + +// pub fn createDomain(self: *const Connection, xml: String, flags: []const Domain.CreateFlags) !Domain { +// const domain = c.virDomainCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Domain.CreateFlags, flags)); +// return if (domain) |d| Domain.init(d, self.allocator) else handleError(); +// } +// pub fn defineDomain(self: *const Connection, xml: String) !Domain { +// const domain = c.virDomainDefineXML(self.ptr, @ptrCast(xml.str)); +// return if (domain) |d| Domain.init(d, self.allocator) else handleError(); +// } +// pub fn defineDomainFlags(self: *const Connection, xml: String, flags: []const Domain.DefineFlags) !Domain { +// const domain = c.virDomainDefineXMLFlags(self.ptr, @ptrCast(xml.str), intFromFlags(Domain.DefineFlags, flags)); +// return if (domain) |d| Domain.init(d, self.allocator) else handleError(); +// } diff --git a/server/src/libvirt-domain.zig b/server/src/libvirt-domain.zig new file mode 100644 index 0000000..1afe22a --- /dev/null +++ b/server/src/libvirt-domain.zig @@ -0,0 +1,268 @@ +const std = @import("std"); +const mem = std.mem; +const heap = std.heap; + +const h = @import("libvirt-helper.zig"); +const c = @import("libvirt-c.zig").c; +const err = @import("libvirt-error.zig"); +const Connection = @import("libvirt-connection.zig"); +const VirError = err.VirError; +const Domain = @This(); + +ptr: c.virDomainPtr, +arena: *heap.ArenaAllocator, + +pub fn init(ptr: c.virDomainPtr, allocator: mem.Allocator) Domain { + var arena = heap.ArenaAllocator.init(allocator); + return .{ + .ptr = ptr, + .arena = &arena, + }; +} +pub fn deinit(self: *const Domain) void { + self.arena.deinit(); +} + +// TODO event handling callbacks + +pub fn xmlFromNative() void {} +pub fn xmlToNative() void {} +pub fn getAllDomainStats() void {} +pub fn getDomainCapabilities() void {} +pub fn listAllDomains() void {} +pub fn listDefinedDomains() void {} +pub fn listDomains() void {} +pub fn numOfDefinedDomains() void {} +pub fn numOfDomains() void {} + +pub fn abortJob() void {} +pub fn abortJobFlags() void {} +pub fn addIOThread() void {} +pub fn agentSetResponseTimeout() void {} +pub fn attachDevice() void {} +pub fn attachDeviceFlags() void {} +pub fn authorizedSSHKeysSet() void {} +pub fn backupBegin() void {} +pub fn backupGetXMLDesc() void {} +pub fn blockCommit() void {} +pub fn blockCopy() void {} +pub fn blockJobAbort() void {} +pub fn blockJobSetSpeed() void {} +pub fn blockPeek() void {} +pub fn blockPull() void {} +pub fn blockRebase() void {} +pub fn blockResize() void {} +pub fn blockStats() void {} +pub fn blockStatsFlags() void {} +pub fn coreDump() void {} +pub fn coreDumpWithFormat() void {} + +pub fn create() void {} +pub fn createLinux() void {} +pub fn createWithFiles() void {} +pub fn createWithFlags() void {} +pub fn createXML() void {} +pub fn createXMLWithFiles() void {} +pub fn defineXML() void {} +pub fn defineXMLFlags() void {} +pub fn delIOThread() void {} +pub fn destroy() void {} +pub fn destroyFlags() void {} +pub fn detachDevice() void {} +pub fn detachDeviceAlias() void {} +pub fn detachDeviceFlags() void {} +pub fn fdAssociate() void {} +pub fn fsFreeze() void {} +pub fn fsInfoFree() void {} +pub fn fsThaw() void {} +pub fn fsTrim() void {} +pub fn free(self: *const Domain) VirError!void { + if (c.virDomainFree(self.ptr) < 0) return err.handleError(); +} + +pub fn getAutostart() void {} +pub fn getBlkioParameters() void {} +pub fn getBlockInfo() void {} +pub fn getBlockIoTune() void {} +pub fn getBlockJobInfo() void {} +pub fn getCPUStats() void {} +pub fn getConnect() void {} +pub fn getControlInfo() void {} +pub fn getDiskErrors() void {} +pub fn getEmulatorPinInfo() void {} +pub fn getFSInfo() void {} +pub fn getGuestInfo() void {} +pub fn getGuestVcpus() void {} +pub fn getHostname() void {} +pub fn getID() void {} +pub fn getIOThreadInfo() void {} +pub fn getInfo() void {} +pub fn getInterfaceParameters() void {} +pub fn getJobInfo() void {} +pub fn getJobStats() void {} +pub fn getLaunchSecurityInfo() void {} +pub fn getMaxMemory() void {} +pub fn getMaxVcpus() void {} +pub fn getMemoryParameters() void {} +pub fn getMessages() void {} +pub fn getMetadata() void {} +pub fn getName(self: *const Domain) VirError![]const u8 { + const name = c.virDomainGetName(self.ptr); + const str = h.string(name); + return if (str.len == 0) err.handleError() else str; +} +pub fn getNumaParameters() void {} +pub fn getOSType() void {} +pub fn getPerfEvents() void {} +pub fn getSchedulerParameters() void {} +pub fn getSchedulerParametersFlags() void {} +pub fn getSchedulerType() void {} +pub fn getSecurityLabel() void {} +pub fn getSecurityLabelList() void {} +pub fn getState() void {} +pub fn getTime() void {} +pub fn getUUID() void {} +pub fn getUUIDString() void {} +pub fn getVcpuPinInfo() void {} +pub fn getVcpus() void {} +pub fn getVpusFlags() void {} +pub fn getXMLDesc() void {} + +pub fn graphicsReload() void {} +pub fn hasManagedSaveImage() void {} +pub fn ioThreadInfoFree() void {} +pub fn injectNMI() void {} +pub fn interfaceAddresses() void {} +pub fn interfaceFree() void {} +pub fn interfaceStats() void {} + +pub fn isActive(self: *const Domain) void { + const active = c.virDomainIsActive(self.ptr); + return if (active == 0) false else true; +} +pub fn isPersistent() void {} +pub fn isUpdated() void {} +pub fn listGetStats() void {} +pub fn lookupByID() void {} +pub fn lookupByUUID() void {} +pub fn lookupByUUIDString() void {} + +pub fn managedSave() void {} +pub fn managedSaveDefineXML() void {} +pub fn managedSaveGetXMLDesc() void {} +pub fn managedSaveRemove() void {} +pub fn memoryPeek() void {} +pub fn memoryStats() void {} + +// TODO virDomainMigrate* + +pub fn openChannel() void {} +pub fn openConsole() void {} +pub fn openGraphics() void {} +pub fn openGraphicsFD() void {} +pub fn pmSuspendForDuration() void {} +pub fn pmWakeup() void {} +pub fn pinEmulator() void {} +pub fn pinIOThread() void {} +pub fn pinVcpu() void {} +pub fn pinVcpuFlags() void {} + +pub fn reboot() void {} +pub fn ref(self: *const Domain) VirError!void { + if (c.virDomainRef(self.ptr) < 0) return err.handleError(); +} +pub fn rename() void {} +pub fn reset() void {} +pub fn restore() void {} +pub fn restoreFlags() void {} +pub fn restoreParams() void {} +pub fn @"resume"() void {} +pub fn save() void {} +pub fn saveFlags() void {} +pub fn saveImageDefineXML() void {} +pub fn saveImageGetXMLDesc() void {} +pub fn saveParams() void {} +pub fn screenshot() void {} +pub fn sendKey() void {} +pub fn sendProcessSignal() void {} + +pub fn setAutostart() void {} +pub fn setBlkioParameters() void {} +pub fn setBlockIoTune() void {} +pub fn setBlockThreshold() void {} +pub fn setGuestVcpus() void {} +pub fn setIOThreadParams() void {} +pub fn setInterfaceParameters() void {} +pub fn setLaunchSecurityState() void {} +pub fn setLifecycleAction() void {} +pub fn setMaxMemory() void {} +pub fn setMemory() void {} +pub fn setMemoryFlags() void {} +pub fn setMemoryParameters() void {} +pub fn setMemoryStatsPeriod() void {} +pub fn setMetadata() void {} +pub fn setNumaParameters() void {} +pub fn setPerfEvents() void {} +pub fn setSchedulerParameters() void {} +pub fn setSchedulerParametersFlags() void {} +pub fn setTime() void {} +pub fn setUserPassword() void {} +pub fn setVcpu() void {} +pub fn setVcpus() void {} +pub fn setVpusFlags() void {} + +pub fn shutdown() void {} +pub fn @"suspend"() void {} +pub fn undefine() void {} +pub fn undefineFlags() void {} +pub fn updateDeviceFlags() void {} + +pub const ListFlags = enum(c_uint) { + Active = c.VIR_CONNECT_LIST_DOMAINS_ACTIVE, + Inactive = c.VIR_CONNECT_LIST_DOMAINS_INACTIVE, +}; +pub const AbortJobFlagsValues = enum(c_uint) {}; +pub const AgentResponseTimeoutValues = enum(c_uint) {}; +pub const AuthorizedSSHKeysSetFlags = enum(c_uint) {}; +pub const BackupBeginFlags = enum(c_uint) {}; +pub const BlockCommitFlags = enum(c_uint) {}; +pub const BlockCopyFlags = enum(c_uint) {}; +pub const BlockJobAbortFlags = enum(c_uint) {}; +pub const BlockJobInfoFlags = enum(c_uint) {}; +pub const BlockJobSetSpeedFlags = enum(c_uint) {}; +pub const BlockPullFlags = enum(c_uint) {}; +pub const BlockRebaseFlags = enum(c_uint) {}; +pub const BlockResizeFlags = enum(c_uint) {}; +pub const ChannelFlags = enum(c_uint) {}; +pub const ConsoleFlags = enum(c_uint) {}; +pub const CoreDumpFlags = enum(c_uint) {}; +pub const CreateFlags = enum(c_uint) { + None = c.VIR_DOMAIN_NONE, + StartPaused = c.VIR_DOMAIN_START_PAUSED, + StartAutodestroy = c.VIR_DOMAIN_START_AUTODESTROY, + StartBypassCache = c.VIR_DOMAIN_START_BYPASS_CACHE, + StartForceBoot = c.VIR_DOMAIN_START_FORCE_BOOT, + StartValidate = c.VIR_DOMAIN_START_VALIDATE, + StartResetNvram = c.VIR_DOMAIN_START_RESET_NVRAM, +}; +pub const DefineFlags = enum(c_uint) { + Validate = c.VIR_DOMAIN_DEFINE_VALIDATE, +}; +// TODO rest + +pub const BlockInfo = struct {}; +pub const BlockJobCursor = u64; +pub const BlockJobInfo = struct {}; +pub const BlockStats = struct {}; +pub const ControlInfo = struct {}; +// TODO rest + +pub const BlockJobType = enum(c_uint) {}; +pub const BlockedReason = enum(c_uint) {}; +pub const ControlErrorReason = enum(c_uint) {}; +pub const ControlState = enum(c_uint) {}; +pub const CoreDumpFormat = enum(c_uint) {}; +pub const CrashedReason = enum(c_uint) {}; +// TODO rest + +// pub const DomainIterator = Iterator(Domain, c.virDomainPtr, c.virDomainFree); diff --git a/server/src/libvirt-error.zig b/server/src/libvirt-error.zig new file mode 100644 index 0000000..b35bb3e --- /dev/null +++ b/server/src/libvirt-error.zig @@ -0,0 +1,232 @@ +const std = @import("std"); + +const c = @import("libvirt-c.zig").c; + +fn handleError() VirError { + const err = c.virGetLastError(); + // std.debug.print("err: {any}\n", .{err}); + return switch (err.*.code) { + c.VIR_ERR_OK => VirError.OK, + c.VIR_ERR_INTERNAL_ERROR => VirError.InternalError, + c.VIR_ERR_NO_MEMORY => VirError.NoMemory, + c.VIR_ERR_NO_SUPPORT => VirError.NoSupport, + c.VIR_ERR_UNKNOWN_HOST => VirError.UnknownHost, + c.VIR_ERR_NO_CONNECT => VirError.NoConnect, + c.VIR_ERR_INVALID_CONN => VirError.InvalidConn, + c.VIR_ERR_INVALID_DOMAIN => VirError.InvalidDomain, + c.VIR_ERR_INVALID_ARG => VirError.InvalidArg, + c.VIR_ERR_OPERATION_FAILED => VirError.OperationFailed, + c.VIR_ERR_GET_FAILED => VirError.GetFailed, + c.VIR_ERR_POST_FAILED => VirError.PostFailed, + c.VIR_ERR_HTTP_ERROR => VirError.HttpError, + c.VIR_ERR_SEXPR_SERIAL => VirError.SexprSerial, + c.VIR_ERR_NO_XEN => VirError.NoXen, + c.VIR_ERR_XEN_CALL => VirError.XenCall, + c.VIR_ERR_OS_TYPE => VirError.OsType, + c.VIR_ERR_NO_KERNEL => VirError.NoKernel, + c.VIR_ERR_NO_ROOT => VirError.NoRoot, + c.VIR_ERR_NO_TARGET => VirError.NoTarget, + c.VIR_ERR_NO_NAME => VirError.NoName, + c.VIR_ERR_NO_OS => VirError.NoOs, + c.VIR_ERR_NO_DEVICE => VirError.NoDevice, + c.VIR_ERR_DRIVER_FULL => VirError.DriverFull, + c.VIR_ERR_CALL_FAILED => VirError.CallFailed, + c.VIR_ERR_XML_ERROR => VirError.XmlError, + c.VIR_ERR_DOM_EXIST => VirError.DomExist, + c.VIR_ERR_OPERATION_DENIED => VirError.OperationDenied, + c.VIR_ERR_OPEN_FAILED => VirError.OpenFailed, + c.VIR_ERR_READ_FAILED => VirError.ReadFailed, + c.VIR_ERR_PARSE_FAILED => VirError.ParseFailed, + c.VIR_ERR_CONF_SYNTAX => VirError.ConfSyntax, + c.VIR_ERR_WRITE_FAILED => VirError.WriteFailed, + c.VIR_ERR_XML_DETAIL => VirError.XmlDetail, + c.VIR_ERR_INVALID_NETWORK => VirError.InvalidNetwork, + c.VIR_ERR_NETWORK_EXIST => VirError.NetworkExist, + c.VIR_ERR_SYSTEM_ERROR => VirError.SystemError, + c.VIR_ERR_RPC => VirError.Rpc, + c.VIR_ERR_GNUTLS_ERROR => VirError.GnutlsError, + c.VIR_WAR_NO_NETWORK => VirError.WarNoNetwork, // ??? + c.VIR_ERR_NO_DOMAIN => VirError.NoDomain, + c.VIR_ERR_NO_NETWORK => VirError.NoNetwork, + c.VIR_ERR_INVALID_MAC => VirError.InvalidMac, + c.VIR_ERR_AUTH_FAILED => VirError.AuthFailed, + c.VIR_ERR_INVALID_STORAGE_POOL => VirError.InvalidStoragePool, + c.VIR_ERR_INVALID_STORAGE_VOL => VirError.InvalidStorageVol, + c.VIR_WAR_NO_STORAGE => VirError.WarNoStorage, // ??? + c.VIR_ERR_NO_STORAGE_POOL => VirError.NoStoragePool, + c.VIR_ERR_NO_STORAGE_VOL => VirError.NoStorageVol, + c.VIR_WAR_NO_NODE => VirError.WarNoNode, // ??? + c.VIR_ERR_INVALID_NODE_DEVICE => VirError.InvalidNodeDevice, + c.VIR_ERR_NO_NODE_DEVICE => VirError.NoNodeDevice, + c.VIR_ERR_NO_SECURITY_MODEL => VirError.NoSecurityModel, + c.VIR_ERR_OPERATION_INVALID => VirError.OperationInvalid, + c.VIR_WAR_NO_INTERFACE => VirError.WarNoInterface, // ??? + c.VIR_ERR_NO_INTERFACE => VirError.NoInterface, + c.VIR_ERR_INVALID_INTERFACE => VirError.InvalidInterface, + c.VIR_ERR_MULTIPLE_INTERFACES => VirError.MultipleInterfaces, + c.VIR_WAR_NO_NWFILTER => VirError.WarNoNwfilter, // ??? + c.VIR_ERR_INVALID_NWFILTER => VirError.InvalidNwfilter, + c.VIR_ERR_BUILD_FIREWALL => VirError.BuildFirewall, + c.VIR_WAR_NO_SECRET => VirError.WarNoSecret, // ??? + c.VIR_ERR_INVALID_SECRET => VirError.InvalidSecret, + c.VIR_ERR_CONFIG_UNSUPPORTED => VirError.ConfigUnsupported, + c.VIR_ERR_OPERATION_TIMEOUT => VirError.OperationTimeout, + c.VIR_ERR_MIGRATE_PERSIST_FAILED => VirError.MigratePersistFailed, + c.VIR_ERR_HOOK_SCRIPT_FAILED => VirError.HookScriptFailed, + c.VIR_ERR_INVALID_DOMAIN_SNAPSHOT => VirError.InvalidDomainSnapshot, + c.VIR_ERR_NO_DOMAIN_SNAPSHOT => VirError.NoDomainSnapshot, + c.VIR_ERR_INVALID_STREAM => VirError.InvalidStream, + c.VIR_ERR_ARGUMENT_UNSUPPORTED => VirError.ArgumentUnsupported, + c.VIR_ERR_STORAGE_PROBE_FAILED => VirError.StorageProbeFailed, + c.VIR_ERR_STORAGE_POOL_BUILT => VirError.StoragePoolBuilt, + c.VIR_ERR_SNAPSHOT_REVERT_RISKY => VirError.SnapshotReverRisky, + c.VIR_ERR_OPERATION_ABORTED => VirError.OperationAborted, + c.VIR_ERR_AUTH_CANCELLED => VirError.AuthCancelled, + c.VIR_ERR_NO_DOMAIN_METADATA => VirError.NoDomainMetadata, + c.VIR_ERR_MIGRATE_UNSAFE => VirError.MigrateUnsafe, + c.VIR_ERR_OVERFLOW => VirError.Overflow, + c.VIR_ERR_BLOCK_COPY_ACTIVE => VirError.BlockCopyActive, + c.VIR_ERR_OPERATION_UNSUPPORTED => VirError.OperationUnsupported, + c.VIR_ERR_SSH => VirError.Ssh, + c.VIR_ERR_AGENT_UNRESPONSIVE => VirError.AgentUnresponsive, + c.VIR_ERR_RESOURCE_BUSY => VirError.ResourceBusy, + c.VIR_ERR_ACCESS_DENIED => VirError.AccessDenied, + c.VIR_ERR_DBUS_SERVICE => VirError.DbusService, + c.VIR_ERR_STORAGE_VOL_EXIST => VirError.StorageVolExist, + c.VIR_ERR_CPU_INCOMPATIBLE => VirError.CpuIncompatible, + c.VIR_ERR_XML_INVALID_SCHEMA => VirError.XmlInvalidSchema, + c.VIR_ERR_MIGRATE_FINISH_OK => VirError.MigrateFinishOk, + c.VIR_ERR_AUTH_UNAVAILABLE => VirError.AuthUnavailable, + c.VIR_ERR_NO_SERVER => VirError.NoServer, + c.VIR_ERR_NO_CLIENT => VirError.NoClient, + c.VIR_ERR_AGENT_UNSYNCED => VirError.AgentUnsynced, + c.VIR_ERR_LIBSSH => VirError.Libssh, + c.VIR_ERR_DEVICE_MISSING => VirError.DeviceMissing, + c.VIR_ERR_INVALID_NWFILTER_BINDING => VirError.InvalidNwfilterBinding, + c.VIR_ERR_NO_NWFILTER_BINDING => VirError.NoNwfilterBinding, + c.VIR_ERR_INVALID_DOMAIN_CHECKPOINT => VirError.InvalidDomainCheckpoint, + c.VIR_ERR_NO_DOMAIN_CHECKPOINT => VirError.NoDomainCheckpoint, + c.VIR_ERR_NO_DOMAIN_BACKUP => VirError.NoDomainBackup, + c.VIR_ERR_INVALID_NETWORK_PORT => VirError.InvalidNetworkPort, + c.VIR_ERR_NETWORK_PORT_EXIST => VirError.NetworkPortExist, + c.VIR_ERR_NO_NETWORK_PORT => VirError.NoNetworkPort, + c.VIR_ERR_NO_HOSTNAME => VirError.NoHostname, + c.VIR_ERR_CHECKPOINT_INCONSISTENT => VirError.CheckpointInconsistent, + c.VIR_ERR_MULTIPLE_DOMAINS => VirError.MultipleDomains, + c.VIR_ERR_NO_NETWORK_METADATA => VirError.NoNetworkMetadata, + else => VirError.OK, + }; +} + +pub const VirError = error{ + OK, + InternalError, + NoMemory, + NoSupport, + UnknownHost, + NoConnect, + InvalidConn, + InvalidDomain, + InvalidArg, + OperationFailed, + GetFailed, + PostFailed, + HttpError, + SexprSerial, + NoXen, + XenCall, + OsType, + NoKernel, + NoRoot, + NoSource, + NoTarget, + NoName, + NoOs, + NoDevice, + NoXenstore, + DriverFull, + CallFailed, + XmlError, + DomExist, + OperationDenied, + OpenFailed, + ReadFailed, + ParseFailed, + ConfSyntax, + WriteFailed, + XmlDetail, + InvalidNetwork, + NetworkExist, + SystemError, + Rpc, + GnutlsError, + WarNoNetwork, // ??? + NoDomain, + NoNetwork, + InvalidMac, + AuthFailed, + InvalidStoragePool, + InvalidStorageVol, + WarNoStorage, // ??? + NoStoragePool, + NoStorageVol, + WarNoNode, // ??? + InvalidNodeDevice, + NoNodeDevice, + NoSecurityModel, + OperationInvalid, + WarNoInterface, // ??? + NoInterface, + InvalidInterface, + MultipleInterfaces, + WarNoNwfilter, // ??? + InvalidNwfilter, + BuildFirewall, + WarNoSecret, // ??? + InvalidSecret, + ConfigUnsupported, + OperationTimeout, + MigratePersistFailed, + HookScriptFailed, + InvalidDomainSnapshot, + NoDomainSnapshot, + InvalidStream, + ArgumentUnsupported, + StorageProbeFailed, + StoragePoolBuilt, + SnapshotReverRisky, + OperationAborted, + AuthCancelled, + NoDomainMetadata, + MigrateUnsafe, + Overflow, + BlockCopyActive, + OperationUnsupported, + Ssh, + AgentUnresponsive, + ResourceBusy, + AccessDenied, + DbusService, + StorageVolExist, + CpuIncompatible, + XmlInvalidSchema, + MigrateFinishOk, + AuthUnavailable, + NoServer, + NoClient, + AgentUnsynced, + Libssh, + DeviceMissing, + InvalidNwfilterBinding, + NoNwfilterBinding, + InvalidDomainCheckpoint, + NoDomainCheckpoint, + NoDomainBackup, + InvalidNetworkPort, + NetworkPortExist, + NoNetworkPort, + NoHostname, + CheckpointInconsistent, + MultipleDomains, + NoNetworkMetadata, +}; diff --git a/server/src/libvirt-helper.zig b/server/src/libvirt-helper.zig new file mode 100644 index 0000000..256ed0c --- /dev/null +++ b/server/src/libvirt-helper.zig @@ -0,0 +1,89 @@ +const std = @import("std"); +const mem = std.mem; + +const err = @import("libvirt-error.zig"); + +// Helper struct for allocating null-terminated strings +pub const String = struct { + allocator: mem.Allocator, + slice: []u8, + str: [:0]const u8, + + pub fn init(allocator: mem.Allocator, in_str: []const u8) !String { + const str = try allocator.alloc(u8, in_str.len + 1); + @memcpy(str[0..in_str.len], in_str); + str[str.len - 1] = 0; + return .{ + .allocator = allocator, + .slice = str, + .str = @ptrCast(str), + }; + } + pub fn deinit(self: *const String) void { + self.allocator.free(self.slice); + } +}; + +fn string(str: [*c]const u8) []const u8 { + return mem.span(str); +} + +fn intFromFlags(comptime T: type, flags: []const T) c_uint { + var flags_int: c_uint = 0; + for (flags) |f| flags_int |= @intFromEnum(f); + return flags_int; +} + +fn Iterator(comptime T: type, comptime Ptr: type, comptime freeFn: *const fn (Ptr) callconv(.C) c_int) type { + return struct { + allocator: mem.Allocator, + list: [*]Ptr, + num: c_int, + curr: usize, + + pub fn init( + comptime PP: type, // Parent Pointer + comptime P: type, // Parent + comptime F: type, // Flags + parent: *const P, + flags: []const F, + allocator: mem.Allocator, + initFn: *const fn (?*PP, [*c][*c]Ptr, c_uint) callconv(.C) c_int, + ) !Self { + var list: [*]Ptr = undefined; + const num = initFn(parent.ptr, @ptrCast(&list), intFromFlags(F, flags)); + return if (num < 0) err.handleError() else .{ + .allocator = allocator, + .list = list, + .num = num, + .curr = 0, + }; + } + pub fn deinit(self: *Self) void { + var i: usize = 0; + while (i < self.num) : (i += 1) _ = freeFn(self.list[i]); + } + pub fn first(self: *Self) T { + self.curr = 0; + // return .{ .ptr = self.list[self.curr], .arena = heap.ArenaAllocator.init(self.allocator) }; + return T.init(self.list[self.curr], self.allocator); + } + pub fn next(self: *Self) ?T { + if (self.curr >= self.num) return null; + const ptr = self.list[self.curr]; + self.curr += 1; + // return .{ .ptr = ptr, .arena = heap.ArenaAllocator.init(self.allocator) }; + return T.init(ptr, self.allocator); + } + const Self = @This(); + }; +} + +fn numOf( + comptime P: type, + ptr: P, + fnPtr: *const fn (P) callconv(.C) c_int, +) !u32 { + const num = fnPtr(ptr); + return if (num < 0) err.handleError() else @intCast(num); +} diff --git a/server/src/libvirt-pool.zig b/server/src/libvirt-pool.zig new file mode 100644 index 0000000..a635a37 --- /dev/null +++ b/server/src/libvirt-pool.zig @@ -0,0 +1,221 @@ +const std = @import("std"); +const mem = std.mem; +const heap = std.heap; + +const c = @import("libvirt-c.zig").c; +const h = @import("libvirt-helper.zig"); +const err = @import("libvirt-error.zig"); +const Connection = @import("libvirt-connection.zig"); +const Volume = @import("libvirt-volume.zig"); +const VirError = err.VirError; +const Pool = @This(); + +ptr: c.virStoragePoolPtr, +arena: *heap.ArenaAllocator, + +pub fn init(ptr: c.virStoragePoolPtr, allocator: mem.Allocator) Pool { + var arena = heap.ArenaAllocator.init(allocator); + return .{ + .ptr = ptr, + .arena = &arena, + }; +} +pub fn deinit(self: *const Pool) void { + self.arena.deinit(); +} + +// pub fn findStoragePoolSources( +// conn: *const Connection, +// type: []const u8, +// srcSpec: []const u8, +// flags: []const Flags, +// ) VirError![]u8 {} // TODO +// pub fn getStoragePoolCapabilities( +// conn: *const Connection, +// flags: []const Flags, +// ) VirError![]u8 {} // TODO +pub fn listAllStoragePools( + conn: *const Connection, + pools: [*]c.virStoragePoolPtr, + flags: []const ListFlags, +) VirError![]const c.virStoragePoolPtr { + const num = c.virConnectListAllStoragePools( + conn.ptr, + @ptrCast(&pools), + h.intFromFlags(ListFlags, flags), + ); + return if (num < 0) err.handleError() else pools[0..num]; +} +// pub fn listDefinedStoragePools( +// conn: *const Connection, +// names: [*]const []const u8, +// maxnames: u32, +// ) VirError!u32 {} // TODO +// pub fn listStoragePools( +// conn: *const Connection, +// names: [*]const []const u8, +// maxnames: u32, +// ) VirError!u32 {} // TODO +// pub fn numOfDefinedStoragePools(conn: *const Connection) VirError!u32 {} +// pub fn numOfStoragePools(conn: *const Connection) VirError!u32 {} +// TODO event handling callbacks + +// pub fn build(self: *const Pool) VirError!void {} // TODO +// pub fn create(conn: *const Connection) VirError!void {} // TODO +// pub fn createXML(conn: *const Connection) VirError!void {} // TODO +// pub fn defineXML(conn: *const Connection) VirError!void {} // TODO +// pub fn delete(self: *const Pool) VirError!void {} // TODO +// pub fn destroy(self: *const Pool) VirError!void {} // TODO +pub fn free(self: *const Pool) VirError!void { + if (c.virStoragePoolFree(self.ptr) < 0) return err.handleError(); +} + +pub fn getAutostart(self: *const Pool, autostart: *c_int) VirError!void { + if (c.virStoragePoolGetAutostart(self.ptr, autostart) < 0) return err.handleError(); +} +pub fn getConnect(self: *const Pool) VirError!c.virConnectPtr { + return if (c.virStoragePoolGetConnect(self.ptr)) |ptr| ptr else err.handleError(); +} +pub fn getInfo(self: *const Pool, info: c.virStoragePoolInfoPtr) VirError!void { + if (c.virStoragePoolGetInfo(self.ptr, info) < 0) return err.handleError(); +} +pub fn getName(self: *const Pool) VirError![]const u8 { + const name = c.virStoragePoolGetName(self.ptr); + const str = h.string(name); + return if (str.len == 0) err.handleError() else str; +} +// pub fn getUUID(self: *const Pool) VirError!void {} // TODO +// pub fn getUUIDString(self: *const Pool) VirError!void {} // TODO +pub fn getXMLDesc(self: *const Pool, flags: []const XMLFlags) VirError![]const u8 { + const desc = c.virStoragePoolGetXMLDesc(self.ptr, h.intFromFlags(XMLFlags, flags)); + const str = h.string(desc); + return if (str.len == 0) err.handleError() else str; +} + +pub fn isActive(self: *const Pool) VirError!bool { + return switch (c.virStoragePoolIsActive(self.ptr)) { + 0 => false, + 1 => true, + else => err.handleError(), + }; +} +pub fn isPersistent(self: *const Pool) VirError!bool { + return switch (c.virStoragePoolIsPersistent(self.ptr)) { + 0 => false, + 1 => true, + else => err.handleError(), + }; +} +// pub fn listAllVolumes(self: *const Pool) void {} // TODO +// pub fn listVolumes(self: *const Pool) void {} // TODO + +pub fn lookupByName() void {} // TODO +pub fn lookupByTargetPath() void {} // TODO +pub fn lookupByUUID() void {} // TODO +pub fn lookupByUUIDString() void {} // TODO +pub fn lookupByVolume() void {} // TODO + +pub fn numOfVolumes() void {} // TODO +pub fn ref(self: *const Pool) VirError!void { + if (c.virStoragePoolRef(self.ptr) < 0) return err.handleError(); +} +pub fn refresh() void {} // TODO +pub fn setAutostart() void {} // TODO +pub fn undefine() void {} // TODO + +// pub fn createVolume(self: *const Pool, xml: String, flags: []const Volume.CreateFlags) !Volume { +// const volume = c.virStorageVolCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Volume.CreateFlags, flags)); +// return if (volume) |v| Volume.init(v, self.arena.allocator()) else err.handleError(); +// } + +// pub fn lookupVolumeByName(self: *const Pool, name: []const u8) !Volume { +// const volume = c.virStorageVolLookupByName(self.ptr, @ptrCast(name)); +// return if (volume) |v| Volume.init(v, self.arena.allocator()) else err.handleError(); +// } + +// pub fn iterateVolumes(self: *const Pool, flags: []const ListFlags) Volume.VolumeIterator { +// return Volume.VolumeIterator.init( +// c.virStorageVolumePtr, +// Pool, +// Volume.ListFlags, +// self, +// flags, +// self.arena.allocator(), +// c.virStoragePoolListAllVolumes, +// ); +// } + +pub fn lookupVolumeByKey(self: *const Pool, key: []const u8) VirError!Volume { + const volume = Volume.lookupByKey(self, key); + return if (volume) |v| v else err.handleError(); +} +pub fn lookupVolumeByName(self: *const Pool, name: []const u8) VirError!Volume { + const volume = Volume.lookupByName(self, name); + return if (volume) |v| v else err.handleError(); +} +pub fn lookupVolumeByPath(self: *const Pool, path: []const u8) VirError!Volume { + const volume = Volume.lookupByPath(self, path); + return if (volume) |v| v else err.handleError(); +} + +pub const ListFlags = enum(c_uint) { + Inactive = c.VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE, + Active = c.VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE, + Persistent = c.VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT, + Transient = c.VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT, + Autostart = c.VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART, + NoAutostart = c.VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART, + Dir = c.VIR_CONNECT_LIST_STORAGE_POOLS_DIR, + Fs = c.VIR_CONNECT_LIST_STORAGE_POOLS_FS, + NetFs = c.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS, + Logical = c.VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL, + Disk = c.VIR_CONNECT_LIST_STORAGE_POOLS_DISK, + Iscsi = c.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI, + Scsi = c.VIR_CONNECT_LIST_STORAGE_POOLS_SCSI, + Mpath = c.VIR_CONNECT_LIST_STORAGE_POOLS_MPATH, + Rbd = c.VIR_CONNECT_LIST_STORAGE_POOLS_RBD, + Sheepdog = c.VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG, + Gluster = c.VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER, + Zfs = c.VIR_CONNECT_LIST_STORAGE_POOLS_ZFS, + Vstorage = c.VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE, + IscsiDirect = c.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT, +}; +pub const BuildFlags = enum(c_uint) {}; +pub const CreateFlags = enum(c_uint) {}; +pub const DefineFlags = enum(c_uint) {}; +pub const DeleteFlags = enum(c_uint) {}; +pub const XMLFlags = enum(c_uint) { + Inactive = c.VIR_STORAGE_XML_INACTIVE, +}; + +pub const Info = struct { + state: State, + capacity: u64, + allocation: u64, + available: u64, +}; + +pub const State = enum(c_uint) { + Inactive = c.VIR_STORAGE_POOL_INACTIVE, + Building = c.VIR_STORAGE_POOL_BUILDING, + Running = c.VIR_STORAGE_POOL_RUNNING, + Degraded = c.VIR_STORAGE_POOL_DEGRADED, + Inaccessible = c.VIR_STORAGE_POOL_INACCESSIBLE, + Last = c.VIR_STORAGE_POOL_STATE_LAST, +}; +pub const EventID = enum(c_uint) { + Lifecycle = c.VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, + Refresh = c.VIR_STORAGE_POOL_EVENT_ID_REFRESH, + Last = c.VIR_STORAGE_POOL_EVENT_ID_LAST, +}; +pub const EventLifecycleType = enum(c_uint) { + Defined = c.VIR_STORAGE_POOL_EVENT_DEFINED, + Undefined = c.VIR_STORAGE_POOL_EVENT_UNDEFINED, + Started = c.VIR_STORAGE_POOL_EVENT_STARTED, + Stopped = c.VIR_STORAGE_POOL_EVENT_STOPPED, + Created = c.VIR_STORAGE_POOL_EVENT_CREATED, + Deleted = c.VIR_STORAGE_POOL_EVENT_DELETED, + Last = c.VIR_STORAGE_POOL_EVENT_LAST, +}; + +// pub const PoolIterator = Iterator(Pool, c.virStoragePoolPtr, c.virStoragePoolFree); diff --git a/server/src/libvirt-snapshot.zig b/server/src/libvirt-snapshot.zig new file mode 100644 index 0000000..1d48944 --- /dev/null +++ b/server/src/libvirt-snapshot.zig @@ -0,0 +1,92 @@ +const std = @import("std"); +const mem = std.mem; +const heap = std.heap; + +const c = @import("libvirt-c.zig").c; +const err = @import("libvirt-error.zig"); +const VirError = err.VirError; +const Snapshot = @This(); + +ptr: c.virDomainSnapshotPtr, +arena: *heap.ArenaAllocator, + +pub fn init(ptr: c.virDomainSnapshotPtr, allocator: mem.Allocator) Snapshot { + var arena = heap.ArenaAllocator.init(allocator); + return .{ + .ptr = ptr, + .arena = &arena, + }; +} +pub fn deinit(self: *const Snapshot) void { + self.arena.deinit(); +} + +pub fn hasCurrentSnapshot() void {} +pub fn listAllSnapshots() void {} +pub fn revertToSnapshot() void {} +pub fn createXML() void {} +pub fn current() void {} + +pub fn delete() void {} +pub fn free(self: *const Snapshot) VirError!void { + if (c.virDomainSnapshotFree(self.ptr) < 0) return err.handleError(); +} +pub fn getConnect() void {} +pub fn getDomain() void {} +pub fn getName() void {} +pub fn getParent() void {} +pub fn getXMLDesc() void {} +pub fn hasMetadata() void {} +pub fn isCurrent() void {} + +pub fn listAllChildren() void {} +pub fn listChildrenNames() void {} +pub fn listNames() void {} + +pub fn lookupByName() void {} +pub fn num() void {} +pub fn numChildren() void {} +pub fn ref(self: *const Snapshot) VirError!void { + if (c.virDomainSnapshotRef(self.ptr) < 0) return err.handleError(); +} + +pub const ListFlags = enum(c_uint) { + Descendants = c.VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, + Roots = c.VIR_DOMAIN_SNAPSHOT_LIST_ROOTS, + Metadata = c.VIR_DOMAIN_SNAPSHOT_LIST_METADATA, + Leaves = c.VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, + NoLeaves = c.VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, + NoMetadata = c.VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, + Inactive = c.VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE, + Active = c.VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, + DiskOnly = c.VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY, + Internal = c.VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL, + External = c.VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, + Topological = c.VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL, +}; +pub const CreateFlags = enum(c_uint) { + Redefine = c.VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, + Current = c.VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, + NoMetadata = c.VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, + Halt = c.VIR_DOMAIN_SNAPSHOT_CREATE_HALT, + DiskOnly = c.VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, + ReuseExt = c.VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT, + Quiesce = c.VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, + Atomic = c.VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC, + Live = c.VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, + Validate = c.VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE, +}; +pub const DeleteFlags = enum(c_uint) { + Children = c.VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, + MetadataOnly = c.VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, + ChildrenOnly = c.VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, +}; +pub const RevertFlags = enum(c_uint) { + Running = c.VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING, + Paused = c.VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED, + Force = c.VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, + ResetNvram = c.VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM, +}; +pub const XMLFlags = enum(c_uint) { + Secure = c.VIR_DOMAIN_XML_SECURE, +}; diff --git a/server/src/libvirt-volume.zig b/server/src/libvirt-volume.zig new file mode 100644 index 0000000..94a44b8 --- /dev/null +++ b/server/src/libvirt-volume.zig @@ -0,0 +1,154 @@ +const std = @import("std"); +const mem = std.mem; +const heap = std.heap; + +const h = @import("libvirt-helper.zig"); +const c = @import("libvirt-c.zig").c; +const err = @import("libvirt-error.zig"); +const Connection = @import("libvirt-connection.zig"); +const Pool = @import("libvirt-pool.zig"); +const VirError = err.VirError; +const Volume = @This(); + +ptr: c.virStorageVolPtr, +arena: *heap.ArenaAllocator, + +pub fn init(ptr: c.virStorageVolPtr, allocator: mem.Allocator) Volume { + var arena = heap.ArenaAllocator.init(allocator); + return .{ + .ptr = ptr, + .arena = &arena, + }; +} +pub fn deinit(self: *const Volume) void { + self.arena.deinit(); +} + +// pub fn createXML( +// pool: *const Pool, +// xml: h.String, +// flags: []const CreateFlags, +// ) void {} // TODO +// pub fn createXMLFrom( +// pool: *const Pool, +// xml: h.String, +// flags: []const CreateFlags, +// ) void {} // TODO +pub fn delete(self: *const Volume, flags: []const DeleteFlags) VirError!void { + if (c.virStorageVolDelete(self.ptr, h.intFromFlags(DeleteFlags, flags)) < 0) + return err.handleError(); +} +// pub fn download(self: *const Volume) VirError!void {} // TODO +pub fn free(self: *const Volume) VirError!void { + if (c.virStorageVolFree(self.ptr) < 0) return err.handleError(); +} + +pub fn getConnect(self: *const Volume) VirError!c.virConnectPtr { + return if (c.virStorageVolGetConnect(self.ptr)) |conn| conn else err.handleError(); +} +pub const GetInfoError = mem.Allocator.Error || VirError; +pub fn getInfo(self: *const Volume) GetInfoError!*Info { + var info = try self.arena.allocator().create(Info); + errdefer self.arena.allocator().destroy(info); + const p: c.virStorageVolInfoPtr = undefined; + if (c.virStorageVolGetInfo(self.ptr, p) < 0) return err.handleError(); + info.type = p.*.type; + info.capacity = p.*.capacity; + info.allocation = p.*.allocation; + return info; +} // TODO +// pub fn getInfoFlags(self: *const Volume, flags: []const InfoFlags) GetInfoError!void {} // TODO +pub fn getKey(self: *const Volume) VirError![]const u8 { + return if (c.virStorageVolGetKey(self.ptr)) |v| v else err.handleError(); +} +pub fn getName(self: *const Volume) VirError![]const u8 { + return if (c.virStorageVolGetName(self.ptr)) |v| v else err.handleError(); +} +pub fn getPath(self: *const Volume) VirError![]const u8 { + // TODO use h.String? + return if (c.virStorageVolGetPath(self.ptr)) |v| v else err.handleError(); +} +// pub fn getXMLDesc(self: *const Volume) void {} // TODO + +pub fn lookupByKey(conn: *const Connection, key: []const u8) VirError!Volume { + return if (c.virStorageVolLookupByKey(conn.ptr, key)) |v| v else err.handleError(); +} +pub fn lookupByName(conn: *const Connection, name: []const u8) VirError!Volume { + return if (c.virStorageVolLookupByName(conn.ptr, name)) |v| v else err.handleError(); +} +pub fn lookupByPath(conn: *const Connection, path: []const u8) VirError!Volume { + return if (c.virStorageVolLookupByPath(conn.ptr, path)) |v| v else err.handleError(); +} + +pub fn ref(self: *const Volume) VirError!void { + if (c.virStorageVolRef(self.ptr) < 0) return err.handleError(); +} +pub fn resize(self: *const Volume, capacity: u64, flags: []const ResizeFlags) VirError!void { + if (c.virStorageVolResize(self.ptr, capacity, h.intFromFlags(ResizeFlags, flags)) < 0) return err.handleError(); +} +// pub fn upload(self: *const Volume) void {} // TODO +pub fn wipe(self: *const Volume, flags: []const WipeFlags) VirError!void { + if (c.virStorageVolWipe(self.ptr, h.intFromFlags(WipeFlags, flags)) < 0) return err.handleError(); +} +pub fn wipePattern(self: *const Volume, algorithm: WipeAlgorithm, flags: []const WipeFlags) VirError!void { + if (c.virStorageVolWipePattern( + self.ptr, + @intFromEnum(algorithm), + h.intFromFlags(WipeFlags, flags), + ) < 0) return err.handleError(); +} + +pub const ListFlags = enum(c_uint) {}; +pub const CreateFlags = enum(c_uint) { + PreallocMetadata = c.VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, + Reflink = c.VIR_STORAGE_VOL_CREATE_REFLINK, + Validate = c.VIR_STORAGE_VOL_CREATE_VALIDATE, +}; +pub const DeleteFlags = enum(c_uint) { + Normal = c.VIR_STORAGE_VOL_DELETE_NORMAL, + Zeroed = c.VIR_STORAGE_VOL_DELETE_ZEROED, + WithSnapshots = c.VIR_STORAGE_VOL_DELETE_WITH_SNAPSHOTS, +}; +pub const DownloadFlags = enum(c_uint) { + SparseStream = c.VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM, +}; +pub const InfoFlags = enum(c_uint) { + UseAllocation = c.VIR_STORAGE_VOL_USE_ALLOCATION, + GetPhysical = c.VIR_STORAGE_VOL_GET_PHYSICAL, +}; +pub const ResizeFlags = enum(c_uint) { + Allocate = c.VIR_STORAGE_VOL_RESIZE_ALLOCATE, + Delta = c.VIR_STORAGE_VOL_RESIZE_DELTA, + Shrink = c.VIR_STORAGE_VOL_RESIZE_SHRINK, +}; +pub const UploadFlags = enum(c_uint) {}; +pub const WipeFlags = enum(c_uint) {}; +pub const Info = struct { + type: Type, + capacity: u64, + allocation: u64, +}; +pub const Type = enum(c_uint) { + File = c.VIR_STORAGE_VOL_FILE, + Block = c.VIR_STORAGE_VOL_BLOCK, + Dir = c.VIR_STORAGE_VOL_DIR, + Network = c.VIR_STORAGE_VOL_NETWORK, + Netdir = c.VIR_STORAGE_VOL_NETDIR, + Ploop = c.VIR_STORAGE_VOL_PLOOP, + Last = c.VIR_STORAGE_VOL_LAST, +}; +pub const WipeAlgorithm = enum(c_uint) { + Zero = c.VIR_STORAGE_VOL_WIPE_ALG_ZERO, + Nnsa = c.VIR_STORAGE_VOL_WIPE_ALG_NNSA, + Dod = c.VIR_STORAGE_VOL_WIPE_ALG_DOD, + Bsi = c.VIR_STORAGE_VOL_WIPE_ALG_BSI, + Gutmann = c.VIR_STORAGE_VOL_WIPE_ALG_GUTMANN, + Schneier = c.VIR_STORAGE_VOL_WIPE_ALG_SHNEIER, + Pfitzner7 = c.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7, + Pfitzner33 = c.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33, + Random = c.VIR_STORAGE_VOL_WIPE_ALG_RANDOM, + Trim = c.VIR_STORAGE_VOL_WIPE_ALG_TRIM, + Last = c.VIR_STORAGE_VOL_WIPE_ALG_LAST, +}; + +// pub const VolumeIterator = Iterator(Volume, c.virStorageVolPtr, c.virStorageVolFree); diff --git a/server/src/libvirt.zig b/server/src/libvirt.zig index 02bdeb9..2921907 100644 --- a/server/src/libvirt.zig +++ b/server/src/libvirt.zig @@ -2,1093 +2,8 @@ const std = @import("std"); const mem = std.mem; const heap = std.heap; -pub const c = @cImport({ - @cInclude("libvirt/libvirt.h"); - @cInclude("libvirt/libvirt-admin.h"); - @cInclude("libvirt/libvirt-lxc.h"); - @cInclude("libvirt/libvirt-qemu.h"); - @cInclude("libvirt/virterror.h"); -}); - -fn handleError() VirError { - const err = c.virGetLastError(); - // std.debug.print("err: {any}\n", .{err}); - return switch (err.*.code) { - c.VIR_ERR_OK => VirError.OK, - c.VIR_ERR_INTERNAL_ERROR => VirError.InternalError, - c.VIR_ERR_NO_MEMORY => VirError.NoMemory, - c.VIR_ERR_NO_SUPPORT => VirError.NoSupport, - c.VIR_ERR_UNKNOWN_HOST => VirError.UnknownHost, - c.VIR_ERR_NO_CONNECT => VirError.NoConnect, - c.VIR_ERR_INVALID_CONN => VirError.InvalidConn, - c.VIR_ERR_INVALID_DOMAIN => VirError.InvalidDomain, - c.VIR_ERR_INVALID_ARG => VirError.InvalidArg, - c.VIR_ERR_OPERATION_FAILED => VirError.OperationFailed, - c.VIR_ERR_GET_FAILED => VirError.GetFailed, - c.VIR_ERR_POST_FAILED => VirError.PostFailed, - c.VIR_ERR_HTTP_ERROR => VirError.HttpError, - c.VIR_ERR_SEXPR_SERIAL => VirError.SexprSerial, - c.VIR_ERR_NO_XEN => VirError.NoXen, - c.VIR_ERR_XEN_CALL => VirError.XenCall, - c.VIR_ERR_OS_TYPE => VirError.OsType, - c.VIR_ERR_NO_KERNEL => VirError.NoKernel, - c.VIR_ERR_NO_ROOT => VirError.NoRoot, - c.VIR_ERR_NO_TARGET => VirError.NoTarget, - c.VIR_ERR_NO_NAME => VirError.NoName, - c.VIR_ERR_NO_OS => VirError.NoOs, - c.VIR_ERR_NO_DEVICE => VirError.NoDevice, - c.VIR_ERR_DRIVER_FULL => VirError.DriverFull, - c.VIR_ERR_CALL_FAILED => VirError.CallFailed, - c.VIR_ERR_XML_ERROR => VirError.XmlError, - c.VIR_ERR_DOM_EXIST => VirError.DomExist, - c.VIR_ERR_OPERATION_DENIED => VirError.OperationDenied, - c.VIR_ERR_OPEN_FAILED => VirError.OpenFailed, - c.VIR_ERR_READ_FAILED => VirError.ReadFailed, - c.VIR_ERR_PARSE_FAILED => VirError.ParseFailed, - c.VIR_ERR_CONF_SYNTAX => VirError.ConfSyntax, - c.VIR_ERR_WRITE_FAILED => VirError.WriteFailed, - c.VIR_ERR_XML_DETAIL => VirError.XmlDetail, - c.VIR_ERR_INVALID_NETWORK => VirError.InvalidNetwork, - c.VIR_ERR_NETWORK_EXIST => VirError.NetworkExist, - c.VIR_ERR_SYSTEM_ERROR => VirError.SystemError, - c.VIR_ERR_RPC => VirError.Rpc, - c.VIR_ERR_GNUTLS_ERROR => VirError.GnutlsError, - c.VIR_WAR_NO_NETWORK => VirError.WarNoNetwork, // ??? - c.VIR_ERR_NO_DOMAIN => VirError.NoDomain, - c.VIR_ERR_NO_NETWORK => VirError.NoNetwork, - c.VIR_ERR_INVALID_MAC => VirError.InvalidMac, - c.VIR_ERR_AUTH_FAILED => VirError.AuthFailed, - c.VIR_ERR_INVALID_STORAGE_POOL => VirError.InvalidStoragePool, - c.VIR_ERR_INVALID_STORAGE_VOL => VirError.InvalidStorageVol, - c.VIR_WAR_NO_STORAGE => VirError.WarNoStorage, // ??? - c.VIR_ERR_NO_STORAGE_POOL => VirError.NoStoragePool, - c.VIR_ERR_NO_STORAGE_VOL => VirError.NoStorageVol, - c.VIR_WAR_NO_NODE => VirError.WarNoNode, // ??? - c.VIR_ERR_INVALID_NODE_DEVICE => VirError.InvalidNodeDevice, - c.VIR_ERR_NO_NODE_DEVICE => VirError.NoNodeDevice, - c.VIR_ERR_NO_SECURITY_MODEL => VirError.NoSecurityModel, - c.VIR_ERR_OPERATION_INVALID => VirError.OperationInvalid, - c.VIR_WAR_NO_INTERFACE => VirError.WarNoInterface, // ??? - c.VIR_ERR_NO_INTERFACE => VirError.NoInterface, - c.VIR_ERR_INVALID_INTERFACE => VirError.InvalidInterface, - c.VIR_ERR_MULTIPLE_INTERFACES => VirError.MultipleInterfaces, - c.VIR_WAR_NO_NWFILTER => VirError.WarNoNwfilter, // ??? - c.VIR_ERR_INVALID_NWFILTER => VirError.InvalidNwfilter, - c.VIR_ERR_BUILD_FIREWALL => VirError.BuildFirewall, - c.VIR_WAR_NO_SECRET => VirError.WarNoSecret, // ??? - c.VIR_ERR_INVALID_SECRET => VirError.InvalidSecret, - c.VIR_ERR_CONFIG_UNSUPPORTED => VirError.ConfigUnsupported, - c.VIR_ERR_OPERATION_TIMEOUT => VirError.OperationTimeout, - c.VIR_ERR_MIGRATE_PERSIST_FAILED => VirError.MigratePersistFailed, - c.VIR_ERR_HOOK_SCRIPT_FAILED => VirError.HookScriptFailed, - c.VIR_ERR_INVALID_DOMAIN_SNAPSHOT => VirError.InvalidDomainSnapshot, - c.VIR_ERR_NO_DOMAIN_SNAPSHOT => VirError.NoDomainSnapshot, - c.VIR_ERR_INVALID_STREAM => VirError.InvalidStream, - c.VIR_ERR_ARGUMENT_UNSUPPORTED => VirError.ArgumentUnsupported, - c.VIR_ERR_STORAGE_PROBE_FAILED => VirError.StorageProbeFailed, - c.VIR_ERR_STORAGE_POOL_BUILT => VirError.StoragePoolBuilt, - c.VIR_ERR_SNAPSHOT_REVERT_RISKY => VirError.SnapshotReverRisky, - c.VIR_ERR_OPERATION_ABORTED => VirError.OperationAborted, - c.VIR_ERR_AUTH_CANCELLED => VirError.AuthCancelled, - c.VIR_ERR_NO_DOMAIN_METADATA => VirError.NoDomainMetadata, - c.VIR_ERR_MIGRATE_UNSAFE => VirError.MigrateUnsafe, - c.VIR_ERR_OVERFLOW => VirError.Overflow, - c.VIR_ERR_BLOCK_COPY_ACTIVE => VirError.BlockCopyActive, - c.VIR_ERR_OPERATION_UNSUPPORTED => VirError.OperationUnsupported, - c.VIR_ERR_SSH => VirError.Ssh, - c.VIR_ERR_AGENT_UNRESPONSIVE => VirError.AgentUnresponsive, - c.VIR_ERR_RESOURCE_BUSY => VirError.ResourceBusy, - c.VIR_ERR_ACCESS_DENIED => VirError.AccessDenied, - c.VIR_ERR_DBUS_SERVICE => VirError.DbusService, - c.VIR_ERR_STORAGE_VOL_EXIST => VirError.StorageVolExist, - c.VIR_ERR_CPU_INCOMPATIBLE => VirError.CpuIncompatible, - c.VIR_ERR_XML_INVALID_SCHEMA => VirError.XmlInvalidSchema, - c.VIR_ERR_MIGRATE_FINISH_OK => VirError.MigrateFinishOk, - c.VIR_ERR_AUTH_UNAVAILABLE => VirError.AuthUnavailable, - c.VIR_ERR_NO_SERVER => VirError.NoServer, - c.VIR_ERR_NO_CLIENT => VirError.NoClient, - c.VIR_ERR_AGENT_UNSYNCED => VirError.AgentUnsynced, - c.VIR_ERR_LIBSSH => VirError.Libssh, - c.VIR_ERR_DEVICE_MISSING => VirError.DeviceMissing, - c.VIR_ERR_INVALID_NWFILTER_BINDING => VirError.InvalidNwfilterBinding, - c.VIR_ERR_NO_NWFILTER_BINDING => VirError.NoNwfilterBinding, - c.VIR_ERR_INVALID_DOMAIN_CHECKPOINT => VirError.InvalidDomainCheckpoint, - c.VIR_ERR_NO_DOMAIN_CHECKPOINT => VirError.NoDomainCheckpoint, - c.VIR_ERR_NO_DOMAIN_BACKUP => VirError.NoDomainBackup, - c.VIR_ERR_INVALID_NETWORK_PORT => VirError.InvalidNetworkPort, - c.VIR_ERR_NETWORK_PORT_EXIST => VirError.NetworkPortExist, - c.VIR_ERR_NO_NETWORK_PORT => VirError.NoNetworkPort, - c.VIR_ERR_NO_HOSTNAME => VirError.NoHostname, - c.VIR_ERR_CHECKPOINT_INCONSISTENT => VirError.CheckpointInconsistent, - c.VIR_ERR_MULTIPLE_DOMAINS => VirError.MultipleDomains, - c.VIR_ERR_NO_NETWORK_METADATA => VirError.NoNetworkMetadata, - else => VirError.OK, - }; -} - -pub const VirError = error{ - OK, - InternalError, - NoMemory, - NoSupport, - UnknownHost, - NoConnect, - InvalidConn, - InvalidDomain, - InvalidArg, - OperationFailed, - GetFailed, - PostFailed, - HttpError, - SexprSerial, - NoXen, - XenCall, - OsType, - NoKernel, - NoRoot, - NoSource, - NoTarget, - NoName, - NoOs, - NoDevice, - NoXenstore, - DriverFull, - CallFailed, - XmlError, - DomExist, - OperationDenied, - OpenFailed, - ReadFailed, - ParseFailed, - ConfSyntax, - WriteFailed, - XmlDetail, - InvalidNetwork, - NetworkExist, - SystemError, - Rpc, - GnutlsError, - WarNoNetwork, // ??? - NoDomain, - NoNetwork, - InvalidMac, - AuthFailed, - InvalidStoragePool, - InvalidStorageVol, - WarNoStorage, // ??? - NoStoragePool, - NoStorageVol, - WarNoNode, // ??? - InvalidNodeDevice, - NoNodeDevice, - NoSecurityModel, - OperationInvalid, - WarNoInterface, // ??? - NoInterface, - InvalidInterface, - MultipleInterfaces, - WarNoNwfilter, // ??? - InvalidNwfilter, - BuildFirewall, - WarNoSecret, // ??? - InvalidSecret, - ConfigUnsupported, - OperationTimeout, - MigratePersistFailed, - HookScriptFailed, - InvalidDomainSnapshot, - NoDomainSnapshot, - InvalidStream, - ArgumentUnsupported, - StorageProbeFailed, - StoragePoolBuilt, - SnapshotReverRisky, - OperationAborted, - AuthCancelled, - NoDomainMetadata, - MigrateUnsafe, - Overflow, - BlockCopyActive, - OperationUnsupported, - Ssh, - AgentUnresponsive, - ResourceBusy, - AccessDenied, - DbusService, - StorageVolExist, - CpuIncompatible, - XmlInvalidSchema, - MigrateFinishOk, - AuthUnavailable, - NoServer, - NoClient, - AgentUnsynced, - Libssh, - DeviceMissing, - InvalidNwfilterBinding, - NoNwfilterBinding, - InvalidDomainCheckpoint, - NoDomainCheckpoint, - NoDomainBackup, - InvalidNetworkPort, - NetworkPortExist, - NoNetworkPort, - NoHostname, - CheckpointInconsistent, - MultipleDomains, - NoNetworkMetadata, -}; - -// Helper struct for allocating null-terminated strings -pub const String = struct { - allocator: mem.Allocator, - slice: []u8, - str: [:0]const u8, - - pub fn init(allocator: mem.Allocator, in_str: []const u8) !String { - const str = try allocator.alloc(u8, in_str.len + 1); - @memcpy(str[0..in_str.len], in_str); - str[str.len - 1] = 0; - return .{ - .allocator = allocator, - .slice = str, - .str = @ptrCast(str), - }; - } - pub fn deinit(self: *const String) void { - self.allocator.free(self.slice); - } -}; - -fn string(str: [*c]const u8) []const u8 { - return mem.span(str); -} - -fn intFromFlags(comptime T: type, flags: []const T) c_uint { - var flags_int: c_uint = 0; - for (flags) |f| flags_int |= @intFromEnum(f); - return flags_int; -} - -fn Iterator(comptime T: type, comptime Ptr: type, comptime freeFn: *const fn (Ptr) callconv(.C) c_int) type { - return struct { - allocator: mem.Allocator, - list: [*]Ptr, - num: c_int, - curr: usize, - - pub fn init( - comptime PP: type, // Parent Pointer - comptime P: type, // Parent - comptime F: type, // Flags - parent: *const P, - flags: []const F, - allocator: mem.Allocator, - initFn: *const fn (?*PP, [*c][*c]Ptr, c_uint) callconv(.C) c_int, - ) !Self { - var list: [*]Ptr = undefined; - const num = initFn(parent.ptr, @ptrCast(&list), intFromFlags(F, flags)); - return if (num < 0) handleError() else .{ - .allocator = allocator, - .list = list, - .num = num, - .curr = 0, - }; - } - pub fn deinit(self: *Self) void { - var i: usize = 0; - while (i < self.num) : (i += 1) _ = freeFn(self.list[i]); - } - pub fn first(self: *Self) T { - self.curr = 0; - // return .{ .ptr = self.list[self.curr], .arena = heap.ArenaAllocator.init(self.allocator) }; - return T.init(self.list[self.curr], self.allocator); - } - pub fn next(self: *Self) ?T { - if (self.curr >= self.num) return null; - const ptr = self.list[self.curr]; - self.curr += 1; - // return .{ .ptr = ptr, .arena = heap.ArenaAllocator.init(self.allocator) }; - return T.init(ptr, self.allocator); - } - const Self = @This(); - }; -} - -fn numOf( - comptime P: type, - ptr: P, - fnPtr: *const fn (P) callconv(.C) c_int, -) !u32 { - const num = fnPtr(ptr); - return if (num < 0) handleError() else @intCast(num); -} - -pub const Connection = struct { - ptr: c.virConnectPtr, - allocator: mem.Allocator, - - pub fn connect(uri: []const u8, allocator: mem.Allocator) VirError!Connection { - const connection = c.virConnectOpenAuth(@ptrCast(uri), c.virConnectAuthPtrDefault, 0); - if (connection) |conn| return .{ - .ptr = conn, - .allocator = allocator, - } else return handleError(); - } - - pub fn close(self: *const Connection) void { - _ = c.virConnectClose(self.ptr); - } - - // pub fn getURI(self: *const Connection) ![]u8 { - // const uri = c.virConnectGetURI(self.ptr); - // defer std.c.free(uri); - // const str = string(uri); - // return if (str.len == 0) handleError() else try self.allocator.dupe(u8, str); - // } - // pub fn freeURI(self: *const Connection, uri: []u8) void { - // self.allocator.free(uri); - // } - - // pub fn numOfPools(self: *const Connection) !u32 { - // return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfStoragePools); - // } - // pub fn numOfDefinedPools(self: *const Connection) !u32 { - // return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfDefinedStoragePools); - // } - - // pub fn iteratePools(self: *const Connection, flags: []const Pool.ListFlags) !Pool.PoolIterator { - // return Pool.PoolIterator.init( - // c.virConnect, - // Connection, - // Pool.ListFlags, - // self, - // flags, - // self.allocator, - // c.virConnectListAllStoragePools, - // ); - // } - - // pub fn createPool(self: *const Connection, xml: String, flags: []const Pool.CreateFlags) !Pool { - // const pool = c.virStoragePoolCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Pool.CreateFlags, flags)); - // return if (pool) |p| Pool.init(p, self.allocator) else handleError(); - // } - // pub fn definePoolFlags(self: *const Connection, xml: String, flags: []const Pool.DefineFlags) !Pool { - // const pool = c.virStoragePoolCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Pool.DefineFlags, flags)); - // return if (pool) |p| Pool.init(p, self.allocator) else handleError(); - // } - - // pub fn numOfDomains(self: *const Connection) !u32 { - // return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfDomains); - // } - // pub fn numOfDefinedDomains(self: *const Connection) !u32 { - // return numOf(c.virConnectPtr, self.ptr, c.virConnectNumOfDefinedDomains); - // } - - // pub fn iterateDomains(self: *const Connection, flags: []const Domain.ListFlags) !Domain.DomainIterator { - // return Domain.DomainIterator.init( - // c.virConnect, - // Connection, - // Domain.ListFlags, - // self, - // flags, - // self.allocator, - // c.virConnectListAllDomains, - // ); - // } - - // pub fn createDomain(self: *const Connection, xml: String, flags: []const Domain.CreateFlags) !Domain { - // const domain = c.virDomainCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Domain.CreateFlags, flags)); - // return if (domain) |d| Domain.init(d, self.allocator) else handleError(); - // } - // pub fn defineDomain(self: *const Connection, xml: String) !Domain { - // const domain = c.virDomainDefineXML(self.ptr, @ptrCast(xml.str)); - // return if (domain) |d| Domain.init(d, self.allocator) else handleError(); - // } - // pub fn defineDomainFlags(self: *const Connection, xml: String, flags: []const Domain.DefineFlags) !Domain { - // const domain = c.virDomainDefineXMLFlags(self.ptr, @ptrCast(xml.str), intFromFlags(Domain.DefineFlags, flags)); - // return if (domain) |d| Domain.init(d, self.allocator) else handleError(); - // } -}; - -pub const Pool = struct { - ptr: c.virStoragePoolPtr, - arena: *heap.ArenaAllocator, - - pub fn init(ptr: c.virStoragePoolPtr, allocator: mem.Allocator) Pool { - var arena = heap.ArenaAllocator.init(allocator); - return .{ - .ptr = ptr, - .arena = &arena, - }; - } - pub fn deinit(self: *const Pool) void { - self.arena.deinit(); - } - - pub fn findStoragePoolSources( - conn: *const Connection, - type: []const u8, - srcSpec: []const u8, - flags: []const Flags, - ) VirError![]u8 {} // TODO - pub fn getStoragePoolCapabilities( - conn: *const Connection, - flags: []const Flags, - ) VirError![]u8 {} // TODO - pub fn listAllStoragePools( - conn: *const Connection, - pools: [*]c.virStoragePoolPtr, - flags: []const ListFlags, - ) VirError![]const c.virStoragePoolPtr { - const num = c.virConnectListAllStoragePools( - conn.ptr, - @ptrCast(&pools), - intFromFlags(ListFlags, flags), - ); - return if (num < 0) handleError() else pools[0..num]; - } - pub fn listDefinedStoragePools( - conn: *const Connection, - names: [*]const []const u8, - maxnames: u32, - ) VirError!u32 {} // TODO - pub fn listStoragePools( - conn: *const Connection, - names: [*]const []const u8, - maxnames: u32, - ) VirError!u32 {} // TODO - pub fn numOfDefinedStoragePools(conn: *const Connection) VirError!u32 {} - pub fn numOfStoragePools(conn: *const Connection) VirError!u32 {} - // TODO event handling callbacks - - pub fn build(self: *const Pool) VirError!void {} // TODO - pub fn create(conn: *const Connection) VirError!void {} // TODO - pub fn createXML(conn: *const Connection) VirError!void {} // TODO - pub fn defineXML(conn: *const Connection) VirError!void {} // TODO - pub fn delete(self: *const Pool) VirError!void {} // TODO - pub fn destroy(self: *const Pool) VirError!void {} // TODO - pub fn free(self: *const Pool) VirError!void { - if (c.virStoragePoolFree(self.ptr) < 0) return handleError(); - } - - pub fn getAutostart(self: *const Pool, autostart: *c_int) VirError!void { - if (c.virStoragePoolGetAutostart(self.ptr, autostart) < 0) return handleError(); - } - pub fn getConnect(self: *const Pool) VirError!c.virConnectPtr { - return if (c.virStoragePoolGetConnect(self.ptr)) |ptr| ptr else handleError(); - } - pub fn getInfo(self: *const Pool, info: c.virStoragePoolInfoPtr) VirError!void { - if (c.virStoragePoolGetInfo(self.ptr, info) < 0) return handleError(); - } - pub fn getName(self: *const Pool) VirError![]const u8 { - const name = c.virStoragePoolGetName(self.ptr); - const str = string(name); - return if (str.len == 0) handleError() else str; - } - pub fn getUUID(self: *const Pool) VirError!void {} // TODO - pub fn getUUIDString(self: *const Pool) VirError!void {} // TODO - pub fn getXMLDesc(self: *const Pool, flags: []const XMLFlags) VirError![]const u8 { - const desc = c.virStoragePoolGetXMLDesc(self.ptr, intFromFlags(XMLFlags, flags)); - const str = string(desc); - return if (str.len == 0) handleError() else str; - } - - pub fn isActive(self: *const Pool) VirError!bool { - return switch (c.virStoragePoolIsActive(self.ptr)) { - 0 => false, - 1 => true, - else => handleError(), - }; - } - pub fn isPersistent(self: *const Pool) VirError!bool { - return switch (c.virStoragePoolIsPersistent(self.ptr)) { - 0 => false, - 1 => true, - else => handleError(), - }; - } - pub fn listAllVolumes(self: *const Pool) void {} // TODO - pub fn listVolumes(self: *const Pool) void {} // TODO - - pub fn lookupByName() void {} // TODO - pub fn lookupByTargetPath() void {} // TODO - pub fn lookupByUUID() void {} // TODO - pub fn lookupByUUIDString() void {} // TODO - pub fn lookupByVolume() void {} // TODO - - pub fn numOfVolumes() void {} // TODO - pub fn ref(self: *const Pool) VirError!void { - if (c.virStoragePoolRef(self.ptr) < 0) return handleError(); - } - pub fn refresh() void {} // TODO - pub fn setAutostart() void {} // TODO - pub fn undefine() void {} // TODO - - // pub fn createVolume(self: *const Pool, xml: String, flags: []const Volume.CreateFlags) !Volume { - // const volume = c.virStorageVolCreateXML(self.ptr, @ptrCast(xml.str), intFromFlags(Volume.CreateFlags, flags)); - // return if (volume) |v| Volume.init(v, self.arena.allocator()) else handleError(); - // } - - // pub fn lookupVolumeByName(self: *const Pool, name: []const u8) !Volume { - // const volume = c.virStorageVolLookupByName(self.ptr, @ptrCast(name)); - // return if (volume) |v| Volume.init(v, self.arena.allocator()) else handleError(); - // } - - // pub fn iterateVolumes(self: *const Pool, flags: []const ListFlags) Volume.VolumeIterator { - // return Volume.VolumeIterator.init( - // c.virStorageVolumePtr, - // Pool, - // Volume.ListFlags, - // self, - // flags, - // self.arena.allocator(), - // c.virStoragePoolListAllVolumes, - // ); - // } - - pub fn lookupVolumeByKey(self: *const Pool, key: []const u8) VirError!Volume { - const volume = Volume.lookupByKey(self, key); - return if (volume) |v| v else handleError(); - } - pub fn lookupVolumeByName(self: *const Pool, name: []const u8) VirError!Volume { - const volume = Volume.lookupByName(self, name); - return if (volume) |v| v else handleError(); - } - pub fn lookupVolumeByPath(self: *const Pool, path: []const u8) VirError!Volume { - const volume = Volume.lookupByPath(self, path); - return if (volume) |v| v else handleError(); - } - - pub const ListFlags = enum(c_uint) { - Inactive = c.VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE, - Active = c.VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE, - Persistent = c.VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT, - Transient = c.VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT, - Autostart = c.VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART, - NoAutostart = c.VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART, - Dir = c.VIR_CONNECT_LIST_STORAGE_POOLS_DIR, - Fs = c.VIR_CONNECT_LIST_STORAGE_POOLS_FS, - NetFs = c.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS, - Logical = c.VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL, - Disk = c.VIR_CONNECT_LIST_STORAGE_POOLS_DISK, - Iscsi = c.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI, - Scsi = c.VIR_CONNECT_LIST_STORAGE_POOLS_SCSI, - Mpath = c.VIR_CONNECT_LIST_STORAGE_POOLS_MPATH, - Rbd = c.VIR_CONNECT_LIST_STORAGE_POOLS_RBD, - Sheepdog = c.VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG, - Gluster = c.VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER, - Zfs = c.VIR_CONNECT_LIST_STORAGE_POOLS_ZFS, - Vstorage = c.VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE, - IscsiDirect = c.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT, - }; - pub const BuildFlags = enum(c_uint) {}; - pub const CreateFlags = enum(c_uint) {}; - pub const DefineFlags = enum(c_uint) {}; - pub const DeleteFlags = enum(c_uint) {}; - pub const XMLFlags = enum(c_uint) { - Inactive = c.VIR_STORAGE_XML_INACTIVE, - }; - - pub const Info = struct { - state: State, - capacity: u64, - allocation: u64, - available: u64, - }; - - pub const State = enum(c_uint) { - Inactive = c.VIR_STORAGE_POOL_INACTIVE, - Building = c.VIR_STORAGE_POOL_BUILDING, - Running = c.VIR_STORAGE_POOL_RUNNING, - Degraded = c.VIR_STORAGE_POOL_DEGRADED, - Inaccessible = c.VIR_STORAGE_POOL_INACCESSIBLE, - Last = c.VIR_STORAGE_POOL_STATE_LAST, - }; - pub const EventID = enum(c_uint) { - Lifecycle = c.VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, - Refresh = c.VIR_STORAGE_POOL_EVENT_ID_REFRESH, - Last = c.VIR_STORAGE_POOL_EVENT_ID_LAST, - }; - pub const EventLifecycleType = enum(c_uint) { - Defined = c.VIR_STORAGE_POOL_EVENT_DEFINED, - Undefined = c.VIR_STORAGE_POOL_EVENT_UNDEFINED, - Started = c.VIR_STORAGE_POOL_EVENT_STARTED, - Stopped = c.VIR_STORAGE_POOL_EVENT_STOPPED, - Created = c.VIR_STORAGE_POOL_EVENT_CREATED, - Deleted = c.VIR_STORAGE_POOL_EVENT_DELETED, - Last = c.VIR_STORAGE_POOL_EVENT_LAST, - }; - - pub const PoolIterator = Iterator(Pool, c.virStoragePoolPtr, c.virStoragePoolFree); - - pub const Volume = struct { - ptr: c.virStorageVolPtr, - arena: *heap.ArenaAllocator, - - pub fn init(ptr: c.virStorageVolPtr, allocator: mem.Allocator) Volume { - var arena = heap.ArenaAllocator.init(allocator); - return .{ - .ptr = ptr, - .arena = &arena, - }; - } - pub fn deinit(self: *const Volume) void { - self.arena.deinit(); - } - - pub fn createXML( - pool: *const Pool, - xml: String, - flags: []const CreateFlags, - ) void {} // TODO - pub fn createXMLFrom( - pool: *const Pool, - xml: String, - flags: []const CreateFlags, - ) void {} // TODO - pub fn delete(self: *const Volume, flags: []const DeleteFlags) VirError!void { - if (c.virStorageVolDelete(self.ptr, intFromFlags(DeleteFlags, flags)) < 0) - return handleError(); - } - pub fn download(self: *const Volume) VirError!void {} // TODO - pub fn free(self: *const Volume) VirError!void { - if (c.virStorageVolFree(self.ptr) < 0) return handleError(); - } - - pub fn getConnect(self: *const Volume) VirError!c.virConnectPtr { - return if (c.virStorageVolGetConnect(self.ptr)) |c| c else handleError(); - } - pub fn getInfo(self: *const Volume) void {} // TODO - pub fn getInfoFlags(self: *const Volume) void {} // TODO - pub fn getKey(self: *const Volume) VirError![]const u8 { - return if (c.virStorageVolGetKey(self.ptr)) |v| v else handleError(); - } - pub fn getName(self: *const Volume) VirError![]const u8 { - return if (c.virStorageVolGetName(self.ptr)) |v| v else handleError(); - } - pub fn getPath(self: *const Volume) VirError![]const u8 { - // TODO use String? - return if (c.virStorageVolGetPath(self.ptr)) |v| v else handleError(); - } - pub fn getXMLDesc(self: *const Volume) void {} // TODO - - pub fn lookupByKey(conn: *const Connection, key: []const u8) VirError!Volume { - return if (c.virStorageVolLookupByKey(conn.ptr, key)) |v| v else handleError(); - } - pub fn lookupByName(conn: *const Connection, name: []const u8) VirError!Volume { - return if (c.virStorageVolLookupByName(conn.ptr, name)) |v| v else handleError(); - } - pub fn lookupByPath(conn: *const Connection, path: []const u8) VirError!Volume { - return if (c.virStorageVolLookupByPath(conn.ptr, path)) |v| v else handleError(); - } - - pub fn ref(self: *const Volume) VirError!void { - if (c.virStorageVolRef(self.ptr) < 0) return handleError(); - } - pub fn resize(self: *const Volume) void {} // TODO - pub fn upload(self: *const Volume) void {} // TODO - pub fn wipe(self: *const Volume) void {} // TODO - pub fn wipePattern(self: *const Volume) void {} // TODO - - pub const ListFlags = enum(c_uint) {}; - pub const CreateFlags = enum(c_uint) { - PreallocMetadata = c.VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, - Reflink = c.VIR_STORAGE_VOL_CREATE_REFLINK, - Validate = c.VIR_STORAGE_VOL_CREATE_VALIDATE, - }; - pub const DeleteFlags = enum(c_uint) { - Normal = c.VIR_STORAGE_VOL_DELETE_NORMAL, - Zeroed = c.VIR_STORAGE_VOL_DELETE_ZEROED, - WithSnapshots = c.VIR_STORAGE_VOL_DELETE_WITH_SNAPSHOTS, - }; - pub const DownloadFlags = enum(c_uint) { - SparseStream = c.VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM, - }; - pub const InfoFlags = enum(c_uint) { - UseAllocation = c.VIR_STORAGE_VOL_USE_ALLOCATION, - GetPhysical = c.VIR_STORAGE_VOL_GET_PHYSICAL, - }; - pub const ResizeFlags = enum(c_uint) { - Allocate = c.VIR_STORAGE_VOL_RESIZE_ALLOCATE, - Delta = c.VIR_STORAGE_VOL_RESIZE_DELTA, - Shrink = c.VIR_STORAGE_VOL_RESIZE_SHRINK, - }; - pub const UploadFlags = enum(c_uint) {}; - pub const Info = struct { - type: Type, - capacity: u64, - allocation: u64, - }; - pub const Type = enum(c_uint) { - File = c.VIR_STORAGE_VOL_FILE, - Block = c.VIR_STORAGE_VOL_BLOCK, - Dir = c.VIR_STORAGE_VOL_DIR, - Network = c.VIR_STORAGE_VOL_NETWORK, - Netdir = c.VIR_STORAGE_VOL_NETDIR, - Ploop = c.VIR_STORAGE_VOL_PLOOP, - Last = c.VIR_STORAGE_VOL_LAST, - }; - pub const WipeAlgorithm = enum(c_uint) { - Zero = c.VIR_STORAGE_VOL_WIPE_ALG_ZERO, - Nnsa = c.VIR_STORAGE_VOL_WIPE_ALG_NNSA, - Dod = c.VIR_STORAGE_VOL_WIPE_ALG_DOD, - Bsi = c.VIR_STORAGE_VOL_WIPE_ALG_BSI, - Gutmann = c.VIR_STORAGE_VOL_WIPE_ALG_GUTMANN, - Schneier = c.VIR_STORAGE_VOL_WIPE_ALG_SHNEIER, - Pfitzner7 = c.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7, - Pfitzner33 = c.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33, - Random = c.VIR_STORAGE_VOL_WIPE_ALG_RANDOM, - Trim = c.VIR_STORAGE_VOL_WIPE_ALG_TRIM, - Last = c.VIR_STORAGE_VOL_WIPE_ALG_LAST, - }; - - pub const VolumeIterator = Iterator(Volume, c.virStorageVolPtr, c.virStorageVolFree); - }; -}; - -pub const Domain = struct { - ptr: c.virDomainPtr, - arena: *heap.ArenaAllocator, - - pub fn init(ptr: c.virDomainPtr, allocator: mem.Allocator) Domain { - var arena = heap.ArenaAllocator.init(allocator); - return .{ - .ptr = ptr, - .arena = &arena, - }; - } - pub fn deinit(self: *const Domain) void { - self.arena.deinit(); - } - - // TODO event handling callbacks - - pub fn xmlFromNative() void {} - pub fn xmlToNative() void {} - pub fn getAllDomainStats() void {} - pub fn getDomainCapabilities() void {} - pub fn listAllDomains() void {} - pub fn listDefinedDomains() void {} - pub fn listDomains() void {} - pub fn numOfDefinedDomains() void {} - pub fn numOfDomains() void {} - - pub fn abortJob() void {} - pub fn abortJobFlags() void {} - pub fn addIOThread() void {} - pub fn agentSetResponseTimeout() void {} - pub fn attachDevice() void {} - pub fn attachDeviceFlags() void {} - pub fn authorizedSSHKeysSet() void {} - pub fn backupBegin() void {} - pub fn backupGetXMLDesc() void {} - pub fn blockCommit() void {} - pub fn blockCopy() void {} - pub fn blockJobAbort() void {} - pub fn blockJobSetSpeed() void {} - pub fn blockPeek() void {} - pub fn blockPull() void {} - pub fn blockRebase() void {} - pub fn blockResize() void {} - pub fn blockStats() void {} - pub fn blockStatsFlags() void {} - pub fn coreDump() void {} - pub fn coreDumpWithFormat() void {} - - pub fn create() void {} - pub fn createLinux() void {} - pub fn createWithFiles() void {} - pub fn createWithFlags() void {} - pub fn createXML() void {} - pub fn createXMLWithFiles() void {} - pub fn defineXML() void {} - pub fn defineXMLFlags() void {} - pub fn delIOThread() void {} - pub fn destroy() void {} - pub fn destroyFlags() void {} - pub fn detachDevice() void {} - pub fn detachDeviceAlias() void {} - pub fn detachDeviceFlags() void {} - pub fn fdAssociate() void {} - pub fn fsFreeze() void {} - pub fn fsInfoFree() void {} - pub fn fsThaw() void {} - pub fn fsTrim() void {} - pub fn free(self: *const Domain) VirError!void { - if (c.virDomainFree(self.ptr) < 0) return handleError(); - } - - pub fn getAutostart() void {} - pub fn getBlkioParameters() void {} - pub fn getBlockInfo() void {} - pub fn getBlockIoTune() void {} - pub fn getBlockJobInfo() void {} - pub fn getCPUStats() void {} - pub fn getConnect() void {} - pub fn getControlInfo() void {} - pub fn getDiskErrors() void {} - pub fn getEmulatorPinInfo() void {} - pub fn getFSInfo() void {} - pub fn getGuestInfo() void {} - pub fn getGuestVcpus() void {} - pub fn getHostname() void {} - pub fn getID() void {} - pub fn getIOThreadInfo() void {} - pub fn getInfo() void {} - pub fn getInterfaceParameters() void {} - pub fn getJobInfo() void {} - pub fn getJobStats() void {} - pub fn getLaunchSecurityInfo() void {} - pub fn getMaxMemory() void {} - pub fn getMaxVcpus() void {} - pub fn getMemoryParameters() void {} - pub fn getMessages() void {} - pub fn getMetadata() void {} - pub fn getName(self: *const Domain) VirError![]const u8 { - const name = c.virDomainGetName(self.ptr); - const str = string(name); - return if (str.len == 0) handleError() else str; - } - pub fn getNumaParameters() void {} - pub fn getOSType() void {} - pub fn getPerfEvents() void {} - pub fn getSchedulerParameters() void {} - pub fn getSchedulerParametersFlags() void {} - pub fn getSchedulerType() void {} - pub fn getSecurityLabel() void {} - pub fn getSecurityLabelList() void {} - pub fn getState() void {} - pub fn getTime() void {} - pub fn getUUID() void {} - pub fn getUUIDString() void {} - pub fn getVcpuPinInfo() void {} - pub fn getVcpus() void {} - pub fn getVpusFlags() void {} - pub fn getXMLDesc() void {} - - pub fn graphicsReload() void {} - pub fn hasManagedSaveImage() void {} - pub fn ioThreadInfoFree() void {} - pub fn injectNMI() void {} - pub fn interfaceAddresses() void {} - pub fn interfaceFree() void {} - pub fn interfaceStats() void {} - - pub fn isActive(self: *const Domain) void { - const active = c.virDomainIsActive(self.ptr); - return if (active == 0) false else true; - } - pub fn isPersistent() void {} - pub fn isUpdated() void {} - pub fn listGetStats() void {} - pub fn lookupByID() void {} - pub fn lookupByUUID() void {} - pub fn lookupByUUIDString() void {} - - pub fn managedSave() void {} - pub fn managedSaveDefineXML() void {} - pub fn managedSaveGetXMLDesc() void {} - pub fn managedSaveRemove() void {} - pub fn memoryPeek() void {} - pub fn memoryStats() void {} - - // TODO virDomainMigrate* - - pub fn openChannel() void {} - pub fn openConsole() void {} - pub fn openGraphics() void {} - pub fn openGraphicsFD() void {} - pub fn pmSuspendForDuration() void {} - pub fn pmWakeup() void {} - pub fn pinEmulator() void {} - pub fn pinIOThread() void {} - pub fn pinVcpu() void {} - pub fn pinVcpuFlags() void {} - - pub fn reboot() void {} - pub fn ref(self: *const Domain) VirError!void { - if (c.virDomainRef(self.ptr) < 0) return handleError(); - } - pub fn rename() void {} - pub fn reset() void {} - pub fn restore() void {} - pub fn restoreFlags() void {} - pub fn restoreParams() void {} - pub fn @"resume"() void {} - pub fn save() void {} - pub fn saveFlags() void {} - pub fn saveImageDefineXML() void {} - pub fn saveImageGetXMLDesc() void {} - pub fn saveParams() void {} - pub fn screenshot() void {} - pub fn sendKey() void {} - pub fn sendProcessSignal() void {} - - pub fn setAutostart() void {} - pub fn setBlkioParameters() void {} - pub fn setBlockIoTune() void {} - pub fn setBlockThreshold() void {} - pub fn setGuestVcpus() void {} - pub fn setIOThreadParams() void {} - pub fn setInterfaceParameters() void {} - pub fn setLaunchSecurityState() void {} - pub fn setLifecycleAction() void {} - pub fn setMaxMemory() void {} - pub fn setMemory() void {} - pub fn setMemoryFlags() void {} - pub fn setMemoryParameters() void {} - pub fn setMemoryStatsPeriod() void {} - pub fn setMetadata() void {} - pub fn setNumaParameters() void {} - pub fn setPerfEvents() void {} - pub fn setSchedulerParameters() void {} - pub fn setSchedulerParametersFlags() void {} - pub fn setTime() void {} - pub fn setUserPassword() void {} - pub fn setVcpu() void {} - pub fn setVcpus() void {} - pub fn setVpusFlags() void {} - - pub fn shutdown() void {} - pub fn @"suspend"() void {} - pub fn undefine() void {} - pub fn undefineFlags() void {} - pub fn updateDeviceFlags() void {} - - pub const ListFlags = enum(c_uint) { - Active = c.VIR_CONNECT_LIST_DOMAINS_ACTIVE, - Inactive = c.VIR_CONNECT_LIST_DOMAINS_INACTIVE, - }; - pub const AbortJobFlagsValues = enum(c_uint) {}; - pub const AgentResponseTimeoutValues = enum(c_uint) {}; - pub const AuthorizedSSHKeysSetFlags = enum(c_uint) {}; - pub const BackupBeginFlags = enum(c_uint) {}; - pub const BlockCommitFlags = enum(c_uint) {}; - pub const BlockCopyFlags = enum(c_uint) {}; - pub const BlockJobAbortFlags = enum(c_uint) {}; - pub const BlockJobInfoFlags = enum(c_uint) {}; - pub const BlockJobSetSpeedFlags = enum(c_uint) {}; - pub const BlockPullFlags = enum(c_uint) {}; - pub const BlockRebaseFlags = enum(c_uint) {}; - pub const BlockResizeFlags = enum(c_uint) {}; - pub const ChannelFlags = enum(c_uint) {}; - pub const ConsoleFlags = enum(c_uint) {}; - pub const CoreDumpFlags = enum(c_uint) {}; - pub const CreateFlags = enum(c_uint) { - None = c.VIR_DOMAIN_NONE, - StartPaused = c.VIR_DOMAIN_START_PAUSED, - StartAutodestroy = c.VIR_DOMAIN_START_AUTODESTROY, - StartBypassCache = c.VIR_DOMAIN_START_BYPASS_CACHE, - StartForceBoot = c.VIR_DOMAIN_START_FORCE_BOOT, - StartValidate = c.VIR_DOMAIN_START_VALIDATE, - StartResetNvram = c.VIR_DOMAIN_START_RESET_NVRAM, - }; - pub const DefineFlags = enum(c_uint) { - Validate = c.VIR_DOMAIN_DEFINE_VALIDATE, - }; - // TODO rest - - pub const BlockInfo = struct {}; - pub const BlockJobCursor = u64; - pub const BlockJobInfo = struct {}; - pub const BlockStats = struct {}; - pub const ControlInfo = struct {}; - // TODO rest - - pub const BlockJobType = enum(c_uint) {}; - pub const BlockedReason = enum(c_uint) {}; - pub const ControlErrorReason = enum(c_uint) {}; - pub const ControlState = enum(c_uint) {}; - pub const CoreDumpFormat = enum(c_uint) {}; - pub const CrashedReason = enum(c_uint) {}; - // TODO rest - - pub const DomainIterator = Iterator(Domain, c.virDomainPtr, c.virDomainFree); - - pub const Snapshot = struct { - ptr: c.virDomainSnapshotPtr, - arena: *heap.ArenaAllocator, - - pub fn init(ptr: c.virDomainSnapshotPtr, allocator: mem.Allocator) Snapshot { - var arena = heap.ArenaAllocator.init(allocator); - return .{ - .ptr = ptr, - .arena = &arena, - }; - } - pub fn deinit(self: *const Snapshot) void { - self.arena.deinit(); - } - - pub fn hasCurrentSnapshot() void {} - pub fn listAllSnapshots() void {} - pub fn revertToSnapshot() void {} - pub fn createXML() void {} - pub fn current() void {} - - pub fn delete() void {} - pub fn free(self: *const Snapshot) VirError!void { - if (c.virDomainSnapshotFree(self.ptr) < 0) return handleError(); - } - pub fn getConnect() void {} - pub fn getDomain() void {} - pub fn getName() void {} - pub fn getParent() void {} - pub fn getXMLDesc() void {} - pub fn hasMetadata() void {} - pub fn isCurrent() void {} - - pub fn listAllChildren() void {} - pub fn listChildrenNames() void {} - pub fn listNames() void {} - - pub fn lookupByName() void {} - pub fn num() void {} - pub fn numChildren() void {} - pub fn ref(self: *const Snapshot) VirError!void { - if (c.virDomainSnapshotRef(self.ptr) < 0) return handleError(); - } - - pub const ListFlags = enum(c_uint) { - Descendants = c.VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, - Roots = c.VIR_DOMAIN_SNAPSHOT_LIST_ROOTS, - Metadata = c.VIR_DOMAIN_SNAPSHOT_LIST_METADATA, - Leaves = c.VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, - NoLeaves = c.VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, - NoMetadata = c.VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, - Inactive = c.VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE, - Active = c.VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, - DiskOnly = c.VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY, - Internal = c.VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL, - External = c.VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, - Topological = c.VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL, - }; - pub const CreateFlags = enum(c_uint) { - Redefine = c.VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, - Current = c.VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, - NoMetadata = c.VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, - Halt = c.VIR_DOMAIN_SNAPSHOT_CREATE_HALT, - DiskOnly = c.VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, - ReuseExt = c.VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT, - Quiesce = c.VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, - Atomic = c.VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC, - Live = c.VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, - Validate = c.VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE, - }; - pub const DeleteFlags = enum(c_uint) { - Children = c.VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, - MetadataOnly = c.VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, - ChildrenOnly = c.VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, - }; - pub const RevertFlags = enum(c_uint) { - Running = c.VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING, - Paused = c.VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED, - Force = c.VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, - ResetNvram = c.VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM, - }; - pub const XMLFlags = enum(c_uint) { - Secure = c.VIR_DOMAIN_XML_SECURE, - }; - }; -}; +const err = @import("libvirt-error.zig"); +pub const Error = err.VirError; +pub const Connection = @import("libvirt-connection.zig"); +pub const Pool = @import("libvirt-pool.zig"); +pub const Domain = @import("libvirt-domain.zig");