$OpenBSD$
Index: qga/main.c
--- qga/main.c.orig
+++ qga/main.c
@@ -46,9 +46,15 @@
#endif
#ifndef _WIN32
+#ifdef BSD_GUEST_AGENT
+#define QGA_VIRTIO_PATH_DEFAULT "/dev/vtcon/org.qemu.guest_agent.0"
+#define QGA_STATE_RELATIVE_DIR "run"
+#define QGA_SERIAL_PATH_DEFAULT "/dev/cua01"
+#else
#define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
#define QGA_STATE_RELATIVE_DIR "run"
#define QGA_SERIAL_PATH_DEFAULT "/dev/ttyS0"
+#endif
#else
#define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0"
#define QGA_STATE_RELATIVE_DIR "qemu-ga"
@@ -1471,7 +1477,11 @@ int main(int argc, char **argv)
}
if (config->method == NULL) {
+#ifdef BSD_GUEST_AGENT
+ config->method = g_strdup("isa-serial");
+#else
config->method = g_strdup("virtio-serial");
+#endif
}
socket_activation = check_socket_activation();
$OpenBSD$
Index: qga/commands-posix.c
--- qga/commands-posix.c.orig
+++ qga/commands-posix.c
@@ -28,6 +28,26 @@
#include "qemu/cutils.h"
#include "commands-common.h"
+#ifdef BSD_GUEST_AGENT
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <sys/statvfs.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netinet/if_ether.h>
+#include <net/if_var.h>
+
+#ifdef __OpenBSD__
+#define SIOCGIFLLADDR _IOWR('i', 32, struct ifreq) /* get link level addr */
+#define SIOCGHWADDR SIOCGIFLLADDR
+#endif
+#endif
+
#ifdef HAVE_UTMPX
#include <utmpx.h>
#endif
@@ -85,14 +105,23 @@ void qmp_guest_shutdown(bool has_mode, const char *mod
{
const char *shutdown_flag;
Error *local_err = NULL;
+ char *shutdown_mode;
pid_t pid;
int status;
slog("guest-shutdown called, mode: %s", mode);
if (!has_mode || strcmp(mode, "powerdown") == 0) {
+#ifdef BSD_GUEST_AGENT
+ shutdown_flag = "-p";
+#else
shutdown_flag = "-P";
+#endif
} else if (strcmp(mode, "halt") == 0) {
+#ifdef BSD_GUEST_AGENT
+ shutdown_flag = "-h";
+#else
shutdown_flag = "-H";
+#endif
} else if (strcmp(mode, "reboot") == 0) {
shutdown_flag = "-r";
} else {
@@ -109,8 +138,15 @@ void qmp_guest_shutdown(bool has_mode, const char *mod
reopen_fd_to_null(1);
reopen_fd_to_null(2);
+ shutdown_mode = g_strdup_printf("hypervisor initiated %s", mode);
+
+#ifdef BSD_GUEST_AGENT
+ execle("/sbin/shutdown", "-h", shutdown_flag, "+0",
+ shutdown_mode, (char*)NULL, environ);
+#else
execle("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0",
- "hypervisor initiated shutdown", (char *)NULL, environ);
+ shutdown_mode, (char *)NULL, environ);
+#endif
_exit(EXIT_FAILURE);
} else if (pid < 0) {
error_setg_errno(errp, errno, "failed to create child process");
@@ -153,9 +189,11 @@ int64_t qmp_guest_get_time(Error **errp)
void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
{
int ret;
+#ifndef BSD_GUEST_AGENT
int status;
pid_t pid;
Error *local_err = NULL;
+#endif
struct timeval tv;
static const char hwclock_path[] = "/sbin/hwclock";
static int hwclock_available = -1;
@@ -194,6 +232,7 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns
}
}
+#ifndef BSD_GUEST_AGENT
/* Now, if user has passed a time to set and the system time is set, we
* just need to synchronize the hardware clock. However, if no time was
* passed, user is requesting the opposite: set the system time from the
@@ -230,6 +269,7 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns
error_setg(errp, "hwclock failed to set hardware clock to system time");
return;
}
+#endif
}
typedef enum {
@@ -789,7 +829,7 @@ static void build_fs_mount_list(FsMountList *mounts, E
QTAILQ_INSERT_TAIL(mounts, mount, next);
}
- free(line);
+ g_free(line);
fclose(fp);
}
@@ -2939,24 +2979,255 @@ void qmp_guest_suspend_hybrid(Error **errp)
error_setg(errp, QERR_UNSUPPORTED);
}
+#ifndef BSD_GUEST_AGENT
GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
{
error_setg(errp, QERR_UNSUPPORTED);
return NULL;
}
+#else
+static GuestNetworkInterfaceList *
+guest_find_interface(GuestNetworkInterfaceList *head,
+ const char *name)
+{
+ for (; head; head = head->next) {
+ if (strcmp(head->value->name, name) == 0) {
+ break;
+ }
+ }
+ return head;
+}
+static int guest_get_network_stats(const char *name,
+ GuestNetworkInterfaceStat *stats)
+{
+ return -1;
+}
+
+GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
+{
+ GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
+ struct ifaddrs *ifap, *ifa;
+
+ if (getifaddrs(&ifap) < 0) {
+ error_setg_errno(errp, errno, "getifaddrs failed");
+ goto error;
+ }
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ GuestNetworkInterfaceList *info;
+ GuestIpAddressList **address_list = NULL, *address_item = NULL;
+ GuestNetworkInterfaceStat *interface_stat = NULL;
+ char addr4[INET_ADDRSTRLEN];
+ char addr6[INET6_ADDRSTRLEN];
+ int sock;
+ struct ifreq ifr;
+ // struct ifnet ifp;
+ // struct if_data ifd;
+ // unsigned char *mac_addr;
+ char mac_addr[18]="00:00:00:00:00:00"; // = char[18];
+ void *p;
+
+ g_debug("Processing %s interface", ifa->ifa_name);
+
+ info = guest_find_interface(head, ifa->ifa_name);
+
+ if (!info) {
+ info = g_malloc0(sizeof(*info));
+ info->value = g_malloc0(sizeof(*info->value));
+ info->value->name = g_strdup(ifa->ifa_name);
+
+ if (!cur_item) {
+ head = cur_item = info;
+ } else {
+ cur_item->next = info;
+ cur_item = info;
+ }
+ }
+
+ if (!info->value->has_hardware_address &&
+ ifa->ifa_flags & SIOCGHWADDR) {
+ /* we haven't obtained HW address yet */
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ error_setg_errno(errp, errno, "failed to create socket");
+ goto error;
+ }
+ close(sock);
+
+ memset(&ifr, 0, sizeof(ifr));
+ pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
+ // memset(&ifp, 0, sizeof(ifp));
+ // memset(&ifd, 0, sizeof(ifd));
+
+ if (ifa->ifa_addr->sa_family == AF_LINK) {
+ struct sockaddr_dl *sdl =
+ (struct sockaddr_dl *)ifa->ifa_addr;
+
+ info->value->has_hardware_address = false;
+
+ if (sdl->sdl_type == IFT_ETHER &&
+ sdl->sdl_alen == ETHER_ADDR_LEN) {
+ snprintf(mac_addr, 18, "%s", ether_ntoa((struct ether_addr *)LLADDR(sdl)));
+ info->value->has_hardware_address = true;
+ }
+ else
+ {
+ info->value->has_hardware_address = true;
+ }
+ info->value->hardware_address = g_strdup_printf("%s", mac_addr);
+ }
+
+ }
+
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_INET) {
+ /* interface with IPv4 address */
+ p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
+ if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
+ error_setg_errno(errp, errno, "inet_ntop failed");
+ goto error;
+ }
+
+ address_item = g_malloc0(sizeof(*address_item));
+ address_item->value = g_malloc0(sizeof(*address_item->value));
+ address_item->value->ip_address = g_strdup(addr4);
+ address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
+
+ if (ifa->ifa_netmask) {
+ /* Count the number of set bits in netmask.
+ * This is safe as '1' and '0' cannot be shuffled in netmask. */
+ p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
+ address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
+ }
+ } else if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_INET6) {
+ /* interface with IPv6 address */
+ p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
+ error_setg_errno(errp, errno, "inet_ntop failed");
+ goto error;
+ }
+
+ address_item = g_malloc0(sizeof(*address_item));
+ address_item->value = g_malloc0(sizeof(*address_item->value));
+ address_item->value->ip_address = g_strdup(addr6);
+ address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
+
+ if (ifa->ifa_netmask) {
+ /* Count the number of set bits in netmask.
+ * This is safe as '1' and '0' cannot be shuffled in netmask. */
+ p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
+ address_item->value->prefix =
+ ctpop32(((uint32_t *) p)[0]) +
+ ctpop32(((uint32_t *) p)[1]) +
+ ctpop32(((uint32_t *) p)[2]) +
+ ctpop32(((uint32_t *) p)[3]);
+ }
+ }
+
+ if (!address_item) {
+ continue;
+ }
+
+ address_list = &info->value->ip_addresses;
+
+ while (*address_list && (*address_list)->next) {
+ address_list = &(*address_list)->next;
+ }
+
+ if (!*address_list) {
+ *address_list = address_item;
+ } else {
+ (*address_list)->next = address_item;
+ }
+
+ info->value->has_ip_addresses = true;
+
+ if (!info->value->has_statistics) {
+ interface_stat = g_malloc0(sizeof(*interface_stat));
+ if (guest_get_network_stats(info->value->name,
+ interface_stat) == -1) {
+ info->value->has_statistics = false;
+ g_free(interface_stat);
+ } else {
+ info->value->statistics = interface_stat;
+ info->value->has_statistics = true;
+ }
+ }
+ }
+
+ freeifaddrs(ifap);
+ return head;
+
+error:
+ freeifaddrs(ifap);
+ qapi_free_GuestNetworkInterfaceList(head);
+ return NULL;
+}
+#endif // BSD_GUEST_AGENT
+
+#ifndef BSD_GUEST_AGENT
GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
{
error_setg(errp, QERR_UNSUPPORTED);
return NULL;
}
+#else
+GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
+{
+ int64_t current;
+ GuestLogicalProcessorList *head, **link;
+ long sc_max;
+ Error *local_err = NULL;
+ int Query[2];
+ int NumCpu = 0;
+ size_t Length = sizeof(NumCpu);
+ Query[0] = CTL_HW;
+ Query[1] = HW_NCPU;
+ current = 0;
+ head = NULL;
+ link = &head;
+ if (sysctl(Query, 2, &NumCpu, &Length, NULL, 0) == -1) {
+ error_setg(errp, "sysctl get CTL_HW.HW_NCPU failed");
+ }
+ sc_max = NumCpu;
+
+ while (local_err == NULL && current < sc_max) {
+ GuestLogicalProcessor *vcpu;
+ GuestLogicalProcessorList *entry;
+ int64_t id = current++;
+ vcpu = g_malloc0(sizeof *vcpu);
+ vcpu->logical_id = id;
+ vcpu->has_can_offline = false; /* lolspeak ftw */
+ vcpu->online = true;
+ vcpu->can_offline = false;
+ entry = g_malloc0(sizeof *entry);
+ entry->value = vcpu;
+ *link = entry;
+ link = &entry->next;
+ }
+
+ if (local_err == NULL) {
+ /* there's no guest with zero VCPUs */
+ g_assert(head != NULL);
+ return head;
+ }
+
+ qapi_free_GuestLogicalProcessorList(head);
+ error_propagate(errp, local_err);
+ return NULL;
+}
+#endif // BSD_GUEST_AGENT
+
int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
{
error_setg(errp, QERR_UNSUPPORTED);
return -1;
}
+#ifndef BSD_GUEST_AGENT
void qmp_guest_set_user_password(const char *username,
const char *password,
bool crypted,
@@ -2965,6 +3236,114 @@ void qmp_guest_set_user_password(const char *username,
error_setg(errp, QERR_UNSUPPORTED);
}
+#else
+void qmp_guest_set_user_password(const char *username,
+ const char *password,
+ bool crypted,
+ Error **errp)
+{
+ Error *local_err = NULL;
+ char *pw_path = NULL;
+ pid_t pid;
+ int status;
+ int datafd[2] = { -1, -1 };
+ char *rawpasswddata = NULL;
+ size_t rawpasswdlen;
+ char *chpasswddata = NULL;
+ size_t chpasswdlen;
+
+ rawpasswddata = (char *)qbase64_decode(password, -1, &rawpasswdlen, errp);
+ if (!rawpasswddata) {
+ return;
+ }
+
+ rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1);
+ rawpasswddata[rawpasswdlen] = '\0';
+
+ if (strchr(rawpasswddata, '\n')) {
+ error_setg(errp, "forbidden characters in raw password");
+ goto out;
+ }
+
+ if (strchr(username, '\n') ||
+ strchr(username, ':')) {
+ error_setg(errp, "forbidden characters in username");
+ goto out;
+ }
+
+ chpasswddata = g_strdup_printf("%s", rawpasswddata);
+ chpasswdlen = strlen(chpasswddata);
+
+ pw_path = g_find_program_in_path("pw");
+
+ if (!pw_path) {
+ error_setg(errp, "cannot find 'pw' program in PATH");
+ goto out;
+ }
+
+ if (pipe(datafd) < 0) {
+ error_setg(errp, "cannot create pipe FDs");
+ goto out;
+ }
+
+ pid = fork();
+ if (pid == 0) {
+ close(datafd[1]);
+ /* child */
+ setsid();
+ dup2(datafd[0], 0);
+ reopen_fd_to_null(1);
+ reopen_fd_to_null(2);
+
+ if (crypted) {
+ execle(pw_path, "pw", "usermod", username, "-H", "0", (char*)NULL, environ);
+ } else {
+ execle(pw_path, "pw", "usermod", username, "-h", "0", (char*)NULL, environ);
+ }
+ _exit(EXIT_FAILURE);
+ } else if (pid < 0) {
+ error_setg_errno(errp, errno, "failed to create child process");
+ goto out;
+ }
+ close(datafd[0]);
+ datafd[0] = -1;
+
+ if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) {
+ error_setg_errno(errp, errno, "cannot write new account password");
+ goto out;
+ }
+ close(datafd[1]);
+ datafd[1] = -1;
+
+ ga_wait_child(pid, &status, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ goto out;
+ }
+
+ if (!WIFEXITED(status)) {
+ error_setg(errp, "child process has terminated abnormally");
+ goto out;
+ }
+
+ if (WEXITSTATUS(status)) {
+ error_setg(errp, "child process has failed to set user password");
+ goto out;
+ }
+
+out:
+ g_free(chpasswddata);
+ g_free(rawpasswddata);
+ g_free(pw_path);
+ if (datafd[0] != -1) {
+ close(datafd[0]);
+ }
+ if (datafd[1] != -1) {
+ close(datafd[1]);
+ }
+}
+#endif // BSD_GUEST_AGENT
+
GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
{
error_setg(errp, QERR_UNSUPPORTED);
@@ -2988,12 +3367,258 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(
#if !defined(CONFIG_FSFREEZE)
+#ifndef BSD_GUEST_AGENT
GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
{
error_setg(errp, QERR_UNSUPPORTED);
return NULL;
}
+#else
+/* ===================================================================== */
+typedef struct FsMount {
+ char *dirname;
+ char *devtype;
+ char *size;
+ char *used;
+ char *free;
+ char *load;
+ char *mntpoint;
+ unsigned int devmajor, devminor;
+ QTAILQ_ENTRY(FsMount) next;
+} FsMount;
+
+typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList;
+
+static void free_fs_mount_list(FsMountList *mounts)
+{
+ FsMount *mount, *temp;
+
+ if (!mounts) {
+ return;
+ }
+
+ QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
+ QTAILQ_REMOVE(mounts, mount, next);
+ g_free(mount->dirname);
+ g_free(mount->devtype);
+ g_free(mount->size);
+ g_free(mount->used);
+ g_free(mount->free);
+ g_free(mount->load);
+ g_free(mount->mntpoint);
+ g_free(mount);
+ }
+}
+
+
+//#define BUFSIZE 2048
+
+static void build_fs_mount_list(FsMountList *mounts, Error **errp)
+{
+ FsMount *mount;
+#ifdef __OpenBSD__
+ char const *dfcmd = "/bin/df";
+#else // defined(__OpenBSD__)
+ char const *dfcmd = "/bin/df -hT";
+#endif // defined(__OpenBSD__)
+ //char buf[BUFSIZE];
+
+ FILE *fp;
+ char *line = NULL;
+ //, *dash;
+ size_t n;
+ int ret;
+ //, dir_s, dir_e, type_s, type_e, dev_s, dev_e;
+ char dev_name[128], size[12], used[12], free[12], load[10], mounted[128];
+#ifndef __OpenBSD__
+ char fstype[12] = "";
+#endif // !defined(__OpenBSD__)
+ //int dev_name, fstype, size, used, free, load, mounted;
+
+ if ((fp = popen(dfcmd, "r")) == NULL) {
+ g_debug("Cannot open '%s'!!\n", dfcmd);
+ error_setg_errno(errp, errno,
+ "failed to create child process for command: %s",
+ dfcmd);
+ return;
+ }
+
+ while (getline(&line, &n, fp) != -1) {
+ //g_debug("line '%s'", line);
+#ifdef __OpenBSD__
+ ret = sscanf(line, "%127s%11s%11s%11s%9s%127s",
+ dev_name, size, used, free, load, mounted);
+#else // defined(__OpenBSD__)
+ ret = sscanf(line, "%127s%11s%11s%11s%11s%9s%127s",
+ dev_name, fstype, size, used, free, load, mounted);
+ //g_debug("ret %d, dev_name '%s', fstype '%s', size '%s', used '%s', free '%s', load '%s', mounted '%s'",
+ // ret, dev_name, fstype, size, used, free, load, mounted);
+#endif // defined(__OpenBSD__)
+ if (g_str_equal(dev_name, "Filesystem")
+#ifndef __OpenBSD__
+ ||g_str_equal(fstype,"devfs")
+ ||g_str_equal(fstype,"procfs")
+ ||g_str_equal(fstype,"fdescfs")
+#endif // !defined(__OpenBSD__)
+ ) {
+ continue;
+ }
+
+#ifdef __OpenBSD__
+ if (ret < 6) {
+#else // defined(__OpenBSD__)
+ if (ret < 7) {
+#endif // defined(__OpenBSD__)
+ continue;
+ }
+
+ mount = g_new0(FsMount, 1);
+ mount->dirname = g_strdup(dev_name);
+#ifndef __OpenBSD__
+ mount->devtype = g_strdup(fstype);
+#endif // defined(__OpenBSD__)
+ mount->free = g_strdup(free);
+ mount->load = g_strdup(load);
+ mount->size = g_strdup(size);
+ mount->used = g_strdup(used);
+ mount->mntpoint = g_strdup(mounted);
+ mount->devmajor = 0;
+ mount->devminor = 0;
+
+ QTAILQ_INSERT_TAIL(mounts, mount, next);
+ }
+ g_free(line);
+
+ fclose(fp);
+}
+
+#ifdef __OpenBSD__
+
+static void add_type_fs_mount_list(FsMountList *mounts, Error **errp)
+{
+ FILE *fp;
+ char const *mountcmd = "/sbin/mount";
+ char *line = NULL;
+ size_t n;
+ int ret;
+ char mnt_fsname[128], mnt_dir[128], mnt_type[32], mnt_opts[128];
+ struct FsMount *mount;
+
+ // get mounts from mount command
+ if ((fp = popen(mountcmd, "r")) == NULL) {
+ g_debug("Cannot open '%s'!!\n", mountcmd);
+ error_setg_errno(errp, errno, "failed to create child process for command: %s", mountcmd);
+ return;
+ }
+
+ // loop through mounts from mount command
+ while (getline(&line, &n, fp) != -1) {
+ //g_debug("line '%s'", line);
+
+ ret = sscanf(line, "%127s on %127s type %31s (%127s)",
+ mnt_fsname, mnt_dir, mnt_type, mnt_opts);
+ //g_debug("ret %d, fsname '%s', dir '%s', type '%s', opts '%s'",
+ // ret, mnt_fsname, mnt_dir, mnt_type, mnt_opts);
+
+ if (4 != ret ||
+ '/' != mnt_fsname[0] ||
+ '/' != mnt_dir[0] ||
+ g_str_equal("smbfs", mnt_type) ||
+ g_str_equal("cifs", mnt_type)) {
+ continue;
+ }
+
+ // find mount in supplied mounts list and update device type
+ QTAILQ_FOREACH(mount, mounts, next) {
+ if (NULL == mount->devtype && g_str_equal(mount->dirname, mnt_fsname)) {
+ mount->devtype = g_strdup(mnt_type);
+ break;
+ }
+ }
+ }
+ g_free(line);
+
+ fclose(fp);
+}
+
+#endif // defined(__OpenBSD__)
+
+/* ======================================================= */
+
+
+/* Return a list of the disk device(s)' info which @mount lies on */
+static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount,
+ Error **errp)
+{
+ GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs));
+ struct statvfs buf;
+ unsigned long used, nonroot_total, fr_size;
+
+ fs->name = g_strdup(mount->dirname);
+ fs->mountpoint = g_strdup(mount->mntpoint);
+ fs->type = g_strdup(mount->devtype);
+
+ if (statvfs(fs->mountpoint, &buf) == 0) {
+ fr_size = buf.f_frsize;
+ used = buf.f_blocks - buf.f_bfree;
+ nonroot_total = used + buf.f_bavail;
+ fs->used_bytes = used * fr_size;
+ fs->total_bytes = nonroot_total * fr_size;
+
+ fs->has_total_bytes = true;
+ fs->has_used_bytes = true;
+ }
+
+ //g_free(devpath);
+
+ return fs;
+}
+
+GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
+{
+ FsMountList mounts;
+ struct FsMount *mount;
+ GuestFilesystemInfoList *new, *ret = NULL;
+ Error *local_err = NULL;
+
+ QTAILQ_INIT(&mounts);
+
+ g_debug("Entering to guest_get_fsinfo");
+ build_fs_mount_list(&mounts, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return NULL;
+ }
+
+#ifdef __OpenBSD__
+ add_type_fs_mount_list(&mounts, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return NULL;
+ }
+#endif // defined(__OpenBSD__)
+
+ QTAILQ_FOREACH(mount, &mounts, next) {
+ //g_debug("Building guest fsinfo for '%s'", mount->dirname);
+ //g_debug("Devtype '%s'", mount->devtype);
+ new = g_malloc0(sizeof(*ret));
+ new->value = build_guest_fsinfo(mount, &local_err);
+ new->next = ret;
+ ret = new;
+ if (local_err) {
+ error_propagate(errp, local_err);
+ qapi_free_GuestFilesystemInfoList(ret);
+ ret = NULL;
+ break;
+ }
+ }
+
+ free_fs_mount_list(&mounts);
+ return ret;
+}
+#endif // BSD_GUEST_AGENT
+
GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
{
error_setg(errp, QERR_UNSUPPORTED);
@@ -3046,6 +3671,7 @@ GList *ga_command_blacklist_init(GList *blacklist)
{
#if !defined(__linux__)
{
+#ifndef BSD_GUEST_AGENT
const char *list[] = {
"guest-suspend-disk", "guest-suspend-ram",
"guest-suspend-hybrid", "guest-network-get-interfaces",
@@ -3053,6 +3679,15 @@ GList *ga_command_blacklist_init(GList *blacklist)
"guest-get-memory-blocks", "guest-set-memory-blocks",
"guest-get-memory-block-size", "guest-get-memory-block-info",
NULL};
+#else
+ const char *list[] = {
+ "guest-suspend-disk", "guest-suspend-ram",
+ "guest-suspend-hybrid",
+ "guest-set-vcpus",
+ "guest-get-memory-blocks", "guest-set-memory-blocks",
+ "guest-get-memory-block-size", "guest-get-memory-block-info",
+ NULL};
+#endif // BSD_GUEST_AGENT
char **p = (char **)list;
while (*p) {
@@ -3063,11 +3698,18 @@ GList *ga_command_blacklist_init(GList *blacklist)
#if !defined(CONFIG_FSFREEZE)
{
+#ifndef BSD_GUEST_AGENT
const char *list[] = {
"guest-get-fsinfo", "guest-fsfreeze-status",
"guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list",
"guest-fsfreeze-thaw", "guest-get-fsinfo",
"guest-get-disks", NULL};
+#else
+ const char *list[] = {
+ "guest-fsfreeze-status",
+ "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list",
+ "guest-fsfreeze-thaw", NULL};
+#endif // BSD_GUEST_AGENT
char **p = (char **)list;
while (*p) {
On Fri, Apr 09, 2021 at 04:53:17PM +0200, Landry Breuil wrote:
> On Thu, Apr 08, 2021 at 06:19:58PM +0200, Jeroen Derks wrote:
> > On 08/04/2021 14:35, Landry Breuil wrote:>
> > > well that's very nice, definitely interested in those freebsd patches !
> > > not 100% sure those will get in 6.9 though as we're slowly moving towards
> > > lock, but send them anyway, and we'll figure out what we can do from
> > > there. I suppose those come from https://github.com/aborche/qemu-guest-agent ?
> >
> > Indeed, here they are (if there's interest I can also send a diff of the patches
> > compared to the FreeBSD patches to see what I've done):
>
> oh, well that looks nice. A bit rought around the edges imo, and im not
> sure we want to maintain a rather large patch like this in the
> portstree. according to https://wiki.qemu.org/Contribute/SubmitAPatch i
> think it should be pushed upstream, do you have any idea if the original
> freebsd patches were proposed there or qemu-devel list ?
>
> i'll let brad decide, but as is this doesnt apply as-is against 6.0 rcs
> which we're testing for post-6.9....
so i've backported your patch on top of brad's 6.0rc2 qemu update, and
fixed things here and there, removed commented code, and yeah get-vcpus,
get-fsinfo and network-get-interfaces seems to work fine !
i'm not sure we want the set user password thing in the patch, as it
wont work on openbsd (uses the pw command which is freebsd ?). It's also
a bit gross to exec df to fetch the mount point list..
im also not sure what to do with the localstatedir thing (the -t flag),
i've added --localstatedir=/tmp/ to CONFIGURE_ARGS but that feels wrong.
qga needs it to store its qga.state file and probably to store temp
files..
to build the 6.0rc2 update with those two attached patches (to drop
under patches/), just add to the port Makefile:
# qemu-ga support for more operations
CFLAGS+= -DBSD_GUEST_AGENT
Landry
[08:50] c64:~/mystuff/emulators/qemu/ $mkdir /tmp/run
[08:50] c64:~/mystuff/emulators/qemu/ $doas qemu-ga -v
1618037419.280400: debug: disabling command: guest-suspend-disk
1618037419.280439: debug: disabling command: guest-suspend-ram
1618037419.280452: debug: disabling command: guest-suspend-hybrid
1618037419.280463: debug: disabling command: guest-set-vcpus
1618037419.280474: debug: disabling command: guest-get-memory-blocks
1618037419.280485: debug: disabling command: guest-set-memory-blocks
1618037419.280496: debug: disabling command: guest-get-memory-block-size
1618037419.280507: debug: disabling command: guest-get-memory-block-info
1618037419.280519: debug: disabling command: guest-fsfreeze-status
1618037419.280530: debug: disabling command: guest-fsfreeze-freeze
1618037419.280541: debug: disabling command: guest-fsfreeze-freeze-list
1618037419.280551: debug: disabling command: guest-fsfreeze-thaw
1618037419.280564: debug: disabling command: guest-fstrim
1618037419.280578: debug: disabling command: guest-get-devices
root@openbsd-amd64:~# qm agent 100 get-vcpus
[
{
"logical-id" : 0,
"online" : true
},
{
...
{
"logical-id" : 7,
"online" : true
}
]
...
root@openbsd-amd64:~# qm agent 100 get-fsinfo
[
{
"disk" : [],
"mountpoint" : "/build",
"name" : "/dev/sd1a",
"total-bytes" : 50195449856,
"type" : "ffs",
"used-bytes" : 28191496192
},
{
"disk" : [],
"mountpoint" : "/var",
"name" : "/dev/sd0e",
"total-bytes" : 4011888640,
"type" : "ffs",
"used-bytes" : 3049684992
},
...
root@openbsd-amd64:~# qm agent 100 network-get-interfaces
[
{
"hardware-address" : "a2:6e:16:9f:42:70",
"ip-addresses" : [
{
"ip-address" : "10.0.3.254",
"ip-address-type" : "ipv4",
"prefix" : 24
}
],
"name" : "vio0"
},
{
"hardware-address" : "be:10:50:5f:d0:78",
"ip-addresses" : [
{
"ip-address" : "10.0.2.2",
"ip-address-type" : "ipv4",
"prefix" : 28
}
],
"name" : "vio1"
},
...
No comments:
Post a Comment