]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: support VIR_DOMAIN_DESTROY_REMOVE_LOGS flag
authorNikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
Mon, 14 Feb 2022 12:19:52 +0000 (15:19 +0300)
committerNikolay Shirokovskiy <nikolay.shirokovskiy@openvz.org>
Wed, 6 Apr 2022 07:48:04 +0000 (10:48 +0300)
Note that we attempt to remove logs only if virtlogd is in use.
Otherwise we do not know the pattern for rotated files.

For example for VM named "foo" we can not use "foo.log*" pattern to
remove rotated logs as we can have VM named "foo.log" with log
"foo.log.log".  We can add extra check that filename does not end with
".log" but for VM "foo.log" we can have rotated log "foo.log.log.1". Ok
let's check we don't have "log" in filename part corresponging to * but
what if someone will use logrotate with "%Y.log-%m-%d" 'dateformat'
option. In this case the check will exclude proper rotated files.

Yes, the last example if quite artificial but it shows it is difficult
to find out correctly rotated files when rotated files pattern is not
known. Thus the above decision only to support case with virtlogd when
we know the pattern.

Another reason for not removing log files when logrotate is present is
that due to races some files can escape deletion. For example foo.log.3
will be rotated to foo.log.4 after removing function will read directory
files and thus foo.log.4 will not be deleted.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c

index fe00c6f25b5d4c7fcefc9d1c12b4093a134b84ab..c35e5c09a30ba76d17ee4adfd4c54b64cd908ce9 100644 (file)
@@ -11820,3 +11820,44 @@ qemuDomainDeviceBackendChardevForeach(virDomainDef *def,
                                            DOMAIN_DEVICE_ITERATE_MISSING_INFO,
                                            &data);
 }
+
+
+int
+qemuDomainRemoveLogs(virQEMUDriver *driver,
+                     const char *name)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = NULL;
+    g_autofree char *format = NULL;
+    g_autofree char *main = NULL;
+    g_autoptr(DIR) dir = NULL;
+    struct dirent *entry;
+    int rc;
+
+    cfg = virQEMUDriverGetConfig(driver);
+    if (!cfg->stdioLogD)
+        return 0;
+
+    if (virDirOpen(&dir, cfg->logDir) < 0)
+        return -1;
+
+    main = g_strdup_printf("%s.log", name);
+    format = g_strdup_printf("%s.log.%%u", name);
+
+    while ((rc = virDirRead(dir, &entry, cfg->logDir)) > 0) {
+        unsigned int u;
+
+        if (STREQ(entry->d_name, main) ||
+            sscanf(entry->d_name, format, &u) == 1) {
+            g_autofree char *path = NULL;
+
+            path = g_strdup_printf("%s/%s", cfg->logDir, entry->d_name);
+            if (unlink(path) && errno != ENOENT)
+                VIR_WARN("unlink(%s) error: %s", path, g_strerror(errno));
+        }
+    }
+
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
index a41d8308e38cd0bb4bf740ccaa71df4b8a8d17be..f4d84ca43a4b79fb3ea72202678ddb97ffdfef74 100644 (file)
@@ -1084,3 +1084,7 @@ int
 qemuDomainDeviceBackendChardevForeach(virDomainDef *def,
                                       qemuDomainDeviceBackendChardevForeachCallback cb,
                                       void *opaque);
+
+int
+qemuDomainRemoveLogs(virQEMUDriver *driver,
+                     const char *name);
index 77012eb527f4ce9b873f297157e1af8ad984b781..26647a9ae393d996404ac2d5ec719468c78f1a91 100644 (file)
@@ -2072,7 +2072,8 @@ qemuDomainDestroyFlags(virDomainPtr dom,
     int reason;
     bool starting;
 
-    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);
+    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL |
+                  VIR_DOMAIN_DESTROY_REMOVE_LOGS, -1);
 
     if (!(vm = qemuDomainObjFromDomain(dom)))
         return -1;
@@ -2112,6 +2113,11 @@ qemuDomainDestroyFlags(virDomainPtr dom,
 
     qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED,
                     VIR_ASYNC_JOB_NONE, stopFlags);
+
+    if ((flags & VIR_DOMAIN_DESTROY_REMOVE_LOGS) &&
+        qemuDomainRemoveLogs(driver, vm->def->name) < 0)
+        VIR_WARN("Failed to remove logs for VM '%s'", vm->def->name);
+
     event = virDomainEventLifecycleNewFromObj(vm,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);