mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
ch: start a new thread for handling ch events
Use a FIFO(named pipe) for --event-monitor option in CH. Introduce a new thread, `virCHEventHandlerLoop`, to continuously monitor and handle events from cloud-hypervisor. Signed-off-by: Purna Pavan Chandra Aekkaladevi <paekkaladevi@linux.microsoft.com> Co-authored-by: Vineeth Pillai <viremana@linux.microsoft.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
d7c9660b15
commit
3015c28c1e
79
src/ch/ch_events.c
Normal file
79
src/ch/ch_events.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright Microsoft Corp. 2024
|
||||
*
|
||||
* ch_events.c: Handle Cloud-Hypervisor events
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "ch_domain.h"
|
||||
#include "ch_events.h"
|
||||
#include "ch_process.h"
|
||||
#include "virfile.h"
|
||||
#include "virlog.h"
|
||||
|
||||
VIR_LOG_INIT("ch.ch_events");
|
||||
|
||||
|
||||
static void
|
||||
virCHEventHandlerLoop(void *data)
|
||||
{
|
||||
virCHMonitor *mon = data;
|
||||
virDomainObj *vm = NULL;
|
||||
|
||||
/* Obtain a vm reference */
|
||||
vm = virObjectRef(mon->vm);
|
||||
|
||||
VIR_DEBUG("%s: Event handler loop thread starting", vm->def->name);
|
||||
|
||||
while (g_atomic_int_get(&mon->event_handler_stop) == 0) {
|
||||
VIR_DEBUG("%s: Reading events from event monitor file", vm->def->name);
|
||||
/* Read and process events here */
|
||||
}
|
||||
|
||||
virObjectUnref(vm);
|
||||
VIR_DEBUG("%s: Event handler loop thread exiting", vm->def->name);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
virCHStartEventHandler(virCHMonitor *mon)
|
||||
{
|
||||
g_autofree char *name = NULL;
|
||||
name = g_strdup_printf("ch-evt-%d", mon->pid);
|
||||
|
||||
virObjectRef(mon);
|
||||
if (virThreadCreateFull(&mon->event_handler_thread,
|
||||
false,
|
||||
virCHEventHandlerLoop,
|
||||
name,
|
||||
false,
|
||||
mon) < 0) {
|
||||
virObjectUnref(mon);
|
||||
return -1;
|
||||
}
|
||||
virObjectUnref(mon);
|
||||
|
||||
g_atomic_int_set(&mon->event_handler_stop, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
virCHStopEventHandler(virCHMonitor *mon)
|
||||
{
|
||||
g_atomic_int_set(&mon->event_handler_stop, 1);
|
||||
}
|
26
src/ch/ch_events.h
Normal file
26
src/ch/ch_events.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright Microsoft Corp. 2024
|
||||
*
|
||||
* ch_events.h: header file for handling Cloud-Hypervisor events
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ch_monitor.h"
|
||||
|
||||
int virCHStartEventHandler(virCHMonitor *mon);
|
||||
void virCHStopEventHandler(virCHMonitor *mon);
|
@ -20,12 +20,14 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "ch_conf.h"
|
||||
#include "ch_events.h"
|
||||
#include "ch_interface.h"
|
||||
#include "ch_monitor.h"
|
||||
#include "domain_interface.h"
|
||||
@ -542,6 +544,7 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
g_autoptr(virCHMonitor) mon = NULL;
|
||||
g_autoptr(virCommand) cmd = NULL;
|
||||
int socket_fd = 0;
|
||||
int event_monitor_fd;
|
||||
|
||||
if (virCHMonitorInitialize() < 0)
|
||||
return NULL;
|
||||
@ -549,6 +552,9 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
if (!(mon = virObjectLockableNew(virCHMonitorClass)))
|
||||
return NULL;
|
||||
|
||||
/* avoid VIR_FORCE_CLOSE()-ing garbage fd value in virCHMonitorClose */
|
||||
mon->eventmonitorfd = -1;
|
||||
|
||||
if (!vm->def) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("VM is not defined"));
|
||||
@ -557,8 +563,6 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
|
||||
/* prepare to launch Cloud-Hypervisor socket */
|
||||
mon->socketpath = g_strdup_printf("%s/%s-socket", cfg->stateDir, vm->def->name);
|
||||
mon->eventmonitorpath = g_strdup_printf("%s/%s-event-monitor",
|
||||
cfg->stateDir, vm->def->name);
|
||||
if (g_mkdir_with_parents(cfg->stateDir, 0777) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Cannot create socket directory '%1$s'"),
|
||||
@ -573,6 +577,27 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Event monitor file to listen for VM state changes */
|
||||
mon->eventmonitorpath = g_strdup_printf("%s/%s-event-monitor-fifo",
|
||||
cfg->stateDir, vm->def->name);
|
||||
if (virFileExists(mon->eventmonitorpath)) {
|
||||
VIR_WARN("Monitor file (%s) already exists, trying to delete!",
|
||||
mon->eventmonitorpath);
|
||||
if (virFileRemove(mon->eventmonitorpath, -1, -1) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Failed to remove the file: %1$s"),
|
||||
mon->eventmonitorpath);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (mkfifo(mon->eventmonitorpath, S_IWUSR | S_IRUSR) < 0 &&
|
||||
errno != EEXIST) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Cannot create monitor FIFO"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmd = virCommandNew(vm->def->emulator);
|
||||
virCommandSetOutputFD(cmd, &logfile);
|
||||
virCommandSetErrorFD(cmd, &logfile);
|
||||
@ -597,12 +622,35 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
if (virCommandRunAsync(cmd, &mon->pid) < 0)
|
||||
return NULL;
|
||||
|
||||
/* get a curl handle */
|
||||
mon->handle = curl_easy_init();
|
||||
/* open the reader end of fifo before start Event Handler */
|
||||
while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
|
||||
if (errno == EINTR) {
|
||||
/* 100 milli seconds */
|
||||
g_usleep(100000);
|
||||
continue;
|
||||
}
|
||||
/* Any other error should be a BUG(kernel/libc/libvirtd)
|
||||
* (ENOMEM can happen on exceeding per-user limits)
|
||||
*/
|
||||
VIR_ERROR(_("%1$s: Failed to open the event monitor FIFO(%2$s) read end!"),
|
||||
vm->def->name, mon->eventmonitorpath);
|
||||
/* CH process(Writer) is blocked at this point as EventHandler(Reader)
|
||||
* fails to open the FIFO.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
mon->eventmonitorfd = event_monitor_fd;
|
||||
VIR_DEBUG("%s: Opened the event monitor FIFO(%s)", vm->def->name, mon->eventmonitorpath);
|
||||
|
||||
/* now has its own reference */
|
||||
mon->vm = virObjectRef(vm);
|
||||
|
||||
if (virCHStartEventHandler(mon) < 0)
|
||||
return NULL;
|
||||
|
||||
/* get a curl handle */
|
||||
mon->handle = curl_easy_init();
|
||||
|
||||
return g_steal_pointer(&mon);
|
||||
}
|
||||
|
||||
@ -638,6 +686,10 @@ void virCHMonitorClose(virCHMonitor *mon)
|
||||
g_clear_pointer(&mon->socketpath, g_free);
|
||||
}
|
||||
|
||||
virCHStopEventHandler(mon);
|
||||
if (mon->eventmonitorfd >= 0) {
|
||||
VIR_FORCE_CLOSE(mon->eventmonitorfd);
|
||||
}
|
||||
if (mon->eventmonitorpath) {
|
||||
if (virFileRemove(mon->eventmonitorpath, -1, -1) < 0) {
|
||||
VIR_WARN("Unable to remove CH event monitor file '%s'",
|
||||
|
@ -97,6 +97,10 @@ struct _virCHMonitor {
|
||||
char *socketpath;
|
||||
|
||||
char *eventmonitorpath;
|
||||
int eventmonitorfd;
|
||||
|
||||
virThread event_handler_thread;
|
||||
int event_handler_stop;
|
||||
|
||||
pid_t pid;
|
||||
|
||||
|
@ -7,6 +7,8 @@ ch_driver_sources = [
|
||||
'ch_domain.h',
|
||||
'ch_driver.c',
|
||||
'ch_driver.h',
|
||||
'ch_events.c',
|
||||
'ch_events.h',
|
||||
'ch_interface.c',
|
||||
'ch_interface.h',
|
||||
'ch_monitor.c',
|
||||
|
Loading…
x
Reference in New Issue
Block a user