basic zig libvirt structure
This commit is contained in:
parent
bb3c001b00
commit
de395d47b1
5 changed files with 210 additions and 74 deletions
8
server/flakes/windows/test/flake.lock
generated
8
server/flakes/windows/test/flake.lock
generated
|
@ -126,11 +126,11 @@
|
||||||
"zig2nix": "zig2nix"
|
"zig2nix": "zig2nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1719259792,
|
"lastModified": 1719259899,
|
||||||
"narHash": "sha256-XX8MuiwtbYvIfb2M7l7gG5wT8Lp5HFS7KMuWEtENnF0=",
|
"narHash": "sha256-DgYQAFhBPxtx3PRGMqR5AwfQRAiOGHNdnPTtlnedZVA=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "19ab6d3c7058aa553843e4cb5282e4d970d0e4fd",
|
"rev": "bb3c001b003c3f4104b32e58289deb00e96fb82a",
|
||||||
"revCount": 5,
|
"revCount": 6,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.jeevio.xyz/jeeves/oslib"
|
"url": "https://git.jeevio.xyz/jeeves/oslib"
|
||||||
},
|
},
|
||||||
|
|
1
server/flakes/windows/test/result
Symbolic link
1
server/flakes/windows/test/result
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/ag7g2kil11yp56ndvhi84azjb6wj65mx-NixVirt-volume-wintest.qcow2
|
1
server/flakes/windows/test/volume
Symbolic link
1
server/flakes/windows/test/volume
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/ag7g2kil11yp56ndvhi84azjb6wj65mx-NixVirt-volume-wintest.qcow2
|
|
@ -61,51 +61,199 @@ pub const VirError = error{
|
||||||
// TODO rest
|
// TODO rest
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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,
|
||||||
|
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 .{
|
||||||
|
.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] };
|
||||||
|
}
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
const Self = @This();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub const Connection = struct {
|
pub const Connection = struct {
|
||||||
conn: c.virConnectPtr,
|
ptr: c.virConnectPtr,
|
||||||
allocator: mem.Allocator,
|
allocator: mem.Allocator,
|
||||||
|
|
||||||
pub fn connect(uri: []const u8, allocator: mem.Allocator) VirError!Connection {
|
pub fn connect(uri: []const u8, allocator: mem.Allocator) VirError!Connection {
|
||||||
const connection = c.virConnectOpenAuth(@ptrCast(uri), c.virConnectAuthPtrDefault, 0);
|
const connection = c.virConnectOpenAuth(@ptrCast(uri), c.virConnectAuthPtrDefault, 0);
|
||||||
if (connection) |conn| return .{
|
if (connection) |conn| return .{
|
||||||
.conn = conn,
|
.ptr = conn,
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
} else return handleError();
|
} else return handleError();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(self: *const Connection) void {
|
pub fn close(self: *const Connection) void {
|
||||||
_ = c.virConnectClose(self.conn);
|
_ = c.virConnectClose(self.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getURI(self: *const Connection) ![]u8 {
|
pub fn getURI(self: *const Connection) ![]u8 {
|
||||||
const uri = c.virConnectGetURI(self.conn);
|
const uri = c.virConnectGetURI(self.ptr);
|
||||||
defer std.c.free(uri);
|
defer std.c.free(uri);
|
||||||
return try self.allocator.dupe(u8, mem.span(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 {
|
pub fn freeURI(self: *const Connection, uri: []u8) void {
|
||||||
self.allocator.free(uri);
|
self.allocator.free(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn numOfPools(self: *const Connection) !u32 {
|
||||||
|
const num = c.virConnectNumOfStoragePools(self.ptr);
|
||||||
|
return if (num < 0) handleError() else @intCast(num);
|
||||||
|
}
|
||||||
|
pub fn numOfDefinedPools(self: *const Connection) !u32 {
|
||||||
|
const num = c.virConnectNumOfDefinedStoragePools(self.ptr);
|
||||||
|
return if (num < 0) handleError() else @intCast(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iteratePools(self: *const Connection, flags: []const Pool.ListFlags) !Pool.PoolIterator {
|
||||||
|
return Pool.PoolIterator.init(
|
||||||
|
c.virConnect,
|
||||||
|
Connection,
|
||||||
|
Pool.ListFlags,
|
||||||
|
self,
|
||||||
|
flags,
|
||||||
|
c.virConnectListAllStoragePools,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn numOfDomains(self: *const Connection) !u32 {
|
pub fn numOfDomains(self: *const Connection) !u32 {
|
||||||
return @intCast(c.virConnectNumOfDomains(self.conn));
|
const num = c.virConnectNumOfDomains(self.ptr);
|
||||||
|
return if (num < 0) handleError() else @intCast(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn numOfDefinedDomains(self: *const Connection) !u32 {
|
pub fn numOfDefinedDomains(self: *const Connection) !u32 {
|
||||||
return @intCast(c.virConnectNumOfDefinedDomains(self.conn));
|
const num = c.virConnectNumOfDefinedDomains(self.ptr);
|
||||||
|
return if (num < 0) handleError() else @intCast(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterateDomains(self: *const Connection, flags: []const Domain.Flags) Domain.Iterator {
|
pub fn iterateDomains(self: *const Connection, flags: []const Domain.ListFlags) !Domain.DomainIterator {
|
||||||
var list: [*]c.virDomainPtr = undefined;
|
return Domain.DomainIterator.init(
|
||||||
var flags_int: c_uint = 0;
|
c.virConnect,
|
||||||
for (flags) |f| flags_int |= @intFromEnum(f);
|
Connection,
|
||||||
const num = c.virConnectListAllDomains(self.conn, @ptrCast(&list), flags_int);
|
Domain.ListFlags,
|
||||||
|
self,
|
||||||
|
flags,
|
||||||
|
c.virConnectListAllDomains,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Pool = struct {
|
||||||
|
ptr: c.virStoragePoolPtr,
|
||||||
|
arena: heap.ArenaAllocator,
|
||||||
|
|
||||||
|
pub fn init(ptr: c.virStoragePoolPtr, allocator: mem.Allocator) Pool {
|
||||||
return .{
|
return .{
|
||||||
.list = list,
|
.ptr = ptr,
|
||||||
.num = num,
|
.arena = heap.ArenaAllocator.init(allocator),
|
||||||
.curr = 0,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn deinit(self: *const Pool) void {
|
||||||
|
self.arena.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 iterateVolumes(self: *const Pool, flags: []const ListFlags) Volume.VolumeIterator {
|
||||||
|
return Volume.VolumeIterator.init(
|
||||||
|
c.virStorageVolumePtr,
|
||||||
|
Pool,
|
||||||
|
Volume.ListFlags,
|
||||||
|
self,
|
||||||
|
flags,
|
||||||
|
c.virStoragePoolListAllVolumes,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ListFlags = enum(c_uint) {
|
||||||
|
Inactive = 1 << 0,
|
||||||
|
Active = 1 << 1,
|
||||||
|
Persistent = 1 << 2,
|
||||||
|
Transient = 1 << 3,
|
||||||
|
Autostart = 1 << 4,
|
||||||
|
NoAutostart = 1 << 5,
|
||||||
|
Dir = 1 << 6,
|
||||||
|
Fs = 1 << 7,
|
||||||
|
NetFs = 1 << 8,
|
||||||
|
Logical = 1 << 9,
|
||||||
|
Disk = 1 << 10,
|
||||||
|
Iscsi = 1 << 11,
|
||||||
|
Scsi = 1 << 12,
|
||||||
|
Mpath = 1 << 13,
|
||||||
|
Rbd = 1 << 14,
|
||||||
|
Sheepdog = 1 << 15,
|
||||||
|
Gluster = 1 << 16,
|
||||||
|
Zfs = 1 << 17,
|
||||||
|
Vstorage = 1 << 18,
|
||||||
|
IscsiDirect = 1 << 19,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PoolIterator = Iterator(Pool, c.virStoragePoolPtr, c.virStoragePoolFree);
|
||||||
|
|
||||||
|
pub const Volume = struct {
|
||||||
|
ptr: c.virStorageVolPtr,
|
||||||
|
|
||||||
|
pub fn getName(self: *const Volume) ![]const u8 {
|
||||||
|
const name = c.virStorageVolGetName(self.ptr);
|
||||||
|
defer std.c.free(name);
|
||||||
|
const str = string(name);
|
||||||
|
return if (str.len == 0) handleError() else try self.arena.allocator().dupe(u8, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ListFlags = enum(c_uint) {};
|
||||||
|
pub const CreateFlags = enum(c_uint) {
|
||||||
|
PreallocMetadata = 1 << 0,
|
||||||
|
Reflink = 1 << 1,
|
||||||
|
Validate = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VolumeIterator = Iterator(Volume, c.virStorageVolPtr, c.virStorageVolFree);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Domain = struct {
|
pub const Domain = struct {
|
||||||
|
@ -121,31 +269,10 @@ pub const Domain = struct {
|
||||||
return if (active == 0) false else true;
|
return if (active == 0) false else true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Flags = enum(c_uint) {
|
pub const ListFlags = enum(c_uint) {
|
||||||
ListDomainsActive = c.VIR_CONNECT_LIST_DOMAINS_ACTIVE,
|
Active = c.VIR_CONNECT_LIST_DOMAINS_ACTIVE,
|
||||||
ListDomainsInactive = c.VIR_CONNECT_LIST_DOMAINS_INACTIVE,
|
Inactive = c.VIR_CONNECT_LIST_DOMAINS_INACTIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Iterator = struct {
|
pub const DomainIterator = Iterator(Domain, c.virDomainPtr, c.virDomainFree);
|
||||||
list: [*]c.virDomainPtr,
|
|
||||||
num: c_int,
|
|
||||||
curr: usize,
|
|
||||||
|
|
||||||
pub fn deinit(self: *Iterator) void {
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < self.num) : (i += 1) _ = c.virDomainFree(self.list[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn first(self: *Iterator) Domain {
|
|
||||||
self.curr = 0;
|
|
||||||
return .{ .ptr = self.list[self.curr] };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next(self: *Iterator) ?Domain {
|
|
||||||
if (self.curr >= self.num) return null;
|
|
||||||
const ptr = self.list[self.curr];
|
|
||||||
self.curr += 1;
|
|
||||||
return .{ .ptr = ptr };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,44 +10,51 @@ pub fn main() !void {
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
const connection = try libvirt.Connection.connect("qemu+ssh://jeeves@evil.lan/system", allocator);
|
const connection = try libvirt.Connection.connect("qemu:///system", allocator);
|
||||||
defer connection.close();
|
defer connection.close();
|
||||||
|
|
||||||
var nix = process.Child.init(&[_][]const u8{ "nix", "build", ".#volume" }, allocator);
|
var flake_dir = try fs.cwd().openDir("flakes/windows/test", .{});
|
||||||
nix.cwd_dir = try fs.cwd().openDir("flakes/windows/test", .{});
|
defer flake_dir.close();
|
||||||
|
|
||||||
|
var nix = process.Child.init(&[_][]const u8{ "nix", "build", ".#volume", "-o", "volume" }, allocator);
|
||||||
|
nix.cwd_dir = flake_dir;
|
||||||
|
_ = try nix.spawnAndWait();
|
||||||
|
nix.argv = &[_][]const u8{ "nix", "build", ".#beforeInstall", "-o", "beforeInstall" };
|
||||||
|
_ = try nix.spawnAndWait();
|
||||||
|
nix.argv = &[_][]const u8{ "nix", "build", ".#afterInstall", "-o", "afterInstall" };
|
||||||
|
_ = try nix.spawnAndWait();
|
||||||
|
nix.argv = &[_][]const u8{ "nix", "build", ".#beforeBoot", "-o", "beforeBoot" };
|
||||||
|
_ = try nix.spawnAndWait();
|
||||||
|
nix.argv = &[_][]const u8{ "nix", "build", ".#afterBoot", "-o", "afterBoot" };
|
||||||
_ = try nix.spawnAndWait();
|
_ = try nix.spawnAndWait();
|
||||||
|
|
||||||
// const uri = try connection.getURI();
|
// const volume_def = try flake_dir.openFile("volume", .{});
|
||||||
// defer connection.freeURI(uri);
|
// defer volume_def.close();
|
||||||
// std.debug.print("uri: {s}\n", .{uri});
|
// const volume_xml = try volume_def.readToEndAlloc(allocator, 1024 * 1024);
|
||||||
|
// defer allocator.free(volume_xml);
|
||||||
|
// const volume = try connection.defineVolume(volume_xml);
|
||||||
|
|
||||||
// const num_active = try connection.numOfDomains();
|
// --------------
|
||||||
// const num_inactive = try connection.numOfDefinedDomains();
|
|
||||||
// std.debug.print("active: {d}, inactive: {d}\n", .{ num_active, num_inactive });
|
|
||||||
|
|
||||||
// var domain_iter = connection.iterateDomains(&[_]libvirt.Domain.Flags{
|
const uri = try connection.getURI();
|
||||||
// libvirt.Domain.Flags.ListDomainsActive,
|
defer connection.freeURI(uri);
|
||||||
// libvirt.Domain.Flags.ListDomainsInactive,
|
std.debug.print("uri: {s}\n", .{uri});
|
||||||
// });
|
|
||||||
// defer domain_iter.deinit();
|
|
||||||
|
|
||||||
// while (domain_iter.next()) |domain| {
|
const num_active = try connection.numOfDomains();
|
||||||
// const active = domain.isActive();
|
const num_inactive = try connection.numOfDefinedDomains();
|
||||||
// const name = domain.getName();
|
std.debug.print("active: {d}, inactive: {d}\n", .{ num_active, num_inactive });
|
||||||
// std.debug.print("name: {s}, active: {any}\n", .{ name, active });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var flake = try fs.cwd().createFile("flake.nix", .{});
|
var domain_iter = try connection.iterateDomains(&[_]libvirt.Domain.ListFlags{
|
||||||
// defer flake.close();
|
libvirt.Domain.ListFlags.Active,
|
||||||
// try flake.writeAll(
|
libvirt.Domain.ListFlags.Inactive,
|
||||||
// \\{
|
});
|
||||||
// \\ description = "vm-flake";
|
defer domain_iter.deinit();
|
||||||
// \\ inputs.oslib.url = "git+https://git.jeevio.xyz/jeeves/oslib";
|
|
||||||
// \\ outputs = { self, oslib }: oslib.vmFlake {
|
while (domain_iter.next()) |domain| {
|
||||||
// \\
|
const active = domain.isActive();
|
||||||
// \\ };
|
const name = domain.getName();
|
||||||
// \\}
|
std.debug.print("name: {s}, active: {any}\n", .{ name, active });
|
||||||
// );
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DomainSpec = struct {
|
pub const DomainSpec = struct {
|
||||||
|
|
Loading…
Add table
Reference in a new issue