All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu
@ 2018-10-04 11:43 Dominik Csapak
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 1/3] osdep: add qemu_launch_script for executing scripts Dominik Csapak
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Dominik Csapak @ 2018-10-04 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, sw, jasowang, thuth, philmd

this patch series aims to execute a script when qemu exits
so that one can do cleanups when using --daemonize without
having to use the qmp monitor

changes since v1:

* refactored as qemu_launch_script, only for non-windows platforms
* updated net/tap.c to use qemu_launch_script instead of launch_script
* fixed a small error in the option description

Dominik Csapak (3):
  osdep: add qemu_launch_script for executing scripts
  tap: use qemu_launch_script instead of launch_script
  vl.c: call optional script when exiting

 include/qemu/osdep.h | 12 +++++++++++
 net/tap.c            | 56 ++++++++++------------------------------------------
 qemu-options.hx      | 20 +++++++++++++++++++
 util/oslib-posix.c   | 34 +++++++++++++++++++++++++++++++
 util/oslib-win32.c   |  8 ++++++++
 vl.c                 | 29 +++++++++++++++++++++++++++
 6 files changed, 113 insertions(+), 46 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 1/3] osdep: add qemu_launch_script for executing scripts
  2018-10-04 11:43 [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Dominik Csapak
@ 2018-10-04 11:43 ` Dominik Csapak
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 2/3] tap: use qemu_launch_script instead of launch_script Dominik Csapak
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2018-10-04 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, sw, jasowang, thuth, philmd

this adds a small function for launching an external script
via fork/exec (not available for windows) and is intended
for replacing 'launch_script' in net/tap.c and to provide a general
way to launch scripts

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
i modeled the windows error after the qemu_fork implementation,
since it does not exist for the same reason

changes since v1:
* new in v2

 include/qemu/osdep.h | 12 ++++++++++++
 util/oslib-posix.c   | 34 ++++++++++++++++++++++++++++++++++
 util/oslib-win32.c   |  8 ++++++++
 3 files changed, 54 insertions(+)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 4f8559e550..26c1f01d55 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -564,6 +564,18 @@ char *qemu_get_pid_name(pid_t pid);
  */
 pid_t qemu_fork(Error **errp);
 
+/**
+ * qemu_launch_script:
+ * @script: the path to the script
+ * @args: the arguments for the script
+ * @fd: a file descriptor that should not be closed
+ *
+ * fork and exec a script with the given arguments
+ * closes all file descriptors > 2 except the one given with fd
+ */
+void qemu_launch_script(const char *script, char *const args[], int fd,
+                        Error **errp);
+
 /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
  * when intptr_t is 32-bit and we are aligning a long long.
  */
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index fbd0dc8c57..123b142591 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -698,3 +698,37 @@ void sigaction_invoke(struct sigaction *action,
     }
     action->sa_sigaction(info->ssi_signo, &si, NULL);
 }
+
+void qemu_launch_script(const char *script, char *const args[], int fd,
+                        Error **errp)
+{
+    int pid, status;
+
+    pid = fork();
+    if (pid < 0) {
+        error_setg_errno(errp, errno, "could not launch script %s",
+                         script);
+        return;
+    }
+    if (pid == 0) {
+        int open_max = sysconf(_SC_OPEN_MAX), i;
+
+        for (i = 3; i < open_max; i++) {
+            if (i != fd) {
+                close(i);
+            }
+        }
+        execv(script, args);
+        _exit(1);
+    } else {
+        while (waitpid(pid, &status, 0) != pid) {
+            /* loop */
+        }
+
+        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+            return;
+        }
+        error_setg(errp, "script %s failed with status %d",
+                   script, status);
+    }
+}
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index b4c17f5dfa..5e14c89dc7 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -803,3 +803,11 @@ bool qemu_write_pidfile(const char *filename, Error **errp)
     }
     return true;
 }
+
+void qemu_launch_script(const char *script, char *const args[], int fd,
+                        Error **errp)
+{
+    errno = ENOSYS;
+    error_setg_errno(errp, errno,
+                     "cannot fork child process");
+}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 2/3] tap: use qemu_launch_script instead of launch_script
  2018-10-04 11:43 [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Dominik Csapak
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 1/3] osdep: add qemu_launch_script for executing scripts Dominik Csapak
@ 2018-10-04 11:43 ` Dominik Csapak
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 3/3] vl.c: call optional script when exiting Dominik Csapak
  2018-10-08  3:28 ` [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Jason Wang
  3 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2018-10-04 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, sw, jasowang, thuth, philmd

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes since v1:
* new in v2

 net/tap.c | 56 ++++++++++----------------------------------------------
 1 file changed, 10 insertions(+), 46 deletions(-)

diff --git a/net/tap.c b/net/tap.c
index cc8525f154..15a0dd65b8 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -62,9 +62,6 @@ typedef struct TAPState {
     Notifier exit;
 } TAPState;
 
-static void launch_script(const char *setup_script, const char *ifname,
-                          int fd, Error **errp);
-
 static void tap_send(void *opaque);
 static void tap_writable(void *opaque);
 
@@ -300,7 +297,11 @@ static void tap_exit_notify(Notifier *notifier, void *data)
     Error *err = NULL;
 
     if (s->down_script[0]) {
-        launch_script(s->down_script, s->down_script_arg, s->fd, &err);
+        char *args[3];
+        args[0] = (char *)(s->down_script);
+        args[1] = (char *)(s->down_script_arg);
+        args[2] = NULL;
+        qemu_launch_script(s->down_script, args, s->fd, &err);
         if (err) {
             error_report_err(err);
         }
@@ -397,47 +398,6 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
     return s;
 }
 
-static void launch_script(const char *setup_script, const char *ifname,
-                          int fd, Error **errp)
-{
-    int pid, status;
-    char *args[3];
-    char **parg;
-
-    /* try to launch network script */
-    pid = fork();
-    if (pid < 0) {
-        error_setg_errno(errp, errno, "could not launch network script %s",
-                         setup_script);
-        return;
-    }
-    if (pid == 0) {
-        int open_max = sysconf(_SC_OPEN_MAX), i;
-
-        for (i = 3; i < open_max; i++) {
-            if (i != fd) {
-                close(i);
-            }
-        }
-        parg = args;
-        *parg++ = (char *)setup_script;
-        *parg++ = (char *)ifname;
-        *parg = NULL;
-        execv(setup_script, args);
-        _exit(1);
-    } else {
-        while (waitpid(pid, &status, 0) != pid) {
-            /* loop */
-        }
-
-        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
-            return;
-        }
-        error_setg(errp, "network script %s failed with status %d",
-                   setup_script, status);
-    }
-}
-
 static int recv_fd(int c)
 {
     int fd;
@@ -626,7 +586,11 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr,
     if (setup_script &&
         setup_script[0] != '\0' &&
         strcmp(setup_script, "no") != 0) {
-        launch_script(setup_script, ifname, fd, &err);
+        char *args[3];
+        args[0] = (char *)setup_script;
+        args[1] = (char *)ifname;
+        args[2] = NULL;
+        qemu_launch_script(setup_script, args, fd, &err);
         if (err) {
             error_propagate(errp, err);
             close(fd);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 3/3] vl.c: call optional script when exiting
  2018-10-04 11:43 [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Dominik Csapak
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 1/3] osdep: add qemu_launch_script for executing scripts Dominik Csapak
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 2/3] tap: use qemu_launch_script instead of launch_script Dominik Csapak
@ 2018-10-04 11:43 ` Dominik Csapak
  2018-10-08  3:28 ` [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Jason Wang
  3 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2018-10-04 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, sw, jasowang, thuth, philmd

some users might want to call a script when qemu exits, without listening
to a qmp monitor for events when running with --daemonize
this option is only available on non windows systems,
since there is no fork there and no --daemonize option

this can be used for things like external cleanups

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes since v1:
* only for non WIN32
* use qemu_launch_script
* fix error in option description (@var{file} instead of $var{file})

 qemu-options.hx | 20 ++++++++++++++++++++
 vl.c            | 29 +++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index f139459e80..6a67ec76fe 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3421,6 +3421,26 @@ This allows for instance switching to monitor to commit changes to the
 disk image.
 ETEXI
 
+#ifndef _WIN32
+DEF("exit-script", HAS_ARG, QEMU_OPTION_exit_script, \
+    "-exit-script    <file>\n"
+    "                      Execute the script in file on exit.\n"
+    "                      The arguments are:\n"
+    "                       - the shutdown reason,\n"
+    "                       - if it was really a reset (if -no-reboot was set)\n"
+    "                       - the name of the guest",
+    QEMU_ARCH_ALL)
+STEXI
+@item -exit-script @var{file}
+@findex -exit-script
+Execute the script @var{file} on exit.
+The arguments are:
+ - the shutdown reason
+ - if it was really a reset (if -no-reboot was set)
+ - the name of the guest
+ETEXI
+#endif
+
 DEF("loadvm", HAS_ARG, QEMU_OPTION_loadvm, \
     "-loadvm [tag|id]\n" \
     "                start right away with a saved state (loadvm in monitor)\n",
diff --git a/vl.c b/vl.c
index 0388852deb..5adf7c80f7 100644
--- a/vl.c
+++ b/vl.c
@@ -1522,6 +1522,9 @@ void vm_state_notify(int running, RunState state)
     }
 }
 
+static ShutdownCause shutdown_reason;
+static bool shutdown_was_reset;
+
 static ShutdownCause reset_requested;
 static ShutdownCause shutdown_requested;
 static int shutdown_signal;
@@ -1681,6 +1684,7 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
 void qemu_system_reset_request(ShutdownCause reason)
 {
     if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
+        shutdown_was_reset = true;
         shutdown_requested = reason;
     } else {
         reset_requested = reason;
@@ -1811,6 +1815,7 @@ static bool main_loop_should_exit(void)
         if (no_shutdown) {
             vm_stop(RUN_STATE_SHUTDOWN);
         } else {
+            shutdown_reason = request;
             return true;
         }
     }
@@ -2908,6 +2913,7 @@ int main(int argc, char **argv, char **envp)
     Error *err = NULL;
     bool list_data_dirs = false;
     char *dir, **dirs;
+    const char *exit_script = NULL;
     typedef struct BlockdevOptions_queue {
         BlockdevOptions *bdo;
         Location loc;
@@ -3596,6 +3602,11 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_no_shutdown:
                 no_shutdown = 1;
                 break;
+#ifndef _WIN32
+            case QEMU_OPTION_exit_script:
+                exit_script = optarg;
+                break;
+#endif
             case QEMU_OPTION_show_cursor:
                 cursor_hide = 0;
                 break;
@@ -4590,5 +4601,23 @@ int main(int argc, char **argv, char **envp)
     migration_object_finalize();
     /* TODO: unref root container, check all devices are ok */
 
+    if (exit_script) {
+        char *args[5];
+        Error *local_err =  NULL;
+        args[0] = (char *)exit_script;
+        args[1] = g_strdup_printf("%d", shutdown_reason);
+        args[2] = g_strdup_printf("%d", shutdown_was_reset);
+        args[3] = (char *)qemu_get_vm_name();
+        args[4] = NULL;
+
+        qemu_launch_script(exit_script, args, -1, &local_err);
+        g_free(args[1]);
+        g_free(args[2]);
+        if (local_err) {
+            error_report_err(local_err);
+            exit(1);
+        }
+    }
+
     return 0;
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu
  2018-10-04 11:43 [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Dominik Csapak
                   ` (2 preceding siblings ...)
  2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 3/3] vl.c: call optional script when exiting Dominik Csapak
