Implement fork & setns for lxcDomainShutdownFlags
---
src/lxc/lxc_driver.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index c499182..9d200b2 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2619,6 +2619,50 @@ lxcDomainShutdownFlags(virDomainPtr dom,
goto cleanup;
}
+#ifdef HAVE_SETNS
+ if (flags == 0 || flags & VIR_DOMAIN_SHUTDOWN_INITCTL) {
+ int pid = -1;
+ int status = -1;
+ int mfd = -1;
+
+ if (virAsprintf(&vroot, "/proc/%llu/ns/mnt",
+ (unsigned long long)priv->initpid) < 0) {
+ goto cleanup;
+ }
+
+ if ((mfd = open(vroot, O_RDONLY)) < 0) {
+ virReportSystemError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("Kernel does not provide mount
namespace"));
+ goto cleanup;
+ }
+
+ switch (pid = fork()) {
+ case 0:
+ if (setns(mfd, 0) == -1) {
+ exit(-1);
+ }
+ rc = virInitctlSetRunLevel(VIR_INITCTL_RUNLEVEL_POWEROFF, NULL);
+ exit(rc);
+ break;
+ case -1:
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Fork failed"));
+ goto cleanup;
+ default:
+ if (waitpid(pid, &status, 0) < 0 || status < 0) {
+ virReportSystemError(errno,
+ _("Sending shutdown failed with status
%i"),
+ status);
+ rc = 0;
+ } else {
+ rc = status;
+ }
+ close(mfd);
+ }
+ } else {
+ rc = 0;
+ }
+#else
if (virAsprintf(&vroot, "/proc/%llu/root",
(unsigned long long)priv->initpid) < 0)
goto cleanup;
@@ -2638,6 +2682,7 @@ lxcDomainShutdownFlags(virDomainPtr dom,
} else {
rc = 0;
}
+#endif
if (rc == 0 &&
(flags == 0 ||
--
1.7.10.4