mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
lxc: Don't reboot host on virDomainReboot
If the container is really a simple one (init is just bash and the whole root is passed through) then virDomainReboot and virDomainShutdown will talk to the actual init within the host. Therefore, 'virsh shutdown $dom' will result in shutting down the host. True, at that point the container is shut down too but looks a bit harsh to me. The solution is to check if the init inside the container is or is not the same as the init running on the host. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
parent
64eca3d5e3
commit
94fce25546
@ -32,6 +32,7 @@
|
||||
#include "virfile.h"
|
||||
#include "virtime.h"
|
||||
#include "virsystemd.h"
|
||||
#include "virinitctl.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_LXC
|
||||
#define LXC_NAMESPACE_HREF "http://libvirt.org/schemas/domain/lxc/1.0"
|
||||
@ -418,3 +419,92 @@ virLXCDomainGetMachineName(virDomainDefPtr def, pid_t pid)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
typedef struct _lxcDomainInitctlCallbackData lxcDomainInitctlCallbackData;
|
||||
struct _lxcDomainInitctlCallbackData {
|
||||
int runlevel;
|
||||
bool *st_valid;
|
||||
struct stat *st;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
lxcDomainInitctlCallback(pid_t pid ATTRIBUTE_UNUSED,
|
||||
void *opaque)
|
||||
{
|
||||
lxcDomainInitctlCallbackData *data = opaque;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; virInitctlFifos[i]; i++) {
|
||||
const char *fifo = virInitctlFifos[i];
|
||||
struct stat cont_sb;
|
||||
|
||||
if (stat(fifo, &cont_sb) < 0) {
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
|
||||
virReportSystemError(errno, _("Unable to stat %s"), fifo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if the init fifo is not the very one that's on
|
||||
* the host. We don't want to change the host's runlevel.
|
||||
*/
|
||||
if (data->st_valid[i] &&
|
||||
data->st[i].st_dev == cont_sb.st_dev &&
|
||||
data->st[i].st_ino == cont_sb.st_ino)
|
||||
continue;
|
||||
|
||||
return virInitctlSetRunLevel(fifo, data->runlevel);
|
||||
}
|
||||
|
||||
/* If no usable fifo was found then declare success. Caller
|
||||
* will try killing the domain with signal. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virLXCDomainSetRunlevel(virDomainObjPtr vm,
|
||||
int runlevel)
|
||||
{
|
||||
virLXCDomainObjPrivatePtr priv = vm->privateData;
|
||||
lxcDomainInitctlCallbackData data;
|
||||
size_t nfifos = 0;
|
||||
size_t i;
|
||||
int ret = -1;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
data.runlevel = runlevel;
|
||||
|
||||
for (nfifos = 0; virInitctlFifos[nfifos]; nfifos++)
|
||||
;
|
||||
|
||||
if (VIR_ALLOC_N(data.st, nfifos) < 0 ||
|
||||
VIR_ALLOC_N(data.st_valid, nfifos) < 0)
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; virInitctlFifos[i]; i++) {
|
||||
const char *fifo = virInitctlFifos[i];
|
||||
|
||||
if (stat(fifo, &(data.st[i])) < 0) {
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
|
||||
virReportSystemError(errno, _("Unable to stat %s"), fifo);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
data.st_valid[i] = true;
|
||||
}
|
||||
|
||||
ret = virProcessRunInMountNamespace(priv->initpid,
|
||||
lxcDomainInitctlCallback,
|
||||
&data);
|
||||
cleanup:
|
||||
VIR_FREE(data.st);
|
||||
VIR_FREE(data.st_valid);
|
||||
return ret;
|
||||
}
|
||||
|
@ -109,4 +109,8 @@ virLXCDomainObjEndJob(virLXCDriverPtr driver,
|
||||
char *
|
||||
virLXCDomainGetMachineName(virDomainDefPtr def, pid_t pid);
|
||||
|
||||
int
|
||||
virLXCDomainSetRunlevel(virDomainObjPtr vm,
|
||||
int runlevel);
|
||||
|
||||
#endif /* LIBVIRT_LXC_DOMAIN_H */
|
||||
|
@ -3272,15 +3272,6 @@ lxcConnectListAllDomains(virConnectPtr conn,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lxcDomainInitctlCallback(pid_t pid ATTRIBUTE_UNUSED,
|
||||
void *opaque)
|
||||
{
|
||||
int *command = opaque;
|
||||
return virInitctlSetRunLevel(NULL, *command);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lxcDomainShutdownFlags(virDomainPtr dom,
|
||||
unsigned int flags)
|
||||
@ -3318,9 +3309,7 @@ lxcDomainShutdownFlags(virDomainPtr dom,
|
||||
(flags & VIR_DOMAIN_SHUTDOWN_INITCTL)) {
|
||||
int command = VIR_INITCTL_RUNLEVEL_POWEROFF;
|
||||
|
||||
if ((rc = virProcessRunInMountNamespace(priv->initpid,
|
||||
lxcDomainInitctlCallback,
|
||||
&command)) < 0)
|
||||
if ((rc = virLXCDomainSetRunlevel(vm, command)) < 0)
|
||||
goto endjob;
|
||||
if (rc == 0 && flags != 0 &&
|
||||
((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) {
|
||||
@ -3398,9 +3387,7 @@ lxcDomainReboot(virDomainPtr dom,
|
||||
(flags & VIR_DOMAIN_REBOOT_INITCTL)) {
|
||||
int command = VIR_INITCTL_RUNLEVEL_REBOOT;
|
||||
|
||||
if ((rc = virProcessRunInMountNamespace(priv->initpid,
|
||||
lxcDomainInitctlCallback,
|
||||
&command)) < 0)
|
||||
if ((rc = virLXCDomainSetRunlevel(vm, command)) < 0)
|
||||
goto endjob;
|
||||
if (rc == 0 && flags != 0 &&
|
||||
((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user