2008-08-13 10:25:34 +00:00
|
|
|
/*
|
2016-05-13 17:20:54 +00:00
|
|
|
* Copyright (C) 2010-2016 Red Hat, Inc.
|
2011-03-09 03:13:18 +00:00
|
|
|
* Copyright IBM Corp. 2008
|
2008-08-13 10:25:34 +00:00
|
|
|
*
|
|
|
|
* lxc_controller.c: linux container process controller
|
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-08-13 10:25:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/epoll.h>
|
2008-08-13 10:52:15 +00:00
|
|
|
#include <sys/wait.h>
|
2016-04-14 13:11:45 +00:00
|
|
|
|
2020-01-24 17:32:48 +00:00
|
|
|
#ifdef __linux__
|
2016-04-14 13:11:45 +00:00
|
|
|
# include <sys/sysmacros.h>
|
|
|
|
#endif
|
|
|
|
|
2011-02-23 17:17:53 +00:00
|
|
|
#include <sys/personality.h>
|
2008-08-13 10:25:34 +00:00
|
|
|
#include <unistd.h>
|
2008-08-13 10:52:15 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
2008-08-20 20:55:32 +00:00
|
|
|
#include <getopt.h>
|
2009-04-22 14:26:50 +00:00
|
|
|
#include <sys/mount.h>
|
2011-10-19 01:39:57 +00:00
|
|
|
#include <grp.h>
|
|
|
|
#include <sys/stat.h>
|
2008-08-13 10:25:34 +00:00
|
|
|
|
2012-09-20 14:17:56 +00:00
|
|
|
#if WITH_CAPNG
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <cap-ng.h>
|
2009-06-29 17:09:42 +00:00
|
|
|
#endif
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2008-08-13 10:25:34 +00:00
|
|
|
|
|
|
|
#include "lxc_conf.h"
|
2008-08-13 10:52:15 +00:00
|
|
|
#include "lxc_container.h"
|
2012-07-13 11:21:27 +00:00
|
|
|
#include "lxc_cgroup.h"
|
2012-12-21 13:19:54 +00:00
|
|
|
#include "lxc_monitor_protocol.h"
|
2012-11-14 09:39:04 +00:00
|
|
|
#include "lxc_fuse.h"
|
2011-11-02 16:03:09 +00:00
|
|
|
#include "virnetdev.h"
|
|
|
|
#include "virnetdevveth.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2020-09-09 14:43:12 +00:00
|
|
|
#include "virgdbus.h"
|
2011-08-05 13:13:12 +00:00
|
|
|
#include "virpidfile.h"
|
2016-04-13 17:53:02 +00:00
|
|
|
#include "virhostcpu.h"
|
2012-09-24 17:10:37 +00:00
|
|
|
#include "virprocess.h"
|
2013-03-18 09:04:02 +00:00
|
|
|
#include "virnuma.h"
|
2015-03-16 14:02:41 +00:00
|
|
|
#include "rpc/virnetdaemon.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2016-04-12 22:29:52 +00:00
|
|
|
#include "virgettext.h"
|
2020-02-16 21:59:28 +00:00
|
|
|
#include "virutil.h"
|
2008-08-13 10:25:34 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_LXC
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("lxc.lxc_controller");
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
typedef struct _virLXCControllerConsole virLXCControllerConsole;
|
|
|
|
struct _virLXCControllerConsole {
|
|
|
|
int hostWatch;
|
|
|
|
int hostFd; /* PTY FD in the host OS */
|
|
|
|
bool hostClosed;
|
|
|
|
int hostEpoll;
|
|
|
|
|
|
|
|
int contWatch;
|
|
|
|
int contFd; /* PTY FD in the container */
|
|
|
|
bool contClosed;
|
|
|
|
int contEpoll;
|
|
|
|
|
|
|
|
int epollWatch;
|
|
|
|
int epollFd; /* epoll FD for dealing with EOF */
|
|
|
|
|
|
|
|
size_t fromHostLen;
|
|
|
|
char fromHostBuf[1024];
|
|
|
|
size_t fromContLen;
|
|
|
|
char fromContBuf[1024];
|
2012-11-16 09:11:23 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virNetDaemon *daemon;
|
2012-07-03 11:42:53 +00:00
|
|
|
};
|
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
typedef struct _virLXCController virLXCController;
|
|
|
|
struct _virLXCController {
|
|
|
|
char *name;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainObj *vm;
|
|
|
|
virDomainDef *def;
|
2012-07-03 11:06:38 +00:00
|
|
|
|
2021-04-20 11:28:20 +00:00
|
|
|
int handshakeFds[2]; /* { read FD, write FD } */
|
2012-07-03 12:16:48 +00:00
|
|
|
|
2012-07-03 11:12:59 +00:00
|
|
|
pid_t initpid;
|
|
|
|
|
2015-05-26 16:29:27 +00:00
|
|
|
size_t nnbdpids;
|
|
|
|
pid_t *nbdpids;
|
|
|
|
|
2012-07-03 11:06:38 +00:00
|
|
|
size_t nveths;
|
|
|
|
char **veths;
|
2012-07-03 11:42:53 +00:00
|
|
|
|
2015-01-16 16:58:39 +00:00
|
|
|
size_t nnicindexes;
|
|
|
|
int *nicindexes;
|
|
|
|
|
2013-07-09 17:15:45 +00:00
|
|
|
size_t npassFDs;
|
|
|
|
int *passFDs;
|
|
|
|
|
2015-08-20 13:46:17 +00:00
|
|
|
int *nsFDs;
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
size_t nconsoles;
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerConsole *consoles;
|
2012-07-03 13:02:33 +00:00
|
|
|
char *devptmx;
|
2012-07-03 12:49:19 +00:00
|
|
|
|
|
|
|
size_t nloopDevs;
|
|
|
|
int *loopDevFds;
|
2012-07-03 12:59:36 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *securityManager;
|
2012-07-03 13:40:45 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virNetDaemon *daemon;
|
2012-11-20 17:49:25 +00:00
|
|
|
bool firstClient;
|
2021-03-11 07:16:13 +00:00
|
|
|
virNetServerClient *client;
|
|
|
|
virNetServerProgram *prog;
|
2012-07-17 14:54:08 +00:00
|
|
|
bool inShutdown;
|
|
|
|
int timerShutdown;
|
2012-11-14 09:39:04 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virCgroup *cgroup;
|
2013-07-22 15:36:06 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
struct virLXCFuse *fuse;
|
2012-07-03 10:54:09 +00:00
|
|
|
};
|
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
#include "lxc_controller_dispatch.h"
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void virLXCControllerFree(virLXCController *ctrl);
|
|
|
|
static int virLXCControllerEventSendInit(virLXCController *ctrl,
|
2012-11-20 17:49:25 +00:00
|
|
|
pid_t initpid);
|
2012-07-03 10:54:09 +00:00
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static void virLXCControllerQuitTimer(int timer G_GNUC_UNUSED, void *opaque)
|
2012-07-17 14:54:08 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = opaque;
|
2012-07-17 14:54:08 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Triggering event loop quit");
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(ctrl->daemon);
|
2012-07-17 14:54:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static virLXCDriver *
|
2019-12-03 10:49:49 +00:00
|
|
|
virLXCControllerDriverNew(void)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCDriver *driver = g_new0(virLXCDriver, 1);
|
2019-12-03 10:49:49 +00:00
|
|
|
|
|
|
|
if (virMutexInit(&driver->lock) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot initialize mutex"));
|
|
|
|
g_free(driver);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
driver->caps = virLXCDriverCapsInit(NULL);
|
2020-12-03 18:55:24 +00:00
|
|
|
driver->xmlopt = lxcDomainXMLConfInit(driver, NULL);
|
2019-12-03 10:49:49 +00:00
|
|
|
|
|
|
|
return driver;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerDriverFree(virLXCDriver *driver)
|
2019-12-03 10:49:49 +00:00
|
|
|
{
|
|
|
|
if (!driver)
|
|
|
|
return;
|
|
|
|
virObjectUnref(driver->xmlopt);
|
|
|
|
virObjectUnref(driver->caps);
|
|
|
|
virMutexDestroy(&driver->lock);
|
|
|
|
g_free(driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static virLXCController *virLXCControllerNew(const char *name)
|
2012-07-03 10:54:09 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = g_new0(virLXCController, 1);
|
|
|
|
virLXCDriver *driver = NULL;
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *configFile = NULL;
|
2012-07-03 10:54:09 +00:00
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
ctrl->timerShutdown = -1;
|
2012-11-20 17:49:25 +00:00
|
|
|
ctrl->firstClient = true;
|
2019-10-20 11:49:46 +00:00
|
|
|
ctrl->name = g_strdup(name);
|
2021-04-20 11:28:20 +00:00
|
|
|
ctrl->handshakeFds[0] = -1;
|
|
|
|
ctrl->handshakeFds[1] = -1;
|
2012-07-03 10:54:09 +00:00
|
|
|
|
2019-12-03 10:49:49 +00:00
|
|
|
if (!(driver = virLXCControllerDriverNew()))
|
2013-03-05 15:17:24 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
if ((configFile = virDomainConfigFile(LXC_STATE_DIR,
|
|
|
|
ctrl->name)) == NULL)
|
|
|
|
goto error;
|
|
|
|
|
2015-01-16 16:39:57 +00:00
|
|
|
if ((ctrl->vm = virDomainObjParseFile(configFile,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt,
|
2015-01-16 16:39:57 +00:00
|
|
|
0)) == NULL)
|
2012-07-03 10:54:09 +00:00
|
|
|
goto error;
|
2015-01-16 16:39:57 +00:00
|
|
|
ctrl->def = ctrl->vm->def;
|
2012-07-03 10:54:09 +00:00
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
if ((ctrl->timerShutdown = virEventAddTimeout(-1,
|
|
|
|
virLXCControllerQuitTimer, ctrl,
|
|
|
|
NULL)) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2019-12-03 10:49:49 +00:00
|
|
|
virLXCControllerDriverFree(driver);
|
2012-07-03 10:54:09 +00:00
|
|
|
return ctrl;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
error:
|
2022-01-28 17:42:45 +00:00
|
|
|
g_clear_pointer(&ctrl, virLXCControllerFree);
|
2012-07-03 10:54:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:12:59 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerCloseLoopDevices(virLXCController *ctrl)
|
2012-07-03 12:49:19 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nloopDevs; i++)
|
2013-03-15 15:07:13 +00:00
|
|
|
VIR_FORCE_CLOSE(ctrl->loopDevFds[i]);
|
2012-07-03 12:49:19 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void virLXCControllerStopInit(virLXCController *ctrl)
|
2012-07-03 11:12:59 +00:00
|
|
|
{
|
|
|
|
if (ctrl->initpid == 0)
|
|
|
|
return;
|
|
|
|
|
2013-03-15 15:07:13 +00:00
|
|
|
virLXCControllerCloseLoopDevices(ctrl);
|
2012-09-24 16:59:31 +00:00
|
|
|
virProcessAbort(ctrl->initpid);
|
2012-07-03 11:12:59 +00:00
|
|
|
ctrl->initpid = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void virLXCControllerConsoleClose(virLXCControllerConsole *console)
|
2012-07-03 11:42:53 +00:00
|
|
|
{
|
|
|
|
if (console->hostWatch != -1)
|
|
|
|
virEventRemoveHandle(console->hostWatch);
|
|
|
|
VIR_FORCE_CLOSE(console->hostFd);
|
|
|
|
|
|
|
|
if (console->contWatch != -1)
|
|
|
|
virEventRemoveHandle(console->contWatch);
|
|
|
|
VIR_FORCE_CLOSE(console->contFd);
|
|
|
|
|
|
|
|
if (console->epollWatch != -1)
|
|
|
|
virEventRemoveHandle(console->epollWatch);
|
|
|
|
VIR_FORCE_CLOSE(console->epollFd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-14 09:39:04 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerFreeFuse(virLXCController *ctrl)
|
2012-11-14 09:39:04 +00:00
|
|
|
{
|
|
|
|
return lxcFreeFuse(&ctrl->fuse);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void virLXCControllerFree(virLXCController *ctrl)
|
2012-07-03 10:54:09 +00:00
|
|
|
{
|
2012-07-03 11:06:38 +00:00
|
|
|
size_t i;
|
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
if (!ctrl)
|
|
|
|
return;
|
|
|
|
|
2012-07-03 11:12:59 +00:00
|
|
|
virLXCControllerStopInit(ctrl);
|
|
|
|
|
2013-02-05 17:54:55 +00:00
|
|
|
virObjectUnref(ctrl->securityManager);
|
2012-07-03 12:59:36 +00:00
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nveths; i++)
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->veths[i]);
|
|
|
|
g_free(ctrl->veths);
|
|
|
|
g_free(ctrl->nicindexes);
|
2012-07-03 11:06:38 +00:00
|
|
|
|
2013-07-09 17:15:45 +00:00
|
|
|
for (i = 0; i < ctrl->npassFDs; i++)
|
|
|
|
VIR_FORCE_CLOSE(ctrl->passFDs[i]);
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->passFDs);
|
2013-07-09 17:15:45 +00:00
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nconsoles; i++)
|
2012-07-03 11:42:53 +00:00
|
|
|
virLXCControllerConsoleClose(&(ctrl->consoles[i]));
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->consoles);
|
2012-07-03 11:42:53 +00:00
|
|
|
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->devptmx);
|
2012-07-03 13:02:33 +00:00
|
|
|
|
2018-03-26 22:21:59 +00:00
|
|
|
virDomainObjEndAPI(&ctrl->vm);
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->name);
|
2012-07-03 10:54:09 +00:00
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
if (ctrl->timerShutdown != -1)
|
|
|
|
virEventRemoveTimeout(ctrl->timerShutdown);
|
|
|
|
|
2015-03-16 14:02:41 +00:00
|
|
|
virObjectUnref(ctrl->daemon);
|
2012-11-14 09:39:04 +00:00
|
|
|
virLXCControllerFreeFuse(ctrl);
|
2012-07-03 13:40:45 +00:00
|
|
|
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->nbdpids);
|
2015-05-26 16:29:27 +00:00
|
|
|
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl->nsFDs);
|
2020-09-22 12:07:27 +00:00
|
|
|
virCgroupFree(ctrl->cgroup);
|
2013-07-22 15:36:06 +00:00
|
|
|
|
2013-03-04 20:47:37 +00:00
|
|
|
/* This must always be the last thing to be closed */
|
2021-04-20 11:28:20 +00:00
|
|
|
for (i = 0; i < G_N_ELEMENTS(ctrl->handshakeFds); i++)
|
|
|
|
VIR_FORCE_CLOSE(ctrl->handshakeFds[i]);
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(ctrl);
|
2012-07-03 10:54:09 +00:00
|
|
|
}
|
|
|
|
|
2012-07-03 11:06:38 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerAddConsole(virLXCController *ctrl,
|
2012-07-03 11:42:53 +00:00
|
|
|
int hostFd)
|
|
|
|
{
|
2021-03-19 23:37:03 +00:00
|
|
|
VIR_EXPAND_N(ctrl->consoles, ctrl->nconsoles, 1);
|
2015-03-16 14:02:41 +00:00
|
|
|
ctrl->consoles[ctrl->nconsoles-1].daemon = ctrl->daemon;
|
2012-07-03 11:42:53 +00:00
|
|
|
ctrl->consoles[ctrl->nconsoles-1].hostFd = hostFd;
|
|
|
|
ctrl->consoles[ctrl->nconsoles-1].hostWatch = -1;
|
|
|
|
|
|
|
|
ctrl->consoles[ctrl->nconsoles-1].contFd = -1;
|
|
|
|
ctrl->consoles[ctrl->nconsoles-1].contWatch = -1;
|
|
|
|
|
|
|
|
ctrl->consoles[ctrl->nconsoles-1].epollFd = -1;
|
|
|
|
ctrl->consoles[ctrl->nconsoles-1].epollWatch = -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerConsoleSetNonblocking(virLXCControllerConsole *console)
|
2012-07-03 11:42:53 +00:00
|
|
|
{
|
|
|
|
if (virSetBlocking(console->hostFd, false) < 0 ||
|
|
|
|
virSetBlocking(console->contFd, false) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to set console file descriptor non-blocking"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-20 08:33:03 +00:00
|
|
|
static int virLXCControllerDaemonHandshakeCont(virLXCController *ctrl)
|
2012-07-03 12:16:48 +00:00
|
|
|
{
|
2021-04-20 11:28:20 +00:00
|
|
|
if (lxcContainerSendContinue(ctrl->handshakeFds[1]) < 0) {
|
2012-07-03 12:16:48 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("error sending continue signal to daemon"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-04-20 08:33:03 +00:00
|
|
|
static int virLXCControllerDaemonHandshakeWait(virLXCController *ctrl)
|
|
|
|
{
|
|
|
|
if (lxcContainerWaitForContinue(ctrl->handshakeFds[0]) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("error waiting for continue signal from daemon"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-07-03 12:16:48 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerValidateNICs(virLXCController *ctrl)
|
2012-07-03 11:06:38 +00:00
|
|
|
{
|
|
|
|
if (ctrl->def->nnets != ctrl->nveths) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("expecting %1$zu veths, but got %2$zu"),
|
2012-07-13 12:59:51 +00:00
|
|
|
ctrl->def->nnets, ctrl->nveths);
|
2012-07-03 11:06:38 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerGetNICIndexes(virLXCController *ctrl)
|
2015-01-16 16:58:39 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2018-12-06 14:59:59 +00:00
|
|
|
/* Gather the ifindexes of the "parent" veths for all interfaces
|
|
|
|
* implemented with a veth pair. These will be used when calling
|
|
|
|
* virCgroupNewMachine (and eventually the dbus method
|
|
|
|
* CreateMachineWithNetwork). ifindexes for the child veths, and
|
|
|
|
* for macvlan interfaces, *should not* be in this list, as they
|
|
|
|
* will be moved into the container. Only the interfaces that will
|
|
|
|
* remain outside the container, but are used for communication
|
|
|
|
* with the container, should be added to the list.
|
|
|
|
*/
|
|
|
|
|
2015-01-16 16:58:39 +00:00
|
|
|
VIR_DEBUG("Getting nic indexes");
|
|
|
|
for (i = 0; i < ctrl->def->nnets; i++) {
|
|
|
|
int nicindex = -1;
|
2018-12-05 21:58:08 +00:00
|
|
|
virDomainNetType actualType = virDomainNetGetActualType(ctrl->def->nets[i]);
|
|
|
|
|
|
|
|
switch (actualType) {
|
2015-01-16 16:58:39 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
2016-05-13 17:20:54 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
2015-01-16 16:58:39 +00:00
|
|
|
if (ctrl->def->nets[i]->ifname == NULL)
|
|
|
|
continue;
|
|
|
|
if (virNetDevGetIndex(ctrl->def->nets[i]->ifname,
|
|
|
|
&nicindex) < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2021-03-19 23:37:03 +00:00
|
|
|
VIR_EXPAND_N(ctrl->nicindexes, ctrl->nnicindexes, 1);
|
2015-01-16 16:58:39 +00:00
|
|
|
VIR_DEBUG("Index %d for %s", nicindex,
|
|
|
|
ctrl->def->nets[i]->ifname);
|
|
|
|
ctrl->nicindexes[ctrl->nnicindexes-1] = nicindex;
|
|
|
|
break;
|
|
|
|
|
2018-12-06 14:59:59 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
|
|
|
break;
|
|
|
|
|
2015-01-16 16:58:39 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
2015-08-29 20:19:10 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_UDP:
|
2015-01-16 16:58:39 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
2020-10-14 17:08:25 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VDPA:
|
2022-08-24 20:46:05 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_NULL:
|
2022-08-17 12:35:17 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VDS:
|
2018-02-14 09:43:59 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unsupported net type %1$s"),
|
2018-12-05 21:58:08 +00:00
|
|
|
virDomainNetTypeToString(actualType));
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2018-02-14 09:43:59 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
2015-01-16 16:58:39 +00:00
|
|
|
default:
|
2018-12-05 21:58:08 +00:00
|
|
|
virReportEnumRangeError(virDomainNetType, actualType);
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2015-01-16 16:58:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:18:55 +00:00
|
|
|
return 0;
|
2015-01-16 16:58:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerValidateConsoles(virLXCController *ctrl)
|
2012-07-03 11:42:53 +00:00
|
|
|
{
|
|
|
|
if (ctrl->def->nconsoles != ctrl->nconsoles) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("expecting %1$zu consoles, but got %2$zu tty file handlers"),
|
2012-07-13 12:59:51 +00:00
|
|
|
ctrl->def->nconsoles, ctrl->nconsoles);
|
2012-07-03 11:42:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupLoopDeviceFS(virDomainFSDef *fs)
|
2011-08-04 09:13:02 +00:00
|
|
|
{
|
2012-07-03 14:06:27 +00:00
|
|
|
int lofd;
|
2011-08-04 09:13:02 +00:00
|
|
|
char *loname = NULL;
|
|
|
|
|
2016-07-14 13:52:38 +00:00
|
|
|
if ((lofd = virFileLoopDeviceAssociate(fs->src->path, &loname)) < 0)
|
2011-08-04 09:13:02 +00:00
|
|
|
return -1;
|
|
|
|
|
2013-10-08 15:36:26 +00:00
|
|
|
VIR_DEBUG("Changing fs %s to use type=block for dev %s",
|
2016-07-14 13:52:38 +00:00
|
|
|
fs->src->path, loname);
|
2011-08-04 09:13:02 +00:00
|
|
|
/*
|
|
|
|
* We now change it into a block device type, so that
|
|
|
|
* the rest of container setup 'just works'
|
|
|
|
*/
|
|
|
|
fs->type = VIR_DOMAIN_FS_TYPE_BLOCK;
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(fs->src->path);
|
2021-03-24 09:32:58 +00:00
|
|
|
fs->src->path = g_steal_pointer(&loname);
|
2011-08-04 09:13:02 +00:00
|
|
|
|
|
|
|
return lofd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupLoopDeviceDisk(virDomainDiskDef *disk)
|
2013-03-04 18:09:23 +00:00
|
|
|
{
|
|
|
|
int lofd;
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *loname = NULL;
|
2014-03-17 20:49:05 +00:00
|
|
|
const char *src = virDomainDiskGetSource(disk);
|
2013-03-04 18:09:23 +00:00
|
|
|
|
2014-03-17 20:49:05 +00:00
|
|
|
if ((lofd = virFileLoopDeviceAssociate(src, &loname)) < 0)
|
2013-03-04 18:09:23 +00:00
|
|
|
return -1;
|
|
|
|
|
2013-10-08 15:36:26 +00:00
|
|
|
VIR_DEBUG("Changing disk %s to use type=block for dev %s",
|
2014-03-17 20:49:05 +00:00
|
|
|
src, loname);
|
2013-10-08 15:36:26 +00:00
|
|
|
|
2013-03-04 18:09:23 +00:00
|
|
|
/*
|
|
|
|
* We now change it into a block device type, so that
|
|
|
|
* the rest of container setup 'just works'
|
|
|
|
*/
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
|
2020-11-05 06:23:41 +00:00
|
|
|
virDomainDiskSetSource(disk, loname);
|
2013-03-04 18:09:23 +00:00
|
|
|
|
|
|
|
return lofd;
|
2014-03-25 17:09:05 +00:00
|
|
|
|
2013-03-04 18:09:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupNBDDeviceFS(virDomainFSDef *fs)
|
2013-04-22 14:06:18 +00:00
|
|
|
{
|
|
|
|
char *dev;
|
|
|
|
|
|
|
|
if (fs->format <= VIR_STORAGE_FILE_NONE) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("An explicit disk format must be specified"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-07-14 13:52:38 +00:00
|
|
|
if (virFileNBDDeviceAssociate(fs->src->path,
|
2021-01-06 12:02:38 +00:00
|
|
|
virStorageFileFormatTypeToString(fs->format),
|
2013-04-22 14:06:18 +00:00
|
|
|
fs->readonly,
|
|
|
|
&dev) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-10-08 15:36:26 +00:00
|
|
|
VIR_DEBUG("Changing fs %s to use type=block for dev %s",
|
2016-07-14 13:52:38 +00:00
|
|
|
fs->src->path, dev);
|
2013-04-22 14:06:18 +00:00
|
|
|
/*
|
|
|
|
* We now change it into a block device type, so that
|
|
|
|
* the rest of container setup 'just works'
|
|
|
|
*/
|
2013-10-08 15:36:49 +00:00
|
|
|
fs->type = VIR_DOMAIN_FS_TYPE_BLOCK;
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(fs->src->path);
|
2016-07-14 13:52:38 +00:00
|
|
|
fs->src->path = dev;
|
2013-04-22 14:06:18 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupNBDDeviceDisk(virDomainDiskDef *disk)
|
2013-04-22 14:06:18 +00:00
|
|
|
{
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *dev = NULL;
|
2014-03-17 20:49:05 +00:00
|
|
|
const char *src = virDomainDiskGetSource(disk);
|
|
|
|
int format = virDomainDiskGetFormat(disk);
|
2013-04-22 14:06:18 +00:00
|
|
|
|
2014-03-17 20:49:05 +00:00
|
|
|
if (format <= VIR_STORAGE_FILE_NONE) {
|
2013-04-22 14:06:18 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("An explicit disk format must be specified"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-03-17 20:49:05 +00:00
|
|
|
if (virFileNBDDeviceAssociate(src,
|
2021-01-06 12:02:38 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
2014-06-24 13:15:55 +00:00
|
|
|
disk->src->readonly,
|
2013-04-22 14:06:18 +00:00
|
|
|
&dev) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-10-08 15:36:26 +00:00
|
|
|
VIR_DEBUG("Changing disk %s to use type=block for dev %s",
|
2014-03-17 20:49:05 +00:00
|
|
|
src, dev);
|
2013-04-22 14:06:18 +00:00
|
|
|
/*
|
|
|
|
* We now change it into a block device type, so that
|
|
|
|
* the rest of container setup 'just works'
|
|
|
|
*/
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
|
2020-11-05 06:23:41 +00:00
|
|
|
virDomainDiskSetSource(disk, dev);
|
2013-04-22 14:06:18 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerAppendNBDPids(virLXCController *ctrl,
|
2015-05-26 16:29:27 +00:00
|
|
|
const char *dev)
|
|
|
|
{
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *pidpath = NULL;
|
|
|
|
g_autofree pid_t *pids = NULL;
|
2015-07-15 07:58:18 +00:00
|
|
|
size_t npids = 0;
|
2015-05-26 16:29:27 +00:00
|
|
|
size_t i;
|
2015-07-15 08:13:21 +00:00
|
|
|
size_t loops = 0;
|
2015-05-26 16:29:27 +00:00
|
|
|
pid_t pid;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
if (!STRPREFIX(dev, "/dev/"))
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2015-05-26 16:29:27 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
pidpath = g_strdup_printf("/sys/devices/virtual/block/%s/pid", dev + 5);
|
|
|
|
|
2015-07-15 08:13:21 +00:00
|
|
|
/* Wait for the pid file to appear */
|
|
|
|
while (!virFileExists(pidpath)) {
|
|
|
|
/* wait for 100ms before checking again, but don't do it for ever */
|
|
|
|
if (errno == ENOENT && loops < 10) {
|
2019-10-02 17:01:11 +00:00
|
|
|
g_usleep(100 * 1000);
|
2015-07-15 08:13:21 +00:00
|
|
|
loops++;
|
|
|
|
} else {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Cannot check NBD device %1$s pid"),
|
2015-07-15 08:13:21 +00:00
|
|
|
dev + 5);
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2015-07-15 08:13:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 16:29:27 +00:00
|
|
|
if (virPidFileReadPath(pidpath, &pid) < 0)
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2015-05-26 16:29:27 +00:00
|
|
|
|
|
|
|
if (virProcessGetPids(pid, &npids, &pids) < 0)
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2015-05-26 16:29:27 +00:00
|
|
|
|
|
|
|
for (i = 0; i < npids; i++) {
|
2021-08-03 12:14:20 +00:00
|
|
|
VIR_APPEND_ELEMENT(ctrl->nbdpids, ctrl->nnbdpids, pids[i]);
|
2015-05-26 16:29:27 +00:00
|
|
|
}
|
|
|
|
|
2020-05-12 16:53:07 +00:00
|
|
|
return 0;
|
2015-05-26 16:29:27 +00:00
|
|
|
}
|
2013-04-22 14:06:18 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupLoopDevices(virLXCController *ctrl)
|
2011-08-04 09:13:02 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2013-07-09 13:24:10 +00:00
|
|
|
VIR_DEBUG("Setting up loop devices for filesystems");
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->def->nfss; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainFSDef *fs = ctrl->def->fss[i];
|
2011-08-04 09:13:02 +00:00
|
|
|
int fd;
|
|
|
|
|
2013-03-04 18:02:42 +00:00
|
|
|
if (fs->type != VIR_DOMAIN_FS_TYPE_FILE)
|
2011-08-04 09:13:02 +00:00
|
|
|
continue;
|
|
|
|
|
2013-07-09 13:23:06 +00:00
|
|
|
if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT) {
|
|
|
|
if (fs->format == VIR_STORAGE_FILE_RAW ||
|
|
|
|
fs->format == VIR_STORAGE_FILE_NONE)
|
|
|
|
fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_LOOP;
|
|
|
|
else
|
|
|
|
fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_NBD;
|
|
|
|
}
|
|
|
|
|
2013-04-22 14:06:15 +00:00
|
|
|
if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_LOOP) {
|
|
|
|
if (fs->format != VIR_STORAGE_FILE_RAW &&
|
|
|
|
fs->format != VIR_STORAGE_FILE_NONE) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("fs format %1$s is not supported"),
|
2013-04-22 14:06:15 +00:00
|
|
|
virStorageFileFormatTypeToString(fs->format));
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-04-22 14:06:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fd = virLXCControllerSetupLoopDeviceFS(fs);
|
|
|
|
if (fd < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-04-22 14:06:15 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Saving loop fd %d", fd);
|
2021-03-19 23:37:03 +00:00
|
|
|
VIR_EXPAND_N(ctrl->loopDevFds, ctrl->nloopDevs, 1);
|
2013-04-22 14:06:15 +00:00
|
|
|
ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd;
|
2013-04-22 14:06:18 +00:00
|
|
|
} else if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_NBD) {
|
|
|
|
if (virLXCControllerSetupNBDDeviceFS(fs) < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2015-05-26 16:29:27 +00:00
|
|
|
|
|
|
|
/* The NBD device will be cleaned up while the cgroup will end.
|
|
|
|
* For this we need to remember the qemu-nbd pid and add it to
|
2020-01-24 20:30:04 +00:00
|
|
|
* the cgroup */
|
2016-07-14 13:52:38 +00:00
|
|
|
if (virLXCControllerAppendNBDPids(ctrl, fs->src->path) < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-04-22 14:06:15 +00:00
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("fs driver %1$s is not supported"),
|
2014-05-14 19:48:15 +00:00
|
|
|
virDomainFSDriverTypeToString(fs->fsdriver));
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2011-08-04 09:13:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-09 13:24:10 +00:00
|
|
|
VIR_DEBUG("Setting up loop devices for disks");
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->def->ndisks; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDiskDef *disk = ctrl->def->disks[i];
|
2013-03-04 18:09:23 +00:00
|
|
|
int fd;
|
2014-03-17 20:49:05 +00:00
|
|
|
const char *driver = virDomainDiskGetDriver(disk);
|
|
|
|
int format = virDomainDiskGetFormat(disk);
|
2013-03-04 18:09:23 +00:00
|
|
|
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
if (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE)
|
2013-03-04 18:09:23 +00:00
|
|
|
continue;
|
|
|
|
|
2013-04-22 14:06:18 +00:00
|
|
|
/* If no driverName is set, we prefer 'loop' for
|
|
|
|
* dealing with raw or undefined formats, otherwise
|
|
|
|
* we use 'nbd'.
|
|
|
|
*/
|
2014-03-17 20:49:05 +00:00
|
|
|
if (STREQ_NULLABLE(driver, "loop") ||
|
|
|
|
(!driver &&
|
|
|
|
(format == VIR_STORAGE_FILE_RAW ||
|
|
|
|
format == VIR_STORAGE_FILE_NONE))) {
|
|
|
|
if (format != VIR_STORAGE_FILE_RAW &&
|
|
|
|
format != VIR_STORAGE_FILE_NONE) {
|
2013-03-04 18:09:23 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("disk format %1$s is not supported"),
|
2014-03-17 20:49:05 +00:00
|
|
|
virStorageFileFormatTypeToString(format));
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-03-04 18:09:23 +00:00
|
|
|
}
|
|
|
|
|
2013-04-22 14:06:15 +00:00
|
|
|
/* We treat 'none' as meaning 'raw' since we
|
|
|
|
* don't want to go into the auto-probing
|
|
|
|
* business for security reasons
|
|
|
|
*/
|
2013-03-04 18:09:23 +00:00
|
|
|
fd = virLXCControllerSetupLoopDeviceDisk(disk);
|
|
|
|
if (fd < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-03-04 18:09:23 +00:00
|
|
|
|
2013-04-22 14:06:15 +00:00
|
|
|
VIR_DEBUG("Saving loop fd %d", fd);
|
2021-03-19 23:37:03 +00:00
|
|
|
VIR_EXPAND_N(ctrl->loopDevFds, ctrl->nloopDevs, 1);
|
2013-04-22 14:06:15 +00:00
|
|
|
ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd;
|
2014-03-17 20:49:05 +00:00
|
|
|
} else if (!driver || STREQ(driver, "nbd")) {
|
2013-04-22 14:06:18 +00:00
|
|
|
if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT &&
|
|
|
|
disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Disk cache mode %1$s is not supported"),
|
2013-04-22 14:06:18 +00:00
|
|
|
virDomainDiskCacheTypeToString(disk->cachemode));
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-04-22 14:06:18 +00:00
|
|
|
}
|
|
|
|
if (virLXCControllerSetupNBDDeviceDisk(disk) < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2015-05-26 16:29:27 +00:00
|
|
|
|
|
|
|
/* The NBD device will be cleaned up while the cgroup will end.
|
|
|
|
* For this we need to remember the qemu-nbd pid and add it to
|
2020-01-24 20:30:04 +00:00
|
|
|
* the cgroup */
|
2015-05-26 16:29:27 +00:00
|
|
|
if (virLXCControllerAppendNBDPids(ctrl, virDomainDiskGetSource(disk)) < 0)
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-04-22 14:06:15 +00:00
|
|
|
} else {
|
2013-03-04 18:09:23 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("disk driver %1$s is not supported"),
|
2014-03-17 20:49:05 +00:00
|
|
|
driver);
|
2019-10-21 18:18:55 +00:00
|
|
|
return -1;
|
2013-03-04 18:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-04 09:13:02 +00:00
|
|
|
VIR_DEBUG("Setup all loop devices");
|
|
|
|
|
2019-10-21 18:18:55 +00:00
|
|
|
return 0;
|
2011-08-04 09:13:02 +00:00
|
|
|
}
|
|
|
|
|
2011-11-10 11:54:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* To be run while still single threaded
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupCpuAffinity(virLXCController *ctrl)
|
2011-11-10 11:54:53 +00:00
|
|
|
{
|
2012-09-14 07:47:01 +00:00
|
|
|
int hostcpus, maxcpu = CPU_SETSIZE;
|
2021-12-07 15:34:00 +00:00
|
|
|
g_autoptr(virBitmap) cpumap = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *cpumapToSet;
|
2011-11-10 11:54:53 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Setting CPU affinity");
|
|
|
|
|
|
|
|
/* setaffinity fails if you set bits for CPUs which
|
|
|
|
* aren't present, so we have to limit ourselves */
|
2016-04-13 17:16:16 +00:00
|
|
|
if ((hostcpus = virHostCPUGetCount()) < 0)
|
2012-11-13 12:54:37 +00:00
|
|
|
return -1;
|
|
|
|
|
2011-11-10 11:54:53 +00:00
|
|
|
if (maxcpu > hostcpus)
|
|
|
|
maxcpu = hostcpus;
|
|
|
|
|
2012-09-14 07:46:59 +00:00
|
|
|
cpumap = virBitmapNew(maxcpu);
|
2012-09-14 07:47:01 +00:00
|
|
|
cpumapToSet = cpumap;
|
|
|
|
|
2012-07-03 13:53:59 +00:00
|
|
|
if (ctrl->def->cpumask) {
|
2012-09-14 07:47:01 +00:00
|
|
|
cpumapToSet = ctrl->def->cpumask;
|
2011-11-10 11:54:53 +00:00
|
|
|
} else {
|
|
|
|
/* You may think this is redundant, but we can't assume libvirtd
|
|
|
|
* itself is running on all pCPUs, so we need to explicitly set
|
|
|
|
* the spawned LXC instance to all pCPUs if no map is given in
|
|
|
|
* its config file */
|
2012-09-14 07:46:59 +00:00
|
|
|
virBitmapSetAll(cpumap);
|
2011-11-10 11:54:53 +00:00
|
|
|
}
|
|
|
|
|
2012-09-14 07:46:59 +00:00
|
|
|
/* We are presuming we are running between fork/exec of LXC
|
2011-11-10 11:54:53 +00:00
|
|
|
* so use '0' to indicate our own process ID. No threads are
|
|
|
|
* running at this point
|
|
|
|
*/
|
2021-12-07 15:34:00 +00:00
|
|
|
if (virProcessSetAffinity(0 /* Self */, cpumapToSet, false) < 0)
|
2011-11-10 11:54:53 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerGetNumadAdvice(virLXCController *ctrl,
|
|
|
|
virBitmap **mask)
|
2013-03-18 09:04:02 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *nodemask = NULL;
|
2020-02-24 14:24:27 +00:00
|
|
|
g_autofree char *nodeset = NULL;
|
2013-03-18 09:04:02 +00:00
|
|
|
|
|
|
|
/* Get the advisory nodeset from numad if 'placement' of
|
|
|
|
* either <vcpu> or <numatune> is 'auto'.
|
|
|
|
*/
|
2014-06-09 13:00:22 +00:00
|
|
|
if (virDomainDefNeedsPlacementAdvice(ctrl->def)) {
|
2015-10-22 12:59:03 +00:00
|
|
|
nodeset = virNumaGetAutoPlacementAdvice(virDomainDefGetVcpus(ctrl->def),
|
2013-03-18 09:04:02 +00:00
|
|
|
ctrl->def->mem.cur_balloon);
|
|
|
|
if (!nodeset)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-03-18 09:04:02 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Nodeset returned from numad: %s", nodeset);
|
|
|
|
|
2016-06-17 12:56:45 +00:00
|
|
|
if (virBitmapParse(nodeset, &nodemask, VIR_DOMAIN_CPUMASK_LEN) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-03-18 09:04:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*mask = nodemask;
|
|
|
|
|
2020-02-24 14:24:27 +00:00
|
|
|
return 0;
|
2013-03-18 09:04:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-10 12:38:24 +00:00
|
|
|
/**
|
2012-07-03 13:53:59 +00:00
|
|
|
* virLXCControllerSetupResourceLimits
|
|
|
|
* @ctrl: the controller state
|
2011-11-10 12:38:24 +00:00
|
|
|
*
|
2015-01-16 16:23:45 +00:00
|
|
|
* Sets up the non-cgroup based resource limits that need
|
|
|
|
* to be inherited by the child process across clone()/exec().
|
|
|
|
* The cgroup limits are setup later
|
2011-11-10 12:38:24 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupResourceLimits(virLXCController *ctrl)
|
2011-11-10 12:38:24 +00:00
|
|
|
{
|
2021-12-07 15:34:00 +00:00
|
|
|
g_autoptr(virBitmap) auto_nodeset = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *nodeset = NULL;
|
2014-11-06 11:16:54 +00:00
|
|
|
virDomainNumatuneMemMode mode;
|
|
|
|
|
2015-05-19 09:55:26 +00:00
|
|
|
if (virDomainNumatuneGetMode(ctrl->def->numa, -1, &mode) == 0) {
|
2022-04-01 12:30:05 +00:00
|
|
|
if ((mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT ||
|
|
|
|
mode == VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE) &&
|
2015-05-19 09:55:26 +00:00
|
|
|
virCgroupControllerAvailable(VIR_CGROUP_CONTROLLER_CPUSET)) {
|
|
|
|
/* Use virNuma* API iff necessary. Once set and child is exec()-ed,
|
|
|
|
* there's no way for us to change it. Rely on cgroups (if available
|
|
|
|
* and enabled in the config) rather than virNuma*. */
|
|
|
|
VIR_DEBUG("Relying on CGroups for memory binding");
|
|
|
|
} else {
|
2014-11-06 11:16:54 +00:00
|
|
|
|
2015-05-19 09:55:26 +00:00
|
|
|
VIR_DEBUG("Setting up process resource limits");
|
2013-03-18 09:04:02 +00:00
|
|
|
|
2015-05-19 09:55:26 +00:00
|
|
|
if (virLXCControllerGetNumadAdvice(ctrl, &auto_nodeset) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2015-03-27 10:44:55 +00:00
|
|
|
|
2015-05-19 09:55:26 +00:00
|
|
|
nodeset = virDomainNumatuneGetNodeset(ctrl->def->numa, auto_nodeset, -1);
|
2015-03-27 10:44:55 +00:00
|
|
|
|
2015-05-19 09:55:26 +00:00
|
|
|
if (virNumaSetupMemoryPolicy(mode, nodeset) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2015-05-19 09:55:26 +00:00
|
|
|
}
|
2015-03-27 10:44:55 +00:00
|
|
|
}
|
2011-11-10 12:38:24 +00:00
|
|
|
|
2012-07-03 13:53:59 +00:00
|
|
|
if (virLXCControllerSetupCpuAffinity(ctrl) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2011-11-10 12:38:24 +00:00
|
|
|
|
2021-12-07 15:35:24 +00:00
|
|
|
return 0;
|
2015-01-16 16:23:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Creates the cgroup and sets up the various limits associated
|
|
|
|
* with it
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupCgroupLimits(virLXCController *ctrl)
|
2015-01-16 16:23:45 +00:00
|
|
|
{
|
2021-12-07 15:34:00 +00:00
|
|
|
g_autoptr(virBitmap) auto_nodeset = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *nodeset = NULL;
|
2015-05-26 16:29:27 +00:00
|
|
|
size_t i;
|
2015-01-16 16:23:45 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Setting up cgroup resource limits");
|
|
|
|
|
|
|
|
if (virLXCControllerGetNumadAdvice(ctrl, &auto_nodeset) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2015-01-16 16:23:45 +00:00
|
|
|
|
2015-02-11 13:54:59 +00:00
|
|
|
nodeset = virDomainNumatuneGetNodeset(ctrl->def->numa, auto_nodeset, -1);
|
2015-01-16 16:23:45 +00:00
|
|
|
|
|
|
|
if (!(ctrl->cgroup = virLXCCgroupCreate(ctrl->def,
|
2021-12-10 12:46:54 +00:00
|
|
|
ctrl->initpid,
|
2015-01-16 16:58:39 +00:00
|
|
|
ctrl->nnicindexes,
|
|
|
|
ctrl->nicindexes)))
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2015-01-16 16:23:45 +00:00
|
|
|
|
2021-12-10 12:46:54 +00:00
|
|
|
if (virCgroupAddMachineProcess(ctrl->cgroup, getpid()) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2015-01-16 16:23:45 +00:00
|
|
|
|
2015-05-26 16:29:27 +00:00
|
|
|
/* Add all qemu-nbd tasks to the cgroup */
|
|
|
|
for (i = 0; i < ctrl->nnbdpids; i++) {
|
2018-09-11 13:03:22 +00:00
|
|
|
if (virCgroupAddMachineProcess(ctrl->cgroup, ctrl->nbdpids[i]) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2015-05-26 16:29:27 +00:00
|
|
|
}
|
|
|
|
|
2014-11-06 11:16:54 +00:00
|
|
|
if (virLXCCgroupSetup(ctrl->def, ctrl->cgroup, nodeset) < 0)
|
2021-12-07 15:35:24 +00:00
|
|
|
return -1;
|
2011-11-10 12:38:24 +00:00
|
|
|
|
2021-12-07 15:35:24 +00:00
|
|
|
return 0;
|
2008-10-03 16:46:01 +00:00
|
|
|
}
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void virLXCControllerClientCloseHook(virNetServerClient *client)
|
2012-07-17 14:54:08 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = virNetServerClientGetPrivateData(client);
|
2012-07-17 14:54:08 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Client %p has closed", client);
|
2021-12-02 18:56:07 +00:00
|
|
|
if (ctrl->client == client) {
|
2012-07-17 14:54:08 +00:00
|
|
|
ctrl->client = NULL;
|
2021-12-02 18:56:07 +00:00
|
|
|
VIR_DEBUG("Client has gone away");
|
|
|
|
}
|
2012-07-17 14:54:08 +00:00
|
|
|
if (ctrl->inShutdown) {
|
|
|
|
VIR_DEBUG("Arm timer to quit event loop");
|
|
|
|
virEventUpdateTimeout(ctrl->timerShutdown, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-09 11:31:34 +00:00
|
|
|
static void virLXCControllerClientPrivateFree(void *data)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = data;
|
2012-11-22 16:45:39 +00:00
|
|
|
VIR_DEBUG("Got private data free %p", ctrl);
|
2012-08-09 11:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void *virLXCControllerClientPrivateNew(virNetServerClient *client,
|
2012-08-09 11:31:34 +00:00
|
|
|
void *opaque)
|
2012-07-03 14:25:30 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = opaque;
|
2012-08-09 11:31:34 +00:00
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
virNetServerClientSetCloseHook(client, virLXCControllerClientCloseHook);
|
|
|
|
VIR_DEBUG("Got new client %p", client);
|
|
|
|
ctrl->client = client;
|
2012-11-20 17:49:25 +00:00
|
|
|
|
|
|
|
if (ctrl->initpid && ctrl->firstClient)
|
|
|
|
virLXCControllerEventSendInit(ctrl, ctrl->initpid);
|
|
|
|
ctrl->firstClient = false;
|
|
|
|
|
2012-11-22 16:45:39 +00:00
|
|
|
return ctrl;
|
2008-08-20 20:55:32 +00:00
|
|
|
}
|
|
|
|
|
2012-07-03 14:25:30 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupServer(virLXCController *ctrl)
|
2008-08-20 20:55:32 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virNetServer *srv = NULL;
|
|
|
|
virNetServerService *svc = NULL;
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *sockpath = NULL;
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
sockpath = g_strdup_printf("%s/%s.sock", LXC_STATE_DIR, ctrl->name);
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2016-04-13 18:54:40 +00:00
|
|
|
if (!(srv = virNetServerNew("LXC", 1,
|
2016-03-01 14:34:15 +00:00
|
|
|
0, 0, 0, 1,
|
2015-07-20 12:51:24 +00:00
|
|
|
0, -1, 0,
|
2015-03-16 14:02:41 +00:00
|
|
|
virLXCControllerClientPrivateNew,
|
|
|
|
NULL,
|
|
|
|
virLXCControllerClientPrivateFree,
|
|
|
|
ctrl)))
|
2009-08-03 12:37:44 +00:00
|
|
|
goto error;
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2014-01-08 03:03:01 +00:00
|
|
|
if (virSecurityManagerSetSocketLabel(ctrl->securityManager, ctrl->def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2012-07-03 14:25:30 +00:00
|
|
|
if (!(svc = virNetServerServiceNewUNIX(sockpath,
|
|
|
|
0700,
|
|
|
|
0,
|
|
|
|
0,
|
2013-01-07 14:54:18 +00:00
|
|
|
NULL,
|
2012-07-03 14:25:30 +00:00
|
|
|
false,
|
2013-07-25 12:45:38 +00:00
|
|
|
0,
|
2013-01-07 14:54:18 +00:00
|
|
|
5)))
|
2008-08-20 20:55:32 +00:00
|
|
|
goto error;
|
2012-07-03 14:25:30 +00:00
|
|
|
|
2014-01-08 03:03:01 +00:00
|
|
|
if (virSecurityManagerClearSocketLabel(ctrl->securityManager, ctrl->def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2019-06-19 14:19:23 +00:00
|
|
|
if (virNetServerAddService(srv, svc) < 0)
|
2008-08-20 20:55:32 +00:00
|
|
|
goto error;
|
2022-01-28 17:42:45 +00:00
|
|
|
g_clear_pointer(&svc, virObjectUnref);
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2013-03-13 19:19:22 +00:00
|
|
|
if (!(ctrl->prog = virNetServerProgramNew(VIR_LXC_MONITOR_PROGRAM,
|
|
|
|
VIR_LXC_MONITOR_PROGRAM_VERSION,
|
|
|
|
virLXCMonitorProcs,
|
|
|
|
virLXCMonitorNProcs)))
|
2012-07-17 14:54:08 +00:00
|
|
|
goto error;
|
|
|
|
|
2015-03-16 14:02:41 +00:00
|
|
|
if (!(ctrl->daemon = virNetDaemonNew()) ||
|
2016-03-01 14:40:31 +00:00
|
|
|
virNetDaemonAddServer(ctrl->daemon, srv) < 0)
|
2015-03-16 14:02:41 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
virNetDaemonUpdateServices(ctrl->daemon, true);
|
2012-07-03 14:25:30 +00:00
|
|
|
return 0;
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
error:
|
2015-03-16 14:02:41 +00:00
|
|
|
virObjectUnref(srv);
|
2022-01-28 17:42:45 +00:00
|
|
|
g_clear_pointer(&ctrl->daemon, virObjectUnref);
|
2012-07-11 13:35:52 +00:00
|
|
|
virObjectUnref(svc);
|
2008-08-20 20:55:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-08-13 10:25:34 +00:00
|
|
|
|
2009-06-29 17:09:42 +00:00
|
|
|
|
|
|
|
static int lxcControllerClearCapabilities(void)
|
|
|
|
{
|
2012-09-20 14:17:56 +00:00
|
|
|
#if WITH_CAPNG
|
2009-06-29 17:09:42 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
capng_clear(CAPNG_SELECT_BOTH);
|
|
|
|
|
|
|
|
if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("failed to apply capabilities: %1$d"), ret);
|
2009-06-29 17:09:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#else
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("libcap-ng support not compiled in, unable to clear capabilities");
|
2009-06-29 17:09:42 +00:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-28 18:38:04 +00:00
|
|
|
static bool wantReboot;
|
2022-02-04 15:38:10 +00:00
|
|
|
static virMutex mutex = VIR_MUTEX_INITIALIZER;
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2021-12-02 18:56:07 +00:00
|
|
|
static int
|
|
|
|
virLXCControllerEventSendExit(virLXCController *ctrl,
|
|
|
|
int exitstatus);
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2021-12-02 18:56:07 +00:00
|
|
|
static void virLXCControllerSignalChildIO(virNetDaemon *dmn G_GNUC_UNUSED,
|
2019-10-14 12:45:33 +00:00
|
|
|
siginfo_t *info G_GNUC_UNUSED,
|
2012-07-03 11:12:59 +00:00
|
|
|
void *opaque)
|
2011-02-22 17:35:06 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = opaque;
|
2012-07-03 14:25:30 +00:00
|
|
|
int ret;
|
2012-07-23 11:25:37 +00:00
|
|
|
int status;
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2012-07-23 11:25:37 +00:00
|
|
|
ret = waitpid(-1, &status, WNOHANG);
|
2018-04-25 12:42:34 +00:00
|
|
|
VIR_DEBUG("Got sig child %d vs %lld", ret, (long long)ctrl->initpid);
|
2012-07-09 13:55:31 +00:00
|
|
|
if (ret == ctrl->initpid) {
|
2022-02-04 15:38:10 +00:00
|
|
|
VIR_WITH_MUTEX_LOCK_GUARD(&mutex) {
|
|
|
|
if (WIFSIGNALED(status) &&
|
|
|
|
WTERMSIG(status) == SIGHUP) {
|
|
|
|
VIR_DEBUG("Status indicates reboot");
|
|
|
|
wantReboot = true;
|
|
|
|
}
|
2013-11-01 16:24:30 +00:00
|
|
|
}
|
2021-12-02 18:56:07 +00:00
|
|
|
virLXCControllerEventSendExit(ctrl, wantReboot ? 1 : 0);
|
2012-07-09 13:55:31 +00:00
|
|
|
}
|
2011-10-19 15:22:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsole *console)
|
2011-10-19 15:22:24 +00:00
|
|
|
{
|
|
|
|
int hostEvents = 0;
|
|
|
|
int contEvents = 0;
|
|
|
|
|
2013-11-01 16:24:30 +00:00
|
|
|
/* If host console is open, then we can look to read/write */
|
|
|
|
if (!console->hostClosed) {
|
2011-10-19 15:22:24 +00:00
|
|
|
if (console->fromHostLen < sizeof(console->fromHostBuf))
|
|
|
|
hostEvents |= VIR_EVENT_HANDLE_READABLE;
|
|
|
|
if (console->fromContLen)
|
|
|
|
hostEvents |= VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
}
|
2013-11-01 16:24:30 +00:00
|
|
|
|
|
|
|
/* If cont console is open, then we can look to read/write */
|
|
|
|
if (!console->contClosed) {
|
2011-10-19 15:22:24 +00:00
|
|
|
if (console->fromContLen < sizeof(console->fromContBuf))
|
|
|
|
contEvents |= VIR_EVENT_HANDLE_READABLE;
|
|
|
|
if (console->fromHostLen)
|
|
|
|
contEvents |= VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
}
|
|
|
|
|
2013-11-01 16:24:30 +00:00
|
|
|
VIR_DEBUG("Container watch=%d, events=%d closed=%d; host watch=%d events=%d closed=%d",
|
|
|
|
console->contWatch, contEvents, console->contClosed,
|
|
|
|
console->hostWatch, hostEvents, console->hostClosed);
|
2011-10-19 15:22:24 +00:00
|
|
|
virEventUpdateHandle(console->contWatch, contEvents);
|
|
|
|
virEventUpdateHandle(console->hostWatch, hostEvents);
|
2011-02-22 17:35:06 +00:00
|
|
|
|
2012-01-12 17:03:03 +00:00
|
|
|
if (console->hostClosed) {
|
2013-11-01 16:24:30 +00:00
|
|
|
/* Must setup an epoll to detect when host becomes accessible again */
|
2012-01-12 17:03:03 +00:00
|
|
|
int events = EPOLLIN | EPOLLET;
|
2013-11-01 16:24:30 +00:00
|
|
|
if (console->fromContLen)
|
2012-01-12 17:03:03 +00:00
|
|
|
events |= EPOLLOUT;
|
|
|
|
|
|
|
|
if (events != console->hostEpoll) {
|
|
|
|
struct epoll_event event;
|
|
|
|
int action = EPOLL_CTL_ADD;
|
|
|
|
if (console->hostEpoll)
|
|
|
|
action = EPOLL_CTL_MOD;
|
|
|
|
|
|
|
|
VIR_DEBUG("newHostEvents=%x oldHostEvents=%x", events, console->hostEpoll);
|
|
|
|
|
|
|
|
event.events = events;
|
|
|
|
event.data.fd = console->hostFd;
|
|
|
|
if (epoll_ctl(console->epollFd, action, console->hostFd, &event) < 0) {
|
|
|
|
VIR_DEBUG(":fail");
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to add epoll fd"));
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(console->daemon);
|
2020-01-06 21:57:36 +00:00
|
|
|
return;
|
2012-01-12 17:03:03 +00:00
|
|
|
}
|
|
|
|
console->hostEpoll = events;
|
|
|
|
VIR_DEBUG("newHostEvents=%x oldHostEvents=%x", events, console->hostEpoll);
|
|
|
|
}
|
|
|
|
} else if (console->hostEpoll) {
|
|
|
|
VIR_DEBUG("Stop epoll oldContEvents=%x", console->hostEpoll);
|
|
|
|
if (epoll_ctl(console->epollFd, EPOLL_CTL_DEL, console->hostFd, NULL) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to remove epoll fd"));
|
2012-11-16 09:11:23 +00:00
|
|
|
VIR_DEBUG(":fail");
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(console->daemon);
|
2020-01-06 21:57:36 +00:00
|
|
|
return;
|
2012-01-12 17:03:03 +00:00
|
|
|
}
|
|
|
|
console->hostEpoll = 0;
|
|
|
|
}
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2012-01-12 17:03:03 +00:00
|
|
|
if (console->contClosed) {
|
2013-11-01 16:24:30 +00:00
|
|
|
/* Must setup an epoll to detect when guest becomes accessible again */
|
2012-01-12 17:03:03 +00:00
|
|
|
int events = EPOLLIN | EPOLLET;
|
2013-11-01 16:24:30 +00:00
|
|
|
if (console->fromHostLen)
|
2012-01-12 17:03:03 +00:00
|
|
|
events |= EPOLLOUT;
|
|
|
|
|
|
|
|
if (events != console->contEpoll) {
|
|
|
|
struct epoll_event event;
|
|
|
|
int action = EPOLL_CTL_ADD;
|
|
|
|
if (console->contEpoll)
|
|
|
|
action = EPOLL_CTL_MOD;
|
|
|
|
|
|
|
|
VIR_DEBUG("newContEvents=%x oldContEvents=%x", events, console->contEpoll);
|
|
|
|
|
|
|
|
event.events = events;
|
|
|
|
event.data.fd = console->contFd;
|
|
|
|
if (epoll_ctl(console->epollFd, action, console->contFd, &event) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to add epoll fd"));
|
|
|
|
VIR_DEBUG(":fail");
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(console->daemon);
|
2020-01-06 21:57:36 +00:00
|
|
|
return;
|
2012-01-12 17:03:03 +00:00
|
|
|
}
|
|
|
|
console->contEpoll = events;
|
|
|
|
VIR_DEBUG("newHostEvents=%x oldHostEvents=%x", events, console->contEpoll);
|
|
|
|
}
|
|
|
|
} else if (console->contEpoll) {
|
|
|
|
VIR_DEBUG("Stop epoll oldContEvents=%x", console->contEpoll);
|
|
|
|
if (epoll_ctl(console->epollFd, EPOLL_CTL_DEL, console->contFd, NULL) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to remove epoll fd"));
|
2012-11-16 09:11:23 +00:00
|
|
|
VIR_DEBUG(":fail");
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(console->daemon);
|
2020-01-06 21:57:36 +00:00
|
|
|
return;
|
2012-01-12 17:03:03 +00:00
|
|
|
}
|
|
|
|
console->contEpoll = 0;
|
|
|
|
}
|
|
|
|
}
|
2011-10-19 15:22:24 +00:00
|
|
|
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
static void virLXCControllerConsoleEPoll(int watch, int fd, int events, void *opaque)
|
2011-10-19 15:22:24 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerConsole *console = opaque;
|
2022-02-04 15:38:10 +00:00
|
|
|
VIR_LOCK_GUARD lock = virLockGuardLock(&mutex);
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2012-01-12 17:03:03 +00:00
|
|
|
VIR_DEBUG("IO event watch=%d fd=%d events=%d fromHost=%zu fromcont=%zu",
|
|
|
|
watch, fd, events,
|
|
|
|
console->fromHostLen,
|
|
|
|
console->fromContLen);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
struct epoll_event event;
|
|
|
|
int ret;
|
|
|
|
ret = epoll_wait(console->epollFd, &event, 1, 0);
|
2011-10-19 15:22:24 +00:00
|
|
|
if (ret < 0) {
|
2012-04-27 18:39:17 +00:00
|
|
|
if (errno == EINTR)
|
2011-10-19 15:22:24 +00:00
|
|
|
continue;
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to wait on epoll"));
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(console->daemon);
|
2022-02-04 15:38:10 +00:00
|
|
|
return;
|
2011-10-19 15:22:24 +00:00
|
|
|
}
|
|
|
|
|
2012-01-12 17:03:03 +00:00
|
|
|
if (ret == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
VIR_DEBUG("fd=%d hostFd=%d contFd=%d hostEpoll=%x contEpoll=%x",
|
|
|
|
event.data.fd, console->hostFd, console->contFd,
|
|
|
|
console->hostEpoll, console->contEpoll);
|
|
|
|
|
2011-10-19 15:22:24 +00:00
|
|
|
/* If we get HUP+dead PID, we just re-enable the main loop
|
|
|
|
* which will see the PID has died and exit */
|
2013-11-01 16:24:30 +00:00
|
|
|
if ((event.events & (EPOLLIN|EPOLLOUT))) {
|
2012-01-12 17:03:03 +00:00
|
|
|
if (event.data.fd == console->hostFd) {
|
|
|
|
console->hostClosed = false;
|
2011-10-19 15:22:24 +00:00
|
|
|
} else {
|
2012-01-12 17:03:03 +00:00
|
|
|
console->contClosed = false;
|
2011-10-19 15:22:24 +00:00
|
|
|
}
|
2012-07-03 11:42:53 +00:00
|
|
|
virLXCControllerConsoleUpdateWatch(console);
|
2011-10-19 15:22:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
static void virLXCControllerConsoleIO(int watch, int fd, int events, void *opaque)
|
2011-10-19 15:22:24 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerConsole *console = opaque;
|
2022-02-04 15:38:10 +00:00
|
|
|
VIR_LOCK_GUARD lock = virLockGuardLock(&mutex);
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2012-01-12 17:03:03 +00:00
|
|
|
VIR_DEBUG("IO event watch=%d fd=%d events=%d fromHost=%zu fromcont=%zu",
|
|
|
|
watch, fd, events,
|
|
|
|
console->fromHostLen,
|
|
|
|
console->fromContLen);
|
2011-10-19 15:22:24 +00:00
|
|
|
if (events & VIR_EVENT_HANDLE_READABLE) {
|
|
|
|
char *buf;
|
|
|
|
size_t *len;
|
|
|
|
size_t avail;
|
|
|
|
ssize_t done;
|
|
|
|
if (watch == console->hostWatch) {
|
|
|
|
buf = console->fromHostBuf;
|
|
|
|
len = &console->fromHostLen;
|
|
|
|
avail = sizeof(console->fromHostBuf) - *len;
|
|
|
|
} else {
|
|
|
|
buf = console->fromContBuf;
|
|
|
|
len = &console->fromContLen;
|
|
|
|
avail = sizeof(console->fromContBuf) - *len;
|
|
|
|
}
|
2015-05-12 12:40:34 +00:00
|
|
|
reread:
|
2011-10-19 15:22:24 +00:00
|
|
|
done = read(fd, buf + *len, avail);
|
|
|
|
if (done == -1 && errno == EINTR)
|
|
|
|
goto reread;
|
|
|
|
if (done == -1 && errno != EAGAIN) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to read container pty"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (done > 0) {
|
|
|
|
*len += done;
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Read fd %d done %d errno %d", fd, (int)done, errno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (events & VIR_EVENT_HANDLE_WRITABLE) {
|
|
|
|
char *buf;
|
|
|
|
size_t *len;
|
|
|
|
ssize_t done;
|
|
|
|
if (watch == console->hostWatch) {
|
|
|
|
buf = console->fromContBuf;
|
|
|
|
len = &console->fromContLen;
|
|
|
|
} else {
|
|
|
|
buf = console->fromHostBuf;
|
|
|
|
len = &console->fromHostLen;
|
|
|
|
}
|
|
|
|
|
2015-05-12 12:40:34 +00:00
|
|
|
rewrite:
|
2022-02-14 15:39:00 +00:00
|
|
|
done = write(fd, buf, *len); /* sc_avoid_write */
|
2011-10-19 15:22:24 +00:00
|
|
|
if (done == -1 && errno == EINTR)
|
|
|
|
goto rewrite;
|
|
|
|
if (done == -1 && errno != EAGAIN) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to write to container pty"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (done > 0) {
|
|
|
|
memmove(buf, buf + done, (*len - done));
|
|
|
|
*len -= done;
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Write fd %d done %d errno %d", fd, (int)done, errno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (events & VIR_EVENT_HANDLE_HANGUP) {
|
|
|
|
if (watch == console->hostWatch) {
|
|
|
|
console->hostClosed = true;
|
|
|
|
} else {
|
|
|
|
console->contClosed = true;
|
|
|
|
}
|
|
|
|
VIR_DEBUG("Got EOF on %d %d", watch, fd);
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
virLXCControllerConsoleUpdateWatch(console);
|
2011-10-19 15:22:24 +00:00
|
|
|
return;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
error:
|
2011-10-19 15:22:24 +00:00
|
|
|
virEventRemoveHandle(console->contWatch);
|
|
|
|
virEventRemoveHandle(console->hostWatch);
|
|
|
|
console->contWatch = console->hostWatch = -1;
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonQuit(console->daemon);
|
2011-10-19 15:22:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-13 10:25:34 +00:00
|
|
|
/**
|
2009-11-05 12:35:13 +00:00
|
|
|
* lxcControllerMain
|
2011-10-19 15:22:24 +00:00
|
|
|
* @serverFd: server socket fd to accept client requests
|
|
|
|
* @clientFd: initial client which is the libvirtd daemon
|
2008-08-13 10:25:34 +00:00
|
|
|
*
|
2011-10-19 15:22:24 +00:00
|
|
|
* Processes I/O on consoles and the monitor
|
2008-08-13 10:25:34 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerMain(virLXCController *ctrl)
|
2008-08-13 10:25:34 +00:00
|
|
|
{
|
|
|
|
int rc = -1;
|
2011-10-20 08:44:31 +00:00
|
|
|
size_t i;
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2015-03-16 14:02:41 +00:00
|
|
|
if (virNetDaemonAddSignalHandler(ctrl->daemon,
|
2012-07-03 14:25:30 +00:00
|
|
|
SIGCHLD,
|
|
|
|
virLXCControllerSignalChildIO,
|
|
|
|
ctrl) < 0)
|
2008-08-13 10:25:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-10-19 15:22:24 +00:00
|
|
|
virResetLastError();
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nconsoles; i++) {
|
2012-07-03 11:42:53 +00:00
|
|
|
if ((ctrl->consoles[i].epollFd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
|
2012-01-12 17:03:03 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to create epoll fd"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
if ((ctrl->consoles[i].epollWatch = virEventAddHandle(ctrl->consoles[i].epollFd,
|
|
|
|
VIR_EVENT_HANDLE_READABLE,
|
|
|
|
virLXCControllerConsoleEPoll,
|
|
|
|
&(ctrl->consoles[i]),
|
|
|
|
NULL)) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to watch epoll FD"));
|
2012-01-12 17:03:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
if ((ctrl->consoles[i].hostWatch = virEventAddHandle(ctrl->consoles[i].hostFd,
|
|
|
|
VIR_EVENT_HANDLE_READABLE,
|
|
|
|
virLXCControllerConsoleIO,
|
|
|
|
&(ctrl->consoles[i]),
|
|
|
|
NULL)) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to watch host console PTY"));
|
2011-10-20 08:44:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
if ((ctrl->consoles[i].contWatch = virEventAddHandle(ctrl->consoles[i].contFd,
|
|
|
|
VIR_EVENT_HANDLE_READABLE,
|
|
|
|
virLXCControllerConsoleIO,
|
|
|
|
&(ctrl->consoles[i]),
|
|
|
|
NULL)) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to watch host console PTY"));
|
2011-10-20 08:44:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-10-19 15:22:24 +00:00
|
|
|
}
|
2008-08-13 10:25:34 +00:00
|
|
|
|
2015-03-16 14:02:41 +00:00
|
|
|
virNetDaemonRun(ctrl->daemon);
|
2008-08-13 10:25:34 +00:00
|
|
|
|
2018-05-05 12:04:21 +00:00
|
|
|
if (virGetLastErrorCode() == VIR_ERR_OK)
|
2012-07-23 11:25:37 +00:00
|
|
|
rc = wantReboot ? 1 : 0;
|
2008-08-13 10:25:34 +00:00
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nconsoles; i++)
|
2012-07-03 11:42:53 +00:00
|
|
|
virLXCControllerConsoleClose(&(ctrl->consoles[i]));
|
2012-01-12 17:03:03 +00:00
|
|
|
|
2008-08-13 10:25:34 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2014-07-28 20:59:17 +00:00
|
|
|
static unsigned int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerLookupUsernsMap(virDomainIdMapEntry *map,
|
2014-07-28 20:59:17 +00:00
|
|
|
int num,
|
|
|
|
unsigned int src)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
if (src > map[i].start && src < map[i].start + map[i].count)
|
|
|
|
return map[i].target + (src - map[i].start);
|
|
|
|
}
|
|
|
|
|
|
|
|
return src;
|
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2013-06-07 07:12:21 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupUsernsMap(virDomainIdMapEntry *map,
|
2013-06-07 07:12:21 +00:00
|
|
|
int num,
|
|
|
|
char *path)
|
|
|
|
{
|
2020-07-02 22:23:25 +00:00
|
|
|
g_auto(virBuffer) map_value = VIR_BUFFER_INITIALIZER;
|
Convert 'int i' to 'size_t i' in src/lxc/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-06-07 07:12:21 +00:00
|
|
|
|
2018-12-15 10:02:34 +00:00
|
|
|
/* The kernel supports up to 340 lines in /proc/<pid>/{g,u}id_map */
|
|
|
|
if (num > 340) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Too many id mappings defined."));
|
2020-07-03 03:21:25 +00:00
|
|
|
return -1;
|
2018-12-15 10:02:34 +00:00
|
|
|
}
|
|
|
|
|
2023-08-01 13:32:16 +00:00
|
|
|
VIR_DEBUG("Set '%s' mappings to:", path);
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
VIR_DEBUG("%u %u %u", map[i].start, map[i].target, map[i].count);
|
2013-06-07 07:12:21 +00:00
|
|
|
virBufferAsprintf(&map_value, "%u %u %u\n",
|
|
|
|
map[i].start, map[i].target, map[i].count);
|
2023-08-01 13:32:16 +00:00
|
|
|
}
|
2013-07-01 16:42:25 +00:00
|
|
|
|
2013-06-07 07:12:21 +00:00
|
|
|
if (virFileWriteStr(path, virBufferCurrentContent(&map_value), 0) < 0) {
|
2023-03-09 11:22:28 +00:00
|
|
|
virReportSystemError(errno, _("unable write to %1$s"), path);
|
2020-07-03 03:21:25 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:21 +00:00
|
|
|
}
|
|
|
|
|
2020-07-03 03:21:25 +00:00
|
|
|
return 0;
|
2013-06-07 07:12:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virLXCControllerSetupUserns
|
|
|
|
*
|
|
|
|
* Set proc files for user namespace
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupUserns(virLXCController *ctrl)
|
2013-06-07 07:12:21 +00:00
|
|
|
{
|
2020-02-24 14:24:27 +00:00
|
|
|
g_autofree char *uid_map = NULL;
|
|
|
|
g_autofree char *gid_map = NULL;
|
2013-06-07 07:12:21 +00:00
|
|
|
|
|
|
|
/* User namespace is disabled for container */
|
2015-01-16 17:20:48 +00:00
|
|
|
if (ctrl->def->idmap.nuidmap == 0) {
|
|
|
|
VIR_DEBUG("No uid map, skipping userns setup");
|
2013-06-07 07:12:21 +00:00
|
|
|
return 0;
|
2015-01-16 17:20:48 +00:00
|
|
|
}
|
2013-06-07 07:12:21 +00:00
|
|
|
|
2015-01-16 17:20:48 +00:00
|
|
|
VIR_DEBUG("Setting up userns maps");
|
2019-10-22 13:26:14 +00:00
|
|
|
uid_map = g_strdup_printf("/proc/%d/uid_map", ctrl->initpid);
|
2013-06-07 07:12:21 +00:00
|
|
|
|
|
|
|
if (virLXCControllerSetupUsernsMap(ctrl->def->idmap.uidmap,
|
|
|
|
ctrl->def->idmap.nuidmap,
|
|
|
|
uid_map) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:21 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
gid_map = g_strdup_printf("/proc/%d/gid_map", ctrl->initpid);
|
2013-06-07 07:12:21 +00:00
|
|
|
|
|
|
|
if (virLXCControllerSetupUsernsMap(ctrl->def->idmap.gidmap,
|
|
|
|
ctrl->def->idmap.ngidmap,
|
|
|
|
gid_map) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:21 +00:00
|
|
|
|
2020-02-24 14:24:27 +00:00
|
|
|
return 0;
|
2013-06-07 07:12:21 +00:00
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupDev(virLXCController *ctrl)
|
2013-06-07 07:12:22 +00:00
|
|
|
{
|
2020-02-24 14:24:27 +00:00
|
|
|
g_autofree char *mount_options = NULL;
|
|
|
|
g_autofree char *opts = NULL;
|
|
|
|
g_autofree char *dev = NULL;
|
2013-06-07 07:12:22 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Setting up /dev/ for container");
|
|
|
|
|
|
|
|
mount_options = virSecurityManagerGetMountOptions(ctrl->securityManager,
|
|
|
|
ctrl->def);
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
dev = g_strdup_printf("/%s/%s.dev", LXC_STATE_DIR, ctrl->def->name);
|
2013-06-07 07:12:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* tmpfs is limited to 64kb, since we only have device nodes in there
|
|
|
|
* and don't want to DOS the entire OS RAM usage
|
|
|
|
*/
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
opts = g_strdup_printf("mode=755,size=65536%s", mount_options);
|
2013-06-07 07:12:22 +00:00
|
|
|
|
2016-11-10 15:17:48 +00:00
|
|
|
if (virFileSetupDev(dev, opts) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:22 +00:00
|
|
|
|
2013-07-16 02:00:02 +00:00
|
|
|
if (lxcContainerChown(ctrl->def, dev) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:24 +00:00
|
|
|
|
2020-02-24 14:24:27 +00:00
|
|
|
return 0;
|
2013-06-07 07:12:22 +00:00
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerPopulateDevices(virLXCController *ctrl)
|
2013-06-07 07:12:22 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
const struct {
|
|
|
|
int maj;
|
|
|
|
int min;
|
|
|
|
mode_t mode;
|
|
|
|
const char *path;
|
|
|
|
} devs[] = {
|
|
|
|
{ LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/null" },
|
|
|
|
{ LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/zero" },
|
|
|
|
{ LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/full" },
|
|
|
|
{ LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/random" },
|
|
|
|
{ LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/urandom" },
|
2013-07-09 10:05:14 +00:00
|
|
|
{ LXC_DEV_MAJ_TTY, LXC_DEV_MIN_TTY, 0666, "/tty" },
|
2013-06-07 07:12:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (virLXCControllerSetupDev(ctrl) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:22 +00:00
|
|
|
|
|
|
|
/* Populate /dev/ with a few important bits */
|
2019-10-15 11:55:26 +00:00
|
|
|
for (i = 0; i < G_N_ELEMENTS(devs); i++) {
|
2020-06-16 12:07:04 +00:00
|
|
|
g_autofree char *path = NULL;
|
2020-07-28 17:50:28 +00:00
|
|
|
dev_t dev;
|
2020-06-16 12:07:04 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
path = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR, ctrl->def->name,
|
|
|
|
devs[i].path);
|
2013-06-07 07:12:22 +00:00
|
|
|
|
2020-07-28 17:50:28 +00:00
|
|
|
dev = makedev(devs[i].maj, devs[i].min);
|
2013-06-07 07:12:22 +00:00
|
|
|
if (mknod(path, S_IFCHR, dev) < 0 ||
|
|
|
|
chmod(path, devs[i].mode)) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failed to make device %1$s"),
|
2013-06-07 07:12:22 +00:00
|
|
|
path);
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:22 +00:00
|
|
|
}
|
2013-06-07 07:12:25 +00:00
|
|
|
|
2013-07-16 02:00:02 +00:00
|
|
|
if (lxcContainerChown(ctrl->def, path) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2013-06-07 07:12:22 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 14:24:27 +00:00
|
|
|
return 0;
|
2013-06-07 07:12:22 +00:00
|
|
|
}
|
2013-06-07 07:12:21 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2020-03-02 00:54:12 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupTimers(virLXCController *ctrl)
|
2020-03-02 00:54:12 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDef *def = ctrl->def;
|
2020-03-02 00:54:12 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* Not sync'ed with Host clock */
|
|
|
|
if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < def->clock.ntimers; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainTimerDef *timer = def->clock.timers[i];
|
2020-03-02 00:54:12 +00:00
|
|
|
g_autofree char *path = NULL;
|
|
|
|
const char *timer_dev = NULL;
|
|
|
|
struct stat sb;
|
|
|
|
dev_t dev;
|
|
|
|
|
|
|
|
/* Check if "present" is set to "no" otherwise enable it. */
|
2022-01-23 20:15:10 +00:00
|
|
|
if (timer->present == VIR_TRISTATE_BOOL_NO)
|
2020-03-02 00:54:12 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
switch ((virDomainTimerNameType)timer->name) {
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_TSC:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_PIT:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_LAST:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("unsupported timer type (name) '%1$s'"),
|
2020-03-02 00:54:12 +00:00
|
|
|
virDomainTimerNameTypeToString(timer->name));
|
|
|
|
return -1;
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_RTC:
|
|
|
|
timer_dev = "/dev/rtc0";
|
|
|
|
path = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR,
|
|
|
|
def->name, "/rtc");
|
|
|
|
break;
|
2020-03-02 00:54:13 +00:00
|
|
|
case VIR_DOMAIN_TIMER_NAME_HPET:
|
|
|
|
timer_dev = "/dev/hpet";
|
|
|
|
path = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR,
|
|
|
|
ctrl->def->name, "/hpet");
|
|
|
|
break;
|
2020-03-02 00:54:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!timer_dev)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (stat(timer_dev, &sb) < 0) {
|
2023-03-09 11:22:28 +00:00
|
|
|
virReportSystemError(errno, _("Unable to access %1$s"),
|
2020-03-02 00:54:12 +00:00
|
|
|
timer_dev);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev = makedev(major(sb.st_rdev), minor(sb.st_rdev));
|
|
|
|
if (mknod(path, S_IFCHR, dev) < 0 ||
|
|
|
|
chmod(path, sb.st_mode)) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failed to make device %1$s"),
|
2020-03-02 00:54:12 +00:00
|
|
|
path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lxcContainerChown(def, path) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-16 02:00:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupHostdevSubsysUSB(virDomainDef *vmDef,
|
|
|
|
virDomainHostdevDef *def,
|
|
|
|
virSecurityManager *securityDriver)
|
2013-07-16 02:00:04 +00:00
|
|
|
{
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *src = NULL;
|
|
|
|
g_autofree char *dstdir = NULL;
|
|
|
|
g_autofree char *dstfile = NULL;
|
|
|
|
g_autofree char *vroot = NULL;
|
2013-07-16 02:00:04 +00:00
|
|
|
struct stat sb;
|
|
|
|
mode_t mode;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysUSB *usbsrc = &def->source.subsys.u.usb;
|
2013-07-16 02:00:04 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
src = g_strdup_printf(USB_DEVFS "/%03d/%03d", usbsrc->bus, usbsrc->device);
|
2013-07-16 02:00:04 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
vroot = g_strdup_printf("/%s/%s.dev/bus/usb/", LXC_STATE_DIR, vmDef->name);
|
2013-07-16 02:00:04 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
dstdir = g_strdup_printf("%s/%03d/", vroot, usbsrc->bus);
|
2013-07-16 02:00:04 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
dstfile = g_strdup_printf("%s/%03d", dstdir, usbsrc->device);
|
2013-07-16 02:00:04 +00:00
|
|
|
|
|
|
|
if (stat(src, &sb) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to access %1$s"), src);
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2013-07-16 02:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!S_ISCHR(sb.st_mode)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("USB source %1$s was not a character device"),
|
2013-07-16 02:00:04 +00:00
|
|
|
src);
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2013-07-16 02:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mode = 0700 | S_IFCHR;
|
|
|
|
|
2021-02-26 08:37:10 +00:00
|
|
|
if (g_mkdir_with_parents(dstdir, 0777) < 0) {
|
2013-07-16 02:00:04 +00:00
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to create %1$s"), dstdir);
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2013-07-16 02:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Creating dev %s (%d,%d)",
|
|
|
|
dstfile, major(sb.st_rdev), minor(sb.st_rdev));
|
|
|
|
if (mknod(dstfile, mode, sb.st_rdev) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to create device %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dstfile);
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2013-07-16 02:00:04 +00:00
|
|
|
}
|
|
|
|
|
2013-07-16 02:00:05 +00:00
|
|
|
if (lxcContainerChown(vmDef, dstfile) < 0)
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2013-07-16 02:00:05 +00:00
|
|
|
|
2013-07-16 02:00:04 +00:00
|
|
|
if (virSecurityManagerSetHostdevLabel(securityDriver,
|
|
|
|
vmDef, def, vroot) < 0)
|
2020-05-12 16:53:07 +00:00
|
|
|
return -1;
|
2013-07-16 02:00:04 +00:00
|
|
|
|
2020-05-12 16:53:07 +00:00
|
|
|
return 0;
|
2013-07-16 02:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupHostdevCapsStorage(virDomainDef *vmDef,
|
|
|
|
virDomainHostdevDef *def,
|
|
|
|
virSecurityManager *securityDriver)
|
2013-07-16 02:00:04 +00:00
|
|
|
{
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *dst = NULL;
|
|
|
|
g_autofree char *path = NULL;
|
2013-07-16 02:00:04 +00:00
|
|
|
int len = 0;
|
|
|
|
int ret = -1;
|
|
|
|
struct stat sb;
|
|
|
|
mode_t mode;
|
|
|
|
char *dev = def->source.caps.u.storage.block;
|
|
|
|
|
|
|
|
if (dev == NULL) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Missing storage host block path"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
path = g_strdup(dev);
|
2013-07-16 02:00:04 +00:00
|
|
|
|
|
|
|
while (*(path + len) == '/')
|
|
|
|
len++;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
dst = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR, vmDef->name,
|
|
|
|
strchr(path + len, '/'));
|
2013-07-16 02:00:04 +00:00
|
|
|
|
|
|
|
if (stat(dev, &sb) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to access %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dev);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!S_ISBLK(sb.st_mode)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Storage source %1$s must be a block device"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dev);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) {
|
|
|
|
virReportError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failed to create directory for device %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dev);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode = 0700 | S_IFBLK;
|
|
|
|
|
|
|
|
VIR_DEBUG("Creating dev %s (%d,%d)", dst,
|
|
|
|
major(sb.st_rdev), minor(sb.st_rdev));
|
|
|
|
if (mknod(dst, mode, sb.st_rdev) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to create device %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dst);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-16 02:00:05 +00:00
|
|
|
if (lxcContainerChown(vmDef, dst) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-16 02:00:04 +00:00
|
|
|
def->source.caps.u.storage.block = dst;
|
|
|
|
if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2013-07-16 02:00:04 +00:00
|
|
|
def->source.caps.u.storage.block = dev;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupHostdevCapsMisc(virDomainDef *vmDef,
|
|
|
|
virDomainHostdevDef *def,
|
|
|
|
virSecurityManager *securityDriver)
|
2013-07-16 02:00:04 +00:00
|
|
|
{
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *dst = NULL;
|
|
|
|
g_autofree char *path = NULL;
|
2013-07-16 02:00:04 +00:00
|
|
|
int len = 0;
|
|
|
|
int ret = -1;
|
|
|
|
struct stat sb;
|
|
|
|
mode_t mode;
|
|
|
|
char *dev = def->source.caps.u.misc.chardev;
|
|
|
|
|
|
|
|
if (dev == NULL) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Missing storage host block path"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
path = g_strdup(dev);
|
2013-07-16 02:00:04 +00:00
|
|
|
|
|
|
|
while (*(path + len) == '/')
|
|
|
|
len++;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
dst = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR, vmDef->name,
|
|
|
|
strchr(path + len, '/'));
|
2013-07-16 02:00:04 +00:00
|
|
|
|
|
|
|
if (stat(dev, &sb) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to access %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dev);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!S_ISCHR(sb.st_mode)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Storage source %1$s must be a character device"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dev);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) {
|
|
|
|
virReportError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failed to create directory for device %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dst);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode = 0700 | S_IFCHR;
|
|
|
|
|
|
|
|
VIR_DEBUG("Creating dev %s (%d,%d)", dst,
|
|
|
|
major(sb.st_rdev), minor(sb.st_rdev));
|
|
|
|
if (mknod(dst, mode, sb.st_rdev) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to create device %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
dev);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-16 02:00:05 +00:00
|
|
|
if (lxcContainerChown(vmDef, dst) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-16 02:00:04 +00:00
|
|
|
def->source.caps.u.misc.chardev = dst;
|
|
|
|
if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2013-07-16 02:00:04 +00:00
|
|
|
def->source.caps.u.misc.chardev = dev;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupHostdevSubsys(virDomainDef *vmDef,
|
|
|
|
virDomainHostdevDef *def,
|
|
|
|
virSecurityManager *securityDriver)
|
2013-07-16 02:00:04 +00:00
|
|
|
{
|
|
|
|
switch (def->source.subsys.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
|
|
|
return virLXCControllerSetupHostdevSubsysUSB(vmDef,
|
|
|
|
def,
|
|
|
|
securityDriver);
|
|
|
|
|
2023-04-24 12:13:53 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
|
2013-07-16 02:00:04 +00:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unsupported host device mode %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
virDomainHostdevSubsysTypeToString(def->source.subsys.type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupHostdevCaps(virDomainDef *vmDef,
|
|
|
|
virDomainHostdevDef *def,
|
|
|
|
virSecurityManager *securityDriver)
|
2013-07-16 02:00:04 +00:00
|
|
|
{
|
2023-04-25 08:00:18 +00:00
|
|
|
switch (def->source.caps.type) {
|
2013-07-16 02:00:04 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
|
|
|
|
return virLXCControllerSetupHostdevCapsStorage(vmDef,
|
|
|
|
def,
|
|
|
|
securityDriver);
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
|
|
|
|
return virLXCControllerSetupHostdevCapsMisc(vmDef,
|
|
|
|
def,
|
|
|
|
securityDriver);
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
|
2017-04-27 06:47:19 +00:00
|
|
|
return 0; /* case is handled in virLXCControllerMoveInterfaces */
|
2013-07-16 02:00:04 +00:00
|
|
|
|
2023-04-24 12:13:32 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST:
|
2013-07-16 02:00:04 +00:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unsupported host device mode %1$s"),
|
2023-09-13 12:41:00 +00:00
|
|
|
virDomainHostdevCapsTypeToString(def->source.caps.type));
|
2013-07-16 02:00:04 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupAllHostdevs(virLXCController *ctrl)
|
2013-07-16 02:00:04 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDef *vmDef = ctrl->def;
|
|
|
|
virSecurityManager *securityDriver = ctrl->securityManager;
|
2013-07-16 02:00:04 +00:00
|
|
|
VIR_DEBUG("Setting up hostdevs");
|
|
|
|
|
|
|
|
for (i = 0; i < vmDef->nhostdevs; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevDef *def = vmDef->hostdevs[i];
|
2013-07-16 02:00:04 +00:00
|
|
|
switch (def->mode) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
|
|
|
|
if (virLXCControllerSetupHostdevSubsys(vmDef,
|
|
|
|
def,
|
|
|
|
securityDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
|
|
|
|
if (virLXCControllerSetupHostdevCaps(vmDef,
|
|
|
|
def,
|
|
|
|
securityDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
default:
|
2023-04-24 11:15:27 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_LAST:
|
2013-07-16 02:00:04 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unsupported host device mode %1$s"),
|
2013-07-16 02:00:04 +00:00
|
|
|
virDomainHostdevModeTypeToString(def->mode));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Setup all hostdevs");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupDisk(virLXCController *ctrl,
|
|
|
|
virDomainDiskDef *def,
|
|
|
|
virSecurityManager *securityDriver)
|
2013-07-16 02:00:00 +00:00
|
|
|
{
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *dst = NULL;
|
2013-07-16 02:00:00 +00:00
|
|
|
int ret = -1;
|
|
|
|
struct stat sb;
|
|
|
|
mode_t mode;
|
2014-05-21 23:13:12 +00:00
|
|
|
char *tmpsrc = def->src->path;
|
2013-07-16 02:00:00 +00:00
|
|
|
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
if (virDomainDiskGetType(def) != VIR_STORAGE_TYPE_BLOCK) {
|
2013-07-16 02:00:00 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Can't setup disk for non-block device"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-03-17 20:49:05 +00:00
|
|
|
if (!tmpsrc) {
|
2013-07-16 02:00:00 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Can't setup disk without media"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
dst = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR, ctrl->def->name,
|
|
|
|
def->dst);
|
2013-07-16 02:00:00 +00:00
|
|
|
|
2014-05-21 23:13:12 +00:00
|
|
|
if (stat(def->src->path, &sb) < 0) {
|
2013-07-16 02:00:00 +00:00
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to access %1$s"), tmpsrc);
|
2013-07-16 02:00:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Disk source %1$s must be a character/block device"),
|
2014-03-17 20:49:05 +00:00
|
|
|
tmpsrc);
|
2013-07-16 02:00:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode = 0700;
|
|
|
|
if (S_ISCHR(sb.st_mode))
|
|
|
|
mode |= S_IFCHR;
|
|
|
|
else
|
|
|
|
mode |= S_IFBLK;
|
|
|
|
|
|
|
|
/* Yes, the device name we're creating may not
|
|
|
|
* actually correspond to the major:minor number
|
|
|
|
* we're using, but we've no other option at this
|
|
|
|
* time. Just have to hope that containerized apps
|
|
|
|
* don't get upset that the major:minor is different
|
|
|
|
* to that normally implied by the device name
|
|
|
|
*/
|
|
|
|
VIR_DEBUG("Creating dev %s (%d,%d) from %s",
|
2014-03-17 20:49:05 +00:00
|
|
|
dst, major(sb.st_rdev), minor(sb.st_rdev), tmpsrc);
|
2013-07-16 02:00:00 +00:00
|
|
|
if (mknod(dst, mode, sb.st_rdev) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to create device %1$s"),
|
2013-07-16 02:00:00 +00:00
|
|
|
dst);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-16 02:00:02 +00:00
|
|
|
if (lxcContainerChown(ctrl->def, dst) < 0)
|
2013-07-16 02:00:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-16 02:00:00 +00:00
|
|
|
/* Labelling normally operates on src, but we need
|
2013-09-26 21:40:34 +00:00
|
|
|
* to actually label the dst here, so hack the config */
|
2014-05-21 23:13:12 +00:00
|
|
|
def->src->path = dst;
|
2019-01-23 12:28:43 +00:00
|
|
|
if (virSecurityManagerSetImageLabel(securityDriver, ctrl->def, def->src,
|
|
|
|
VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN) < 0)
|
2013-07-16 02:00:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2014-05-21 23:13:12 +00:00
|
|
|
def->src->path = tmpsrc;
|
2013-07-16 02:00:00 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerSetupAllDisks(virLXCController *ctrl)
|
2013-07-16 02:00:00 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
VIR_DEBUG("Setting up disks");
|
|
|
|
|
|
|
|
for (i = 0; i < ctrl->def->ndisks; i++) {
|
|
|
|
if (virLXCControllerSetupDisk(ctrl, ctrl->def->disks[i],
|
|
|
|
ctrl->securityManager) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Setup all disks");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
/**
|
2012-07-03 11:06:38 +00:00
|
|
|
* virLXCControllerMoveInterfaces
|
2008-08-13 10:52:15 +00:00
|
|
|
* @nveths: number of interfaces
|
|
|
|
* @veths: interface names
|
|
|
|
* @container: pid of container
|
|
|
|
*
|
|
|
|
* Moves network interfaces into a container's namespace
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerMoveInterfaces(virLXCController *ctrl)
|
2008-08-13 10:52:15 +00:00
|
|
|
{
|
2012-07-03 11:06:38 +00:00
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDef *def = ctrl->def;
|
2012-07-03 11:06:38 +00:00
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nveths; i++) {
|
2012-07-03 11:12:59 +00:00
|
|
|
if (virNetDevSetNamespace(ctrl->veths[i], ctrl->initpid) < 0)
|
2008-08-13 10:52:15 +00:00
|
|
|
return -1;
|
2012-07-03 11:06:38 +00:00
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2013-04-05 12:26:40 +00:00
|
|
|
for (i = 0; i < def->nhostdevs; i ++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevDef *hdev = def->hostdevs[i];
|
2020-07-28 17:50:28 +00:00
|
|
|
virDomainHostdevCaps hdcaps;
|
2013-04-05 12:26:40 +00:00
|
|
|
|
|
|
|
if (hdev->mode != VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES)
|
|
|
|
continue;
|
|
|
|
|
2020-07-28 17:50:28 +00:00
|
|
|
hdcaps = hdev->source.caps;
|
2013-04-05 12:26:40 +00:00
|
|
|
|
|
|
|
if (hdcaps.type != VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET)
|
2015-05-12 12:40:34 +00:00
|
|
|
continue;
|
2013-04-05 12:26:40 +00:00
|
|
|
|
2016-06-06 19:44:15 +00:00
|
|
|
if (virNetDevSetNamespace(hdcaps.u.net.ifname, ctrl->initpid) < 0)
|
2013-04-05 12:26:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2012-07-03 11:06:38 +00:00
|
|
|
* virLXCControllerDeleteInterfaces:
|
|
|
|
* @ctrl: the LXC controller
|
2008-08-13 10:52:15 +00:00
|
|
|
*
|
|
|
|
* Cleans up the container interfaces by deleting the veth device pairs.
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virLXCControllerDeleteInterfaces(virLXCController *ctrl)
|
2008-08-13 10:52:15 +00:00
|
|
|
{
|
2012-07-03 11:06:38 +00:00
|
|
|
size_t i;
|
|
|
|
int ret = 0;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nveths; i++) {
|
2012-07-03 11:06:38 +00:00
|
|
|
if (virNetDevVethDelete(ctrl->veths[i]) < 0)
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2008-08-13 10:52:15 +00:00
|
|
|
}
|
|
|
|
|
2012-07-03 11:06:38 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int lxcSetPersonality(virDomainDef *def)
|
2011-02-23 17:17:53 +00:00
|
|
|
{
|
2012-12-10 22:28:09 +00:00
|
|
|
virArch altArch;
|
2011-02-23 17:17:53 +00:00
|
|
|
|
2015-01-16 17:20:48 +00:00
|
|
|
VIR_DEBUG("Checking for 32-bit personality");
|
2012-12-10 22:28:09 +00:00
|
|
|
altArch = lxcContainerGetAlt32bitArch(virArchFromHost());
|
2011-02-23 17:17:53 +00:00
|
|
|
if (altArch &&
|
2012-12-10 22:28:09 +00:00
|
|
|
(def->os.arch == altArch)) {
|
2015-01-16 17:20:48 +00:00
|
|
|
VIR_DEBUG("Setting personality to %s",
|
|
|
|
virArchToString(altArch));
|
2011-02-23 17:17:53 +00:00
|
|
|
if (personality(PER_LINUX32) < 0) {
|
2023-03-09 11:22:28 +00:00
|
|
|
virReportSystemError(errno, _("Unable to request personality for %1$s on %2$s"),
|
2012-12-10 22:28:09 +00:00
|
|
|
virArchToString(altArch),
|
|
|
|
virArchToString(virArchFromHost()));
|
2011-02-23 17:17:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-10-19 01:39:57 +00:00
|
|
|
/* Create a private tty using the private devpts at PTMX, returning
|
2020-06-17 10:56:58 +00:00
|
|
|
* the primary in @ttyprimary and the name of the secondary, _from the
|
2011-10-19 01:39:57 +00:00
|
|
|
* perspective of the guest after remounting file systems_, in
|
2020-06-17 10:56:58 +00:00
|
|
|
* @ttyName. Heavily borrowed from glibc, but doesn't require that
|
2011-10-19 01:39:57 +00:00
|
|
|
* devpts == "/dev/pts" */
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
lxcCreateTty(virLXCController *ctrl, int *ttyprimary,
|
2013-06-07 07:12:23 +00:00
|
|
|
char **ttyName, char **ttyHostPath)
|
2011-10-19 01:39:57 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int ptyno;
|
|
|
|
int unlock = 0;
|
|
|
|
|
2020-06-17 10:56:58 +00:00
|
|
|
if ((*ttyprimary = open(ctrl->devptmx, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
|
2011-10-19 01:39:57 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-06-17 10:56:58 +00:00
|
|
|
if (ioctl(*ttyprimary, TIOCSPTLCK, &unlock) < 0)
|
2011-10-19 01:39:57 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-06-17 10:56:58 +00:00
|
|
|
if (ioctl(*ttyprimary, TIOCGPTN, &ptyno) < 0)
|
2011-10-19 01:39:57 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* If mount() succeeded at honoring newinstance, then the kernel
|
|
|
|
* was new enough to also honor the mode=0620,gid=5 options, which
|
|
|
|
* guarantee that the new pty already has correct permissions; so
|
|
|
|
* while glibc has to fstat(), fchmod(), and fchown() for older
|
|
|
|
* kernels, we can skip those steps. ptyno shouldn't currently be
|
|
|
|
* anything other than 0, but let's play it safe. */
|
2019-10-22 13:26:14 +00:00
|
|
|
*ttyName = g_strdup_printf("/dev/pts/%d", ptyno);
|
|
|
|
*ttyHostPath = g_strdup_printf("/%s/%s.devpts/%d", LXC_STATE_DIR, ctrl->def->name, ptyno);
|
2011-10-19 01:39:57 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2011-10-19 01:39:57 +00:00
|
|
|
if (ret != 0) {
|
2020-06-17 10:56:58 +00:00
|
|
|
VIR_FORCE_CLOSE(*ttyprimary);
|
2022-01-28 17:42:45 +00:00
|
|
|
g_clear_pointer(ttyName, g_free);
|
2011-10-19 01:39:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
|
2013-01-07 18:14:34 +00:00
|
|
|
static int
|
|
|
|
virLXCControllerSetupPrivateNS(void)
|
|
|
|
{
|
2013-05-20 10:12:19 +00:00
|
|
|
/*
|
|
|
|
* If doing a chroot style setup, we need to prepare
|
|
|
|
* a private /dev/pts for the child now, which they
|
|
|
|
* will later move into position.
|
|
|
|
*
|
|
|
|
* This is complex because 'virsh console' needs to
|
|
|
|
* use /dev/pts from the host OS, and the guest OS
|
|
|
|
* needs to use /dev/pts from the guest.
|
|
|
|
*
|
|
|
|
* This means that we (libvirt_lxc) need to see and
|
|
|
|
* use both /dev/pts instances. We're running in the
|
|
|
|
* host OS context though and don't want to expose
|
|
|
|
* the guest OS /dev/pts there.
|
|
|
|
*
|
|
|
|
* Thus we call unshare(CLONE_NS) so that we can see
|
|
|
|
* the guest's new /dev/pts, without it becoming
|
2020-06-17 10:57:31 +00:00
|
|
|
* visible to the host OS. We also disable mount
|
|
|
|
* propagation out of the root FS, in case it was
|
|
|
|
* currently allowing bi-directional propagation.
|
2013-05-20 10:12:19 +00:00
|
|
|
*/
|
|
|
|
|
2016-11-10 13:55:48 +00:00
|
|
|
return virProcessSetupPrivateMountNS();
|
2013-01-07 18:14:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupDevPTS(virLXCController *ctrl)
|
2008-08-13 10:52:15 +00:00
|
|
|
{
|
2020-02-24 14:24:27 +00:00
|
|
|
g_autofree char *mount_options = NULL;
|
|
|
|
g_autofree char *opts = NULL;
|
|
|
|
g_autofree char *devpts = NULL;
|
2014-07-28 20:59:17 +00:00
|
|
|
gid_t ptsgid = 5;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
VIR_DEBUG("Setting up private /dev/pts");
|
2010-03-04 11:15:42 +00:00
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
mount_options = virSecurityManagerGetMountOptions(ctrl->securityManager,
|
|
|
|
ctrl->def);
|
2011-06-02 18:25:25 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
devpts = g_strdup_printf("%s/%s.devpts", LXC_STATE_DIR, ctrl->def->name);
|
|
|
|
ctrl->devptmx = g_strdup_printf("%s/%s.devpts/ptmx", LXC_STATE_DIR, ctrl->def->name);
|
2009-04-22 14:26:50 +00:00
|
|
|
|
2021-02-26 08:37:10 +00:00
|
|
|
if (g_mkdir_with_parents(devpts, 0777) < 0) {
|
2012-07-03 13:02:33 +00:00
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failed to make path %1$s"),
|
2012-07-03 13:02:33 +00:00
|
|
|
devpts);
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2012-07-03 13:02:33 +00:00
|
|
|
}
|
2009-04-22 14:26:50 +00:00
|
|
|
|
2014-07-28 20:59:17 +00:00
|
|
|
if (ctrl->def->idmap.ngidmap)
|
|
|
|
ptsgid = virLXCControllerLookupUsernsMap(ctrl->def->idmap.gidmap,
|
|
|
|
ctrl->def->idmap.ngidmap,
|
|
|
|
ptsgid);
|
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
/* XXX should we support gid=X for X!=5 for distros which use
|
|
|
|
* a different gid for tty? */
|
2019-10-22 13:26:14 +00:00
|
|
|
opts = g_strdup_printf("newinstance,ptmxmode=0666,mode=0620,gid=%u%s", ptsgid,
|
|
|
|
NULLSTR_EMPTY(mount_options));
|
2012-01-25 14:12:54 +00:00
|
|
|
|
2017-09-25 10:43:33 +00:00
|
|
|
VIR_DEBUG("Mount devpts on %s type=tmpfs flags=0x%x, opts=%s",
|
2012-07-03 13:02:33 +00:00
|
|
|
devpts, MS_NOSUID, opts);
|
|
|
|
if (mount("devpts", devpts, "devpts", MS_NOSUID, opts) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failed to mount devpts on %1$s"),
|
2012-07-03 13:02:33 +00:00
|
|
|
devpts);
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2012-07-03 13:02:33 +00:00
|
|
|
}
|
2009-04-22 14:26:50 +00:00
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
if (access(ctrl->devptmx, R_OK) < 0) {
|
2013-03-28 17:30:25 +00:00
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Kernel does not support private devpts"));
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2009-04-22 14:26:50 +00:00
|
|
|
}
|
|
|
|
|
2013-07-16 02:00:02 +00:00
|
|
|
if ((lxcContainerChown(ctrl->def, ctrl->devptmx) < 0) ||
|
|
|
|
(lxcContainerChown(ctrl->def, devpts) < 0))
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2012-07-03 13:02:33 +00:00
|
|
|
|
2020-02-24 14:24:27 +00:00
|
|
|
return 0;
|
2012-07-03 13:02:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-14 09:39:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupFuse(virLXCController *ctrl)
|
2012-11-14 09:39:04 +00:00
|
|
|
{
|
|
|
|
return lxcSetupFuse(&ctrl->fuse, ctrl->def);
|
|
|
|
}
|
|
|
|
|
2013-11-15 16:15:59 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerStartFuse(virLXCController *ctrl)
|
2013-11-15 16:15:59 +00:00
|
|
|
{
|
|
|
|
return lxcStartFuse(ctrl->fuse);
|
|
|
|
}
|
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerSetupConsoles(virLXCController *ctrl,
|
2012-07-03 13:02:33 +00:00
|
|
|
char **containerTTYPaths)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nconsoles; i++) {
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree char *ttyHostPath = NULL;
|
|
|
|
|
2013-03-28 17:30:25 +00:00
|
|
|
VIR_DEBUG("Opening tty on private %s", ctrl->devptmx);
|
2013-06-07 07:12:23 +00:00
|
|
|
if (lxcCreateTty(ctrl,
|
2013-03-28 17:30:25 +00:00
|
|
|
&ctrl->consoles[i].contFd,
|
2013-06-07 07:12:23 +00:00
|
|
|
&containerTTYPaths[i], &ttyHostPath) < 0) {
|
2013-03-28 17:30:25 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
2015-05-12 12:40:34 +00:00
|
|
|
_("Failed to allocate tty"));
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2011-10-20 08:44:31 +00:00
|
|
|
}
|
2013-06-07 07:12:23 +00:00
|
|
|
|
|
|
|
/* Change the owner of tty device to the root user of container */
|
2013-07-16 02:00:02 +00:00
|
|
|
if (lxcContainerChown(ctrl->def, ttyHostPath) < 0)
|
2020-02-24 14:24:27 +00:00
|
|
|
return -1;
|
2011-10-20 08:44:31 +00:00
|
|
|
}
|
2013-06-07 07:12:23 +00:00
|
|
|
|
2020-02-24 14:24:27 +00:00
|
|
|
return 0;
|
2012-07-03 13:02:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerEventSend(virLXCController *ctrl,
|
2012-07-17 14:54:08 +00:00
|
|
|
int procnr,
|
|
|
|
xdrproc_t proc,
|
|
|
|
void *data)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virNetMessage *msg;
|
2012-07-17 14:54:08 +00:00
|
|
|
|
2012-11-20 17:49:25 +00:00
|
|
|
if (!ctrl->client) {
|
2013-09-27 05:43:24 +00:00
|
|
|
VIR_WARN("Dropping event %d because libvirtd is not connected", procnr);
|
2012-07-17 14:54:08 +00:00
|
|
|
return;
|
2012-11-20 17:49:25 +00:00
|
|
|
}
|
2012-07-17 14:54:08 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Send event %d client=%p", procnr, ctrl->client);
|
|
|
|
if (!(msg = virNetMessageNew(false)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
msg->header.prog = virNetServerProgramGetID(ctrl->prog);
|
|
|
|
msg->header.vers = virNetServerProgramGetVersion(ctrl->prog);
|
|
|
|
msg->header.proc = procnr;
|
|
|
|
msg->header.type = VIR_NET_MESSAGE;
|
|
|
|
msg->header.serial = 1;
|
|
|
|
msg->header.status = VIR_NET_OK;
|
|
|
|
|
|
|
|
if (virNetMessageEncodeHeader(msg) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virNetMessageEncodePayload(msg, proc, data) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
VIR_DEBUG("Queue event %d %zu", procnr, msg->bufferLength);
|
2018-02-26 11:13:50 +00:00
|
|
|
if (virNetServerClientSendMessage(ctrl->client, msg) < 0)
|
|
|
|
goto error;
|
2012-07-17 14:54:08 +00:00
|
|
|
|
|
|
|
xdr_free(proc, data);
|
|
|
|
return;
|
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
error:
|
2012-07-17 14:54:08 +00:00
|
|
|
virNetMessageFree(msg);
|
|
|
|
xdr_free(proc, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerEventSendExit(virLXCController *ctrl,
|
2012-07-17 14:54:08 +00:00
|
|
|
int exitstatus)
|
|
|
|
{
|
2023-08-02 08:09:52 +00:00
|
|
|
virLXCMonitorExitEventMsg msg = { 0 };
|
2012-07-17 14:54:08 +00:00
|
|
|
|
2012-11-22 16:45:39 +00:00
|
|
|
VIR_DEBUG("Exit status %d (client=%p)", exitstatus, ctrl->client);
|
2012-07-17 14:54:08 +00:00
|
|
|
switch (exitstatus) {
|
|
|
|
case 0:
|
2013-03-13 19:19:22 +00:00
|
|
|
msg.status = VIR_LXC_MONITOR_EXIT_STATUS_SHUTDOWN;
|
2012-07-17 14:54:08 +00:00
|
|
|
break;
|
2012-07-23 11:25:37 +00:00
|
|
|
case 1:
|
2013-03-13 19:19:22 +00:00
|
|
|
msg.status = VIR_LXC_MONITOR_EXIT_STATUS_REBOOT;
|
2012-07-23 11:25:37 +00:00
|
|
|
break;
|
2012-07-17 14:54:08 +00:00
|
|
|
default:
|
2013-03-13 19:19:22 +00:00
|
|
|
msg.status = VIR_LXC_MONITOR_EXIT_STATUS_ERROR;
|
2012-07-17 14:54:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
virLXCControllerEventSend(ctrl,
|
2013-03-13 19:19:22 +00:00
|
|
|
VIR_LXC_MONITOR_PROC_EXIT_EVENT,
|
|
|
|
(xdrproc_t)xdr_virLXCMonitorExitEventMsg,
|
2012-07-17 14:54:08 +00:00
|
|
|
(void*)&msg);
|
|
|
|
|
|
|
|
if (ctrl->client) {
|
|
|
|
VIR_DEBUG("Waiting for client to complete dispatch");
|
|
|
|
ctrl->inShutdown = true;
|
|
|
|
virNetServerClientDelayedClose(ctrl->client);
|
2021-12-02 18:56:07 +00:00
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Arm timer to quit event loop");
|
|
|
|
virEventUpdateTimeout(ctrl->timerShutdown, 0);
|
2012-07-17 14:54:08 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-20 17:49:25 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerEventSendInit(virLXCController *ctrl,
|
2012-11-20 17:49:25 +00:00
|
|
|
pid_t initpid)
|
|
|
|
{
|
2023-08-02 08:09:52 +00:00
|
|
|
virLXCMonitorInitEventMsg msg = { 0 };
|
2012-11-20 17:49:25 +00:00
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
VIR_DEBUG("Init pid %lld", (long long)initpid);
|
2012-11-20 17:49:25 +00:00
|
|
|
msg.initpid = initpid;
|
|
|
|
|
|
|
|
virLXCControllerEventSend(ctrl,
|
2013-03-13 19:19:22 +00:00
|
|
|
VIR_LXC_MONITOR_PROC_INIT_EVENT,
|
|
|
|
(xdrproc_t)xdr_virLXCMonitorInitEventMsg,
|
2012-11-20 17:49:25 +00:00
|
|
|
(void*)&msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCControllerRun(virLXCController *ctrl)
|
2012-07-03 13:02:33 +00:00
|
|
|
{
|
|
|
|
int rc = -1;
|
|
|
|
int control[2] = { -1, -1};
|
|
|
|
int containerhandshake[2] = { -1, -1 };
|
2020-05-12 17:31:16 +00:00
|
|
|
char **containerTTYPaths = g_new0(char *, ctrl->nconsoles);
|
2012-07-03 13:02:33 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (socketpair(PF_UNIX, SOCK_STREAM, 0, control) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("sockpair failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (socketpair(PF_UNIX, SOCK_STREAM, 0, containerhandshake) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("socketpair failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-01-07 18:14:34 +00:00
|
|
|
if (virLXCControllerSetupPrivateNS() < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
if (virLXCControllerSetupLoopDevices(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-22 15:36:06 +00:00
|
|
|
if (virLXCControllerSetupResourceLimits(ctrl) < 0)
|
2012-07-03 13:02:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virLXCControllerSetupDevPTS(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-06-07 07:12:22 +00:00
|
|
|
if (virLXCControllerPopulateDevices(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-03-02 00:54:12 +00:00
|
|
|
if (virLXCControllerSetupTimers(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-16 02:00:00 +00:00
|
|
|
if (virLXCControllerSetupAllDisks(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-16 02:00:04 +00:00
|
|
|
if (virLXCControllerSetupAllHostdevs(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-14 09:39:04 +00:00
|
|
|
if (virLXCControllerSetupFuse(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-03 13:02:33 +00:00
|
|
|
if (virLXCControllerSetupConsoles(ctrl, containerTTYPaths) < 0)
|
|
|
|
goto cleanup;
|
2011-10-20 08:44:31 +00:00
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
if (lxcSetPersonality(ctrl->def) < 0)
|
2011-02-23 17:17:53 +00:00
|
|
|
goto cleanup;
|
2009-04-22 14:26:50 +00:00
|
|
|
|
2012-07-03 11:12:59 +00:00
|
|
|
if ((ctrl->initpid = lxcContainerStart(ctrl->def,
|
2012-07-03 12:59:36 +00:00
|
|
|
ctrl->securityManager,
|
2012-07-03 11:12:59 +00:00
|
|
|
ctrl->nveths,
|
|
|
|
ctrl->veths,
|
2013-07-09 17:15:45 +00:00
|
|
|
ctrl->npassFDs,
|
|
|
|
ctrl->passFDs,
|
2012-07-03 11:12:59 +00:00
|
|
|
control[1],
|
|
|
|
containerhandshake[1],
|
2015-08-20 13:46:17 +00:00
|
|
|
ctrl->nsFDs,
|
2013-07-09 17:15:45 +00:00
|
|
|
ctrl->nconsoles,
|
|
|
|
containerTTYPaths)) < 0)
|
2008-08-13 10:52:15 +00:00
|
|
|
goto cleanup;
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(control[1]);
|
2011-06-02 15:52:32 +00:00
|
|
|
VIR_FORCE_CLOSE(containerhandshake[1]);
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2013-07-09 17:15:45 +00:00
|
|
|
for (i = 0; i < ctrl->npassFDs; i++)
|
|
|
|
VIR_FORCE_CLOSE(ctrl->passFDs[i]);
|
|
|
|
|
2015-08-20 13:46:17 +00:00
|
|
|
if (ctrl->nsFDs)
|
|
|
|
for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
|
|
|
|
VIR_FORCE_CLOSE(ctrl->nsFDs[i]);
|
|
|
|
|
2015-01-16 16:23:45 +00:00
|
|
|
if (virLXCControllerSetupCgroupLimits(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-04-20 08:33:03 +00:00
|
|
|
/* Allow daemon to detect CGroups. */
|
|
|
|
if (virLXCControllerDaemonHandshakeCont(ctrl) < 0 ||
|
|
|
|
virLXCControllerDaemonHandshakeWait(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-06-07 07:12:21 +00:00
|
|
|
if (virLXCControllerSetupUserns(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-03 11:12:59 +00:00
|
|
|
if (virLXCControllerMoveInterfaces(ctrl) < 0)
|
2008-08-13 10:52:15 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-11-15 16:15:59 +00:00
|
|
|
if (virLXCControllerStartFuse(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-06-02 15:18:14 +00:00
|
|
|
if (lxcContainerSendContinue(control[0]) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to send container continue message"));
|
2008-08-13 10:52:15 +00:00
|
|
|
goto cleanup;
|
2011-06-02 15:18:14 +00:00
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2011-06-02 15:52:32 +00:00
|
|
|
if (lxcContainerWaitForContinue(containerhandshake[0]) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("error receiving signal from container"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-08-04 09:13:02 +00:00
|
|
|
/* ...and reduce our privileges */
|
2009-06-29 17:09:42 +00:00
|
|
|
if (lxcControllerClearCapabilities() < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nconsoles; i++)
|
2012-07-03 11:42:53 +00:00
|
|
|
if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < 0)
|
2011-10-20 08:44:31 +00:00
|
|
|
goto cleanup;
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2021-04-20 08:33:03 +00:00
|
|
|
/* Allow daemon to connect to the monitor. */
|
|
|
|
if (virLXCControllerDaemonHandshakeCont(ctrl) < 0)
|
2016-07-19 14:23:25 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2021-04-20 11:28:20 +00:00
|
|
|
/* and preemptively close handshakeFds */
|
|
|
|
for (i = 0; i < G_N_ELEMENTS(ctrl->handshakeFds); i++)
|
|
|
|
VIR_FORCE_CLOSE(ctrl->handshakeFds[i]);
|
2021-04-20 11:34:55 +00:00
|
|
|
|
2013-10-11 14:57:31 +00:00
|
|
|
/* We must not hold open a dbus connection for life
|
|
|
|
* of LXC instance, since dbus-daemon is limited to
|
|
|
|
* only a few 100 connections by default
|
|
|
|
*/
|
2020-09-09 14:43:12 +00:00
|
|
|
virGDBusCloseSystemBus();
|
2013-10-11 14:57:31 +00:00
|
|
|
|
2012-07-03 13:40:45 +00:00
|
|
|
rc = virLXCControllerMain(ctrl);
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(control[0]);
|
|
|
|
VIR_FORCE_CLOSE(control[1]);
|
2011-06-02 15:52:32 +00:00
|
|
|
VIR_FORCE_CLOSE(containerhandshake[0]);
|
|
|
|
VIR_FORCE_CLOSE(containerhandshake[1]);
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < ctrl->nconsoles; i++)
|
2020-05-12 16:53:07 +00:00
|
|
|
g_free(containerTTYPaths[i]);
|
|
|
|
g_free(containerTTYPaths);
|
2011-10-27 07:18:00 +00:00
|
|
|
|
2012-07-03 11:12:59 +00:00
|
|
|
virLXCControllerStopInit(ctrl);
|
2011-10-21 17:09:23 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-20 11:28:20 +00:00
|
|
|
static int
|
|
|
|
parseFDPair(const char *arg,
|
|
|
|
int (*fd)[2])
|
|
|
|
{
|
|
|
|
g_auto(GStrv) fds = NULL;
|
|
|
|
|
|
|
|
fds = g_strsplit(arg, ":", 0);
|
|
|
|
|
|
|
|
if (fds[0] == NULL || fds[1] == NULL || fds[2] != NULL ||
|
|
|
|
virStrToLong_i(fds[0], NULL, 10, &(*fd)[0]) < 0 ||
|
|
|
|
virStrToLong_i(fds[1], NULL, 10, &(*fd)[1]) < 0) {
|
|
|
|
fprintf(stderr, "malformed --handshakefds argument '%s'",
|
|
|
|
optarg);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
int main(int argc, char *argv[])
|
2008-08-13 10:52:15 +00:00
|
|
|
{
|
|
|
|
pid_t pid;
|
2013-10-11 16:28:31 +00:00
|
|
|
int rc = -1;
|
2014-01-07 14:42:44 +00:00
|
|
|
const char *name = NULL;
|
2012-07-03 11:06:38 +00:00
|
|
|
size_t nveths = 0;
|
2008-08-20 20:55:32 +00:00
|
|
|
char **veths = NULL;
|
2015-08-20 13:46:17 +00:00
|
|
|
int ns_fd[VIR_LXC_DOMAIN_NAMESPACE_LAST];
|
2021-04-20 11:28:20 +00:00
|
|
|
int handshakeFds[2] = { -1, -1 };
|
2013-05-24 10:14:02 +00:00
|
|
|
bool bg = false;
|
2009-02-03 13:08:59 +00:00
|
|
|
const struct option options[] = {
|
2008-08-20 20:55:32 +00:00
|
|
|
{ "background", 0, NULL, 'b' },
|
|
|
|
{ "name", 1, NULL, 'n' },
|
|
|
|
{ "veth", 1, NULL, 'v' },
|
|
|
|
{ "console", 1, NULL, 'c' },
|
2013-07-09 17:15:45 +00:00
|
|
|
{ "passfd", 1, NULL, 'p' },
|
2021-04-20 11:28:20 +00:00
|
|
|
{ "handshakefds", 1, NULL, 's' },
|
2012-01-25 14:12:53 +00:00
|
|
|
{ "security", 1, NULL, 'S' },
|
2015-08-20 13:46:17 +00:00
|
|
|
{ "share-net", 1, NULL, 'N' },
|
|
|
|
{ "share-ipc", 1, NULL, 'I' },
|
|
|
|
{ "share-uts", 1, NULL, 'U' },
|
2008-08-20 20:55:32 +00:00
|
|
|
{ "help", 0, NULL, 'h' },
|
|
|
|
{ 0, 0, 0, 0 },
|
|
|
|
};
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree int *ttyFDs = NULL;
|
2011-10-20 08:44:31 +00:00
|
|
|
size_t nttyFDs = 0;
|
2020-05-12 16:53:07 +00:00
|
|
|
g_autofree int *passFDs = NULL;
|
2013-07-09 17:15:45 +00:00
|
|
|
size_t npassFDs = 0;
|
2021-03-11 07:16:13 +00:00
|
|
|
virLXCController *ctrl = NULL;
|
2012-07-03 11:42:53 +00:00
|
|
|
size_t i;
|
2012-07-03 12:59:36 +00:00
|
|
|
const char *securityDriver = "none";
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2015-08-20 13:46:17 +00:00
|
|
|
for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
|
|
|
|
ns_fd[i] = -1;
|
|
|
|
|
2016-04-12 22:29:52 +00:00
|
|
|
if (virGettextInitialize() < 0 ||
|
2013-10-08 13:35:01 +00:00
|
|
|
virErrorInitialize() < 0) {
|
2023-03-09 11:22:28 +00:00
|
|
|
fprintf(stderr, _("%1$s: initialization failed\n"), argv[0]);
|
2010-11-16 19:01:37 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2012-05-01 09:47:53 +00:00
|
|
|
/* Initialize logging */
|
2021-12-15 15:34:16 +00:00
|
|
|
if (virLogSetFromEnv() < 0)
|
|
|
|
exit(EXIT_FAILURE);
|
2012-05-01 09:47:53 +00:00
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
while (1) {
|
|
|
|
int c;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2015-08-20 13:46:17 +00:00
|
|
|
c = getopt_long(argc, argv, "dn:v:p:m:c:s:h:S:N:I:U:",
|
2015-05-12 12:40:34 +00:00
|
|
|
options, NULL);
|
2008-08-20 20:55:32 +00:00
|
|
|
|
|
|
|
if (c == -1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'b':
|
2013-05-24 10:14:02 +00:00
|
|
|
bg = true;
|
2008-08-20 20:55:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
2014-01-07 14:42:44 +00:00
|
|
|
name = optarg;
|
2008-08-20 20:55:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v':
|
2020-05-12 17:31:16 +00:00
|
|
|
veths = g_renew(char *, veths, nveths+1);
|
2019-10-20 11:49:46 +00:00
|
|
|
veths[nveths++] = g_strdup(optarg);
|
2008-08-20 20:55:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'c':
|
2020-05-12 17:31:16 +00:00
|
|
|
ttyFDs = g_renew(int, ttyFDs, nttyFDs + 1);
|
2011-10-20 08:44:31 +00:00
|
|
|
if (virStrToLong_i(optarg, NULL, 10, &ttyFDs[nttyFDs++]) < 0) {
|
2008-08-20 20:55:32 +00:00
|
|
|
fprintf(stderr, "malformed --console argument '%s'", optarg);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2013-07-09 17:15:45 +00:00
|
|
|
case 'p':
|
2020-05-12 17:31:16 +00:00
|
|
|
passFDs = g_renew(int, passFDs, npassFDs + 1);
|
2013-07-09 17:15:45 +00:00
|
|
|
if (virStrToLong_i(optarg, NULL, 10, &passFDs[npassFDs++]) < 0) {
|
|
|
|
fprintf(stderr, "malformed --passfd argument '%s'", optarg);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-06-01 22:17:00 +00:00
|
|
|
case 's':
|
2021-04-20 11:28:20 +00:00
|
|
|
if (parseFDPair(optarg, &handshakeFds) < 0)
|
2011-06-01 22:17:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
|
2015-08-20 13:46:17 +00:00
|
|
|
case 'N':
|
|
|
|
if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHARENET]) < 0) {
|
|
|
|
fprintf(stderr, "malformed --share-net argument '%s'",
|
|
|
|
optarg);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'I':
|
|
|
|
if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC]) < 0) {
|
|
|
|
fprintf(stderr, "malformed --share-ipc argument '%s'",
|
|
|
|
optarg);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'U':
|
|
|
|
if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS]) < 0) {
|
|
|
|
fprintf(stderr, "malformed --share-uts argument '%s'",
|
|
|
|
optarg);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-01-25 14:12:53 +00:00
|
|
|
case 'S':
|
2012-07-03 12:59:36 +00:00
|
|
|
securityDriver = optarg;
|
2012-01-25 14:12:53 +00:00
|
|
|
break;
|
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
case 'h':
|
|
|
|
case '?':
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
fprintf(stderr, "syntax: %s [OPTIONS]\n", argv[0]);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
fprintf(stderr, "Options\n");
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
fprintf(stderr, " -b, --background\n");
|
|
|
|
fprintf(stderr, " -n NAME, --name NAME\n");
|
|
|
|
fprintf(stderr, " -c FD, --console FD\n");
|
|
|
|
fprintf(stderr, " -v VETH, --veth VETH\n");
|
2021-04-20 11:28:20 +00:00
|
|
|
fprintf(stderr, " -s FD:FD, --handshakefds FD:FD (read:write)\n");
|
2012-01-25 14:12:53 +00:00
|
|
|
fprintf(stderr, " -S NAME, --security NAME\n");
|
2015-08-20 13:46:17 +00:00
|
|
|
fprintf(stderr, " -N FD, --share-net FD\n");
|
|
|
|
fprintf(stderr, " -I FD, --share-ipc FD\n");
|
|
|
|
fprintf(stderr, " -U FD, --share-uts FD\n");
|
2008-08-20 20:55:32 +00:00
|
|
|
fprintf(stderr, " -h, --help\n");
|
|
|
|
fprintf(stderr, "\n");
|
2015-08-27 00:21:54 +00:00
|
|
|
rc = 0;
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
if (name == NULL) {
|
|
|
|
fprintf(stderr, "%s: missing --name argument for configuration\n", argv[0]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2021-04-20 11:28:20 +00:00
|
|
|
if (handshakeFds[0] < 0 || handshakeFds[1] < 0) {
|
|
|
|
fprintf(stderr, "%s: missing --handshakefds argument for container PTY\n",
|
2011-06-01 22:17:00 +00:00
|
|
|
argv[0]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-10-09 11:13:45 +00:00
|
|
|
if (geteuid() != 0) {
|
2008-08-20 20:55:32 +00:00
|
|
|
fprintf(stderr, "%s: must be run as the 'root' user\n", argv[0]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2011-10-19 15:22:24 +00:00
|
|
|
virEventRegisterDefaultImpl();
|
2013-10-11 14:57:31 +00:00
|
|
|
|
2020-09-09 14:43:12 +00:00
|
|
|
virGDBusSetSharedBus(false);
|
2011-10-19 15:22:24 +00:00
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
if (!(ctrl = virLXCControllerNew(name)))
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2021-04-20 11:28:20 +00:00
|
|
|
memcpy(&ctrl->handshakeFds, &handshakeFds, sizeof(handshakeFds));
|
2012-07-03 12:16:48 +00:00
|
|
|
|
2012-07-03 12:59:36 +00:00
|
|
|
if (!(ctrl->securityManager = virSecurityManagerNew(securityDriver,
|
2018-10-02 13:08:28 +00:00
|
|
|
LXC_DRIVER_NAME, 0)))
|
2012-07-03 12:59:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-26 14:17:58 +00:00
|
|
|
if (ctrl->def->seclabels) {
|
|
|
|
VIR_DEBUG("Security model %s type %s label %s imagelabel %s",
|
|
|
|
NULLSTR(ctrl->def->seclabels[0]->model),
|
|
|
|
virDomainSeclabelTypeToString(ctrl->def->seclabels[0]->type),
|
|
|
|
NULLSTR(ctrl->def->seclabels[0]->label),
|
|
|
|
NULLSTR(ctrl->def->seclabels[0]->imagelabel));
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Security model not initialized");
|
|
|
|
}
|
2012-05-01 09:47:53 +00:00
|
|
|
|
2012-07-03 11:06:38 +00:00
|
|
|
ctrl->veths = veths;
|
|
|
|
ctrl->nveths = nveths;
|
|
|
|
|
2013-07-09 17:15:45 +00:00
|
|
|
ctrl->passFDs = passFDs;
|
|
|
|
ctrl->npassFDs = npassFDs;
|
|
|
|
|
2015-08-20 13:46:17 +00:00
|
|
|
for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) {
|
|
|
|
if (ns_fd[i] != -1) {
|
|
|
|
if (!ctrl->nsFDs) {/*allocate only once */
|
|
|
|
size_t j = 0;
|
2020-05-12 17:31:16 +00:00
|
|
|
ctrl->nsFDs = g_new0(int, VIR_LXC_DOMAIN_NAMESPACE_LAST);
|
2015-08-20 13:46:17 +00:00
|
|
|
for (j = 0; j < VIR_LXC_DOMAIN_NAMESPACE_LAST; j++)
|
|
|
|
ctrl->nsFDs[j] = -1;
|
|
|
|
}
|
|
|
|
ctrl->nsFDs[i] = ns_fd[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < nttyFDs; i++) {
|
2012-07-03 11:42:53 +00:00
|
|
|
if (virLXCControllerAddConsole(ctrl, ttyFDs[i]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
ttyFDs[i] = -1;
|
|
|
|
}
|
|
|
|
|
2012-07-03 11:06:38 +00:00
|
|
|
if (virLXCControllerValidateNICs(ctrl) < 0)
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2015-01-16 16:58:39 +00:00
|
|
|
if (virLXCControllerGetNICIndexes(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-03 11:42:53 +00:00
|
|
|
if (virLXCControllerValidateConsoles(ctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-03 14:25:30 +00:00
|
|
|
if (virLXCControllerSetupServer(ctrl) < 0)
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
if (bg) {
|
|
|
|
if ((pid = fork()) < 0)
|
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
if (pid > 0) {
|
2011-08-05 13:13:12 +00:00
|
|
|
if ((rc = virPidFileWrite(LXC_STATE_DIR, name, pid)) < 0) {
|
2011-07-25 18:11:38 +00:00
|
|
|
virReportSystemError(-rc,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Unable to write pid file '%1$s/%2$s.pid'"),
|
2009-01-20 17:13:33 +00:00
|
|
|
LXC_STATE_DIR, name);
|
2008-08-20 20:55:32 +00:00
|
|
|
_exit(1);
|
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
/* First child now exits, allowing original caller
|
|
|
|
* (ie libvirtd's LXC driver to complete their
|
|
|
|
* waitpid & continue */
|
|
|
|
_exit(0);
|
2008-08-13 10:52:15 +00:00
|
|
|
}
|
|
|
|
|
2013-04-19 20:18:14 +00:00
|
|
|
/* Don't hold on to any cwd we inherit from libvirtd either */
|
2008-08-20 20:55:32 +00:00
|
|
|
if (chdir("/") < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Unable to change to root dir"));
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setsid() < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Unable to become session leader"));
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2012-07-03 13:40:45 +00:00
|
|
|
rc = virLXCControllerRun(ctrl);
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2014-03-25 06:49:26 +00:00
|
|
|
cleanup:
|
2013-03-04 20:47:37 +00:00
|
|
|
if (rc < 0) {
|
2016-05-19 19:10:19 +00:00
|
|
|
fprintf(stderr,
|
2023-03-09 11:22:28 +00:00
|
|
|
_("Failure in libvirt_lxc startup: %1$s\n"),
|
2016-05-19 19:10:19 +00:00
|
|
|
virGetLastErrorMessage());
|
2013-03-04 20:47:37 +00:00
|
|
|
}
|
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
virPidFileDelete(LXC_STATE_DIR, name);
|
2012-11-26 11:13:56 +00:00
|
|
|
if (ctrl)
|
|
|
|
virLXCControllerDeleteInterfaces(ctrl);
|
2013-05-21 08:03:33 +00:00
|
|
|
for (i = 0; i < nttyFDs; i++)
|
2012-07-03 11:42:53 +00:00
|
|
|
VIR_FORCE_CLOSE(ttyFDs[i]);
|
2013-07-09 17:15:45 +00:00
|
|
|
for (i = 0; i < npassFDs; i++)
|
|
|
|
VIR_FORCE_CLOSE(passFDs[i]);
|
2012-07-03 11:42:53 +00:00
|
|
|
|
2012-07-03 10:54:09 +00:00
|
|
|
virLXCControllerFree(ctrl);
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2012-07-17 14:54:08 +00:00
|
|
|
return rc < 0? EXIT_FAILURE : EXIT_SUCCESS;
|
2008-08-20 20:55:32 +00:00
|
|
|
}
|