@ 2018-10-08  3:28 ` Jason Wang
  2018-10-08  7:39   ` Dominik Csapak
  3 siblings, 1 reply; 6+ messages in thread
From: Jason Wang @ 2018-10-08  3:28 UTC (permalink / raw)
  To: Dominik Csapak, qemu-devel; +Cc: pbonzini, philmd, thuth, sw



On 2018年10月04日 19:43, Dominik Csapak wrote:
> this patch series aims to execute a script when qemu exits
> so that one can do cleanups when using --daemonize without
> having to use the qmp monitor

Hi:

Can you give a example of why it must be done through this way? It looks 
to me that we can do this by monitor the pid and behave accordingly 
through bash.

Thanks

>
> changes since v1:
>
> * refactored as qemu_launch_script, only for non-windows platforms
> * updated net/tap.c to use qemu_launch_script instead of launch_script
> * fixed a small error in the option description
>
> Dominik Csapak (3):
>    osdep: add qemu_launch_script for executing scripts
>    tap: use qemu_launch_script instead of launch_script
>    vl.c: call optional script when exiting
>
>   include/qemu/osdep.h | 12 +++++++++++
>   net/tap.c            | 56 ++++++++++------------------------------------------
>   qemu-options.hx      | 20 +++++++++++++++++++
>   util/oslib-posix.c   | 34 +++++++++++++++++++++++++++++++
>   util/oslib-win32.c   |  8 ++++++++
>   vl.c                 | 29 +++++++++++++++++++++++++++
>   6 files changed, 113 insertions(+), 46 deletions(-)
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu
  2018-10-08  3:28 ` [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Jason Wang
@ 2018-10-08  7:39   ` Dominik Csapak
  0 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2018-10-08  7:39 UTC (permalink / raw)
  To: Jason Wang, qemu-devel; +Cc: pbonzini, philmd, thuth, sw

