diff --git a/server/src/libvirt.zig b/server/src/libvirt.zig index df1b7a3..6d82f3e 100644 --- a/server/src/libvirt.zig +++ b/server/src/libvirt.zig @@ -13,14 +13,117 @@ pub const c = @cImport({ fn handleError() VirError { const err = c.virGetLastError(); std.debug.print("err: {any}\n", .{err}); - return VirError.OK; - // switch (err.*.code) { - // 0 => return VirError.OK, - // 1 => return VirError.InternalError, - // 2 => return VirError.NoMemory, - // // TODO rest - // else => VirError.OK, - // } + 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{ @@ -37,7 +140,7 @@ pub const VirError = error{ GetFailed, PostFailed, HttpError, - SExprError, + SexprSerial, NoXen, XenCall, OsType, @@ -58,7 +161,82 @@ pub const VirError = error{ ReadFailed, ParseFailed, ConfSyntax, - // TODO rest + 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, }; fn string(str: [*c]const u8) []const u8 { @@ -147,7 +325,6 @@ pub const Connection = struct { 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); } @@ -236,9 +413,9 @@ pub const Pool = struct { // return if (str.len == 0) handleError() else try self.arena.allocator().dupe(u8, str); } - pub fn createVolume(pool: *const Pool, xml: []const u8, flags: []Volume.Flags) !Volume { - const volume = c.virStorageVolCreateXML(pool, xml, intFromFlags(Volume.CreateFlags, flags)); - return .{ .ptr = volume }; + pub fn createVolume(self: *const Pool, xml: []const u8, flags: []const Volume.CreateFlags) !Volume { + const volume = c.virStorageVolCreateXML(self.ptr, @ptrCast(xml), intFromFlags(Volume.CreateFlags, flags)); + return if (volume) |v| Volume.init(v, self.arena.allocator()) else handleError(); } pub fn iterateVolumes(self: *const Pool, flags: []const ListFlags) Volume.VolumeIterator { @@ -316,6 +493,17 @@ pub const Pool = 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 getName(self: *const Volume) ![]const u8 { const name = c.virStorageVolGetName(self.ptr); // defer std.c.free(name); diff --git a/server/src/main.zig b/server/src/main.zig index db52873..8b02370 100644 --- a/server/src/main.zig +++ b/server/src/main.zig @@ -20,29 +20,30 @@ pub fn main() !void { nix.cwd_dir = flake_dir; _ = try nix.spawnAndWait(); nix.argv = &[_][]const u8{ "nix", "build", ".#beforeInstall", "-o", "beforeInstall" }; - _ = try nix.spawnAndWait(); + // _ = try nix.spawnAndWait(); nix.argv = &[_][]const u8{ "nix", "build", ".#afterInstall", "-o", "afterInstall" }; - _ = try nix.spawnAndWait(); + // _ = try nix.spawnAndWait(); nix.argv = &[_][]const u8{ "nix", "build", ".#beforeBoot", "-o", "beforeBoot" }; - _ = try nix.spawnAndWait(); + // _ = try nix.spawnAndWait(); nix.argv = &[_][]const u8{ "nix", "build", ".#afterBoot", "-o", "afterBoot" }; - _ = try nix.spawnAndWait(); + // _ = try nix.spawnAndWait(); - // const volume_def = try flake_dir.openFile("volume", .{}); - // defer volume_def.close(); - // const volume_xml = try volume_def.readToEndAlloc(allocator, 1024 * 1024); - // defer allocator.free(volume_xml); + const volume_def = try flake_dir.openFile("volume", .{}); + defer volume_def.close(); + const volume_xml = try volume_def.readToEndAlloc(allocator, 1024 * 1024); + defer allocator.free(volume_xml); // const volume = try connection.defineVolume(volume_xml); // -------------- const uri = try connection.getURI(); defer connection.freeURI(uri); - std.debug.print("uri: {s}\n", .{uri}); + // std.debug.print("uri: {s}\n", .{uri}); const num_active = try connection.numOfDomains(); const num_inactive = try connection.numOfDefinedDomains(); - std.debug.print("active: {d}, inactive: {d}\n", .{ num_active, num_inactive }); + // std.debug.print("active: {d}, inactive: {d}\n", .{ num_active, num_inactive }); + _ = .{ num_active, num_inactive }; var domain_iter = try connection.iterateDomains(&[_]libvirt.Domain.ListFlags{ libvirt.Domain.ListFlags.Active, @@ -53,7 +54,8 @@ pub fn main() !void { while (domain_iter.next()) |domain| { const active = domain.isActive(); const name = domain.getName(); - std.debug.print("name: {s}, active: {any}\n", .{ name, active }); + // std.debug.print("name: {s}, active: {any}\n", .{ name, active }); + _ = .{ name, active }; } var pool_iter = try connection.iteratePools(&[_]libvirt.Pool.ListFlags{ @@ -63,9 +65,24 @@ pub fn main() !void { defer pool_iter.deinit(); while (pool_iter.next()) |pool| { - // const active = pool.isActive(); const name = try pool.getName(); - std.debug.print("name: {s}\n", .{name}); + // std.debug.print("name: {s}\n", .{name}); + if (mem.eql(u8, name, "default")) { + // std.debug.print("xml: {s}\n\n", .{volume_xml}); + const xml_str = + \\ + \\ wintest.qcow2 + \\ 16 + \\ + \\ + \\ + \\ + ; + const volume = try pool.createVolume(xml_str, &[_]libvirt.Pool.Volume.CreateFlags{ + libvirt.Pool.Volume.CreateFlags.Validate, + }); + std.debug.print("pool: {any}\n", .{volume}); + } } }