On 10/8/18 5:28 AM, Jason Wang wrote:
> 
> 
> On 2018年10月04日 19:43, Dominik Csapak wrote:
>> this patch series aims to execute a script when qemu exits
>> so that one can do cleanups when using --daemonize without
>> having to use the qmp monitor
> 
> Hi:
> 
> Can you give a example of why it must be done through this way? It looks 
> to me that we can do this by monitor the pid and behave accordingly 
> through bash.
> 
> Thanks

Hi,

as i said in a reply on my original patch, the reason was twofold

first, i thought having an additional process just for monitoring
the exit of qemu with qmp/pidfile was too much for some users, as 
opposed to a simple script that executes then

ans second (more important), i wanted to know the reason qemu
exited (e.g. user initiated shutdown/reset/etc.),
especially when '-no-reboot' is set

please ignore this series (maybe the refactoring of the launch script
is interesting, i don't know), i will send a patch to be able
to distinguish the shutdown/reset with no-reboot in a seperate
patch for qmp

> 
>>
>> changes since v1:
>>
>> * refactored as qemu_launch_script, only for non-windows platforms
>> * updated net/tap.c to use qemu_launch_script instead of launch_script
>> * fixed a small error in the option description
>>
>> Dominik Csapak (3):
>>    osdep: add qemu_launch_script for executing scripts
>>    tap: use qemu_launch_script instead of launch_script
>>    vl.c: call optional script when exiting
>>
>>   include/qemu/osdep.h | 12 +++++++++++
>>   net/tap.c            | 56 
>> ++++++++++------------------------------------------
>>   qemu-options.hx      | 20 +++++++++++++++++++
>>   util/oslib-posix.c   | 34 +++++++++++++++++++++++++++++++
>>   util/oslib-win32.c   |  8 ++++++++
>>   vl.c                 | 29 +++++++++++++++++++++++++++
>>   6 files changed, 113 insertions(+), 46 deletions(-)
>>
> 
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-10-08  7:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-04 11:43 [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Dominik Csapak
2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 1/3] osdep: add qemu_launch_script for executing scripts Dominik Csapak
2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 2/3] tap: use qemu_launch_script instead of launch_script Dominik Csapak
2018-10-04 11:43 ` [Qemu-devel] [PATCH v2 3/3] vl.c: call optional script when exiting Dominik Csapak
2018-10-08  3:28 ` [Qemu-devel] [PATCH v2 0/3] add exit-script option to qemu Jason Wang
2018-10-08  7:39   ` Dominik Csapak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.