uml: convert to virCommand

* src/uml/uml_conf.c (umlBuildCommandLineChr)
(umlBuildCommandLine): Rewrite with virCommand.
* src/uml/uml_conf.h (umlBuildCommandLine): Update signature.
* src/uml/uml_driver.c (umlStartVMDaemon): Adjust caller.
This commit is contained in:
Daniel P. Berrange 2010-05-25 14:17:48 +01:00 committed by Eric Blake
parent 6a7e7c4f62
commit 98c379b3c5
3 changed files with 46 additions and 191 deletions

View File

@ -48,6 +48,7 @@
#include "logging.h"
#include "domain_nwfilter.h"
#include "files.h"
#include "command.h"
#define VIR_FROM_THIS VIR_FROM_UML
@ -307,7 +308,7 @@ error:
static char *
umlBuildCommandLineChr(virDomainChrDefPtr def,
const char *dev,
fd_set *keepfd)
virCommandPtr cmd)
{
char *ret = NULL;
@ -371,7 +372,7 @@ umlBuildCommandLineChr(virDomainChrDefPtr def,
VIR_FORCE_CLOSE(fd_out);
return NULL;
}
FD_SET(fd_out, keepfd);
virCommandTransferFD(cmd, fd_out);
}
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
@ -419,109 +420,27 @@ static char *umlNextArg(char *args)
* Constructs a argv suitable for launching uml with config defined
* for a given virtual machine.
*/
int umlBuildCommandLine(virConnectPtr conn,
struct uml_driver *driver,
virDomainObjPtr vm,
fd_set *keepfd,
const char ***retargv,
const char ***retenv)
virCommandPtr umlBuildCommandLine(virConnectPtr conn,
struct uml_driver *driver,
virDomainObjPtr vm)
{
int i, j;
char memory[50];
struct utsname ut;
int qargc = 0, qarga = 0;
const char **qargv = NULL;
int qenvc = 0, qenva = 0;
const char **qenv = NULL;
char *cmdline = NULL;
virCommandPtr cmd;
uname(&ut);
#define ADD_ARG_SPACE \
do { \
if (qargc == qarga) { \
qarga += 10; \
if (VIR_REALLOC_N(qargv, qarga) < 0) \
goto no_memory; \
} \
} while (0)
cmd = virCommandNew(vm->def->os.kernel);
#define ADD_ARG(thisarg) \
do { \
ADD_ARG_SPACE; \
qargv[qargc++] = thisarg; \
} while (0)
virCommandAddEnvPassCommon(cmd);
#define ADD_ARG_LIT(thisarg) \
do { \
ADD_ARG_SPACE; \
if ((qargv[qargc++] = strdup(thisarg)) == NULL) \
goto no_memory; \
} while (0)
#define ADD_ARG_PAIR(key,val) \
do { \
char *arg; \
ADD_ARG_SPACE; \
if (virAsprintf(&arg, "%s=%s", key, val) < 0) \
goto no_memory; \
qargv[qargc++] = arg; \
} while (0)
#define ADD_ENV_SPACE \
do { \
if (qenvc == qenva) { \
qenva += 10; \
if (VIR_REALLOC_N(qenv, qenva) < 0) \
goto no_memory; \
} \
} while (0)
#define ADD_ENV(thisarg) \
do { \
ADD_ENV_SPACE; \
qenv[qenvc++] = thisarg; \
} while (0)
#define ADD_ENV_LIT(thisarg) \
do { \
ADD_ENV_SPACE; \
if ((qenv[qenvc++] = strdup(thisarg)) == NULL) \
goto no_memory; \
} while (0)
#define ADD_ENV_COPY(envname) \
do { \
char *val = getenv(envname); \
char *envval; \
ADD_ENV_SPACE; \
if (val != NULL) { \
if (virAsprintf(&envval, "%s=%s", envname, val) < 0) \
goto no_memory; \
qenv[qenvc++] = envval; \
} \
} while (0)
snprintf(memory, sizeof(memory), "%luK", vm->def->mem.cur_balloon);
ADD_ENV_LIT("LC_ALL=C");
ADD_ENV_COPY("LD_PRELOAD");
ADD_ENV_COPY("LD_LIBRARY_PATH");
ADD_ENV_COPY("PATH");
ADD_ENV_COPY("USER");
ADD_ENV_COPY("LOGNAME");
ADD_ENV_COPY("TMPDIR");
ADD_ARG_LIT(vm->def->os.kernel);
//ADD_ARG_PAIR("con0", "fd:0,fd:1");
ADD_ARG_PAIR("mem", memory);
ADD_ARG_PAIR("umid", vm->def->name);
ADD_ARG_PAIR("uml_dir", driver->monitorDir);
//virCommandAddArgPair(cmd, "con0", "fd:0,fd:1");
virCommandAddArgFormat(cmd, "mem=%luK", vm->def->mem.cur_balloon);
virCommandAddArgPair(cmd, "umid", vm->def->name);
virCommandAddArgPair(cmd, "uml_dir", driver->monitorDir);
if (vm->def->os.root)
ADD_ARG_PAIR("root", vm->def->os.root);
virCommandAddArgPair(cmd, "root", vm->def->os.root);
for (i = 0 ; i < vm->def->ndisks ; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
@ -532,24 +451,26 @@ int umlBuildCommandLine(virConnectPtr conn,
goto error;
}
ADD_ARG_PAIR(disk->dst, disk->src);
virCommandAddArgPair(cmd, disk->dst, disk->src);
}
for (i = 0 ; i < vm->def->nnets ; i++) {
char *ret = umlBuildCommandLineNet(conn, vm->def->nets[i], i);
if (!ret)
goto error;
ADD_ARG(ret);
virCommandAddArg(cmd, ret);
VIR_FREE(ret);
}
for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
char *ret = NULL;
if (i == 0 && vm->def->console)
ret = umlBuildCommandLineChr(vm->def->console, "con", keepfd);
ret = umlBuildCommandLineChr(vm->def->console, "con", cmd);
if (!ret)
if (virAsprintf(&ret, "con%d=none", i) < 0)
goto no_memory;
ADD_ARG(ret);
virCommandAddArg(cmd, ret);
VIR_FREE(ret);
}
for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
@ -559,15 +480,18 @@ int umlBuildCommandLine(virConnectPtr conn,
if (vm->def->serials[j]->target.port == i)
chr = vm->def->serials[j];
if (chr)
ret = umlBuildCommandLineChr(chr, "ssl", keepfd);
ret = umlBuildCommandLineChr(chr, "ssl", cmd);
if (!ret)
if (virAsprintf(&ret, "ssl%d=none", i) < 0)
goto no_memory;
ADD_ARG(ret);
virCommandAddArg(cmd, ret);
VIR_FREE(ret);
}
if (vm->def->os.cmdline) {
char *args, *next_arg;
char *cmdline;
if ((cmdline = strdup(vm->def->os.cmdline)) == NULL)
goto no_memory;
@ -577,41 +501,18 @@ int umlBuildCommandLine(virConnectPtr conn,
while (*args) {
next_arg = umlNextArg(args);
ADD_ARG_LIT(args);
virCommandAddArg(cmd, args);
args = next_arg;
}
VIR_FREE(cmdline);
}
ADD_ARG(NULL);
ADD_ENV(NULL);
*retargv = qargv;
*retenv = qenv;
return 0;
return cmd;
no_memory:
virReportOOMError();
error:
if (qargv) {
for (i = 0 ; i < qargc ; i++)
VIR_FREE((qargv)[i]);
VIR_FREE(qargv);
}
if (qenv) {
for (i = 0 ; i < qenvc ; i++)
VIR_FREE((qenv)[i]);
VIR_FREE(qenv);
}
VIR_FREE(cmdline);
return -1;
#undef ADD_ARG
#undef ADD_ARG_LIT
#undef ADD_ARG_SPACE
#undef ADD_USBDISK
#undef ADD_ENV
#undef ADD_ENV_COPY
#undef ADD_ENV_LIT
#undef ADD_ENV_SPACE
virCommandFree(cmd);
return NULL;
}

View File

@ -31,6 +31,7 @@
# include "domain_conf.h"
# include "virterror_internal.h"
# include "threads.h"
# include "command.h"
# define umlDebug(fmt, ...) do {} while(0)
@ -68,11 +69,8 @@ struct uml_driver {
virCapsPtr umlCapsInit (void);
int umlBuildCommandLine (virConnectPtr conn,
struct uml_driver *driver,
virDomainObjPtr dom,
fd_set *keepfd,
const char ***retargv,
const char ***retenv);
virCommandPtr umlBuildCommandLine(virConnectPtr conn,
struct uml_driver *driver,
virDomainObjPtr dom);
#endif /* __UML_CONF_H */

View File

@ -812,18 +812,11 @@ static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
static int umlStartVMDaemon(virConnectPtr conn,
struct uml_driver *driver,
virDomainObjPtr vm) {
const char **argv = NULL, **tmp;
const char **progenv = NULL;
int i, ret;
pid_t pid;
int ret;
char *logfile;
int logfd = -1;
struct stat sb;
fd_set keepfd;
char ebuf[1024];
umlDomainObjPrivatePtr priv = vm->privateData;
FD_ZERO(&keepfd);
virCommandPtr cmd = NULL;
if (virDomainObjIsActive(vm)) {
umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@ -840,7 +833,7 @@ static int umlStartVMDaemon(virConnectPtr conn,
* Technically we could catch the exec() failure, but that's
* in a sub-process so its hard to feed back a useful error
*/
if (stat(vm->def->os.kernel, &sb) < 0) {
if (access(vm->def->os.kernel, X_OK) < 0) {
virReportSystemError(errno,
_("Cannot find UML kernel %s"),
vm->def->os.kernel);
@ -877,67 +870,30 @@ static int umlStartVMDaemon(virConnectPtr conn,
return -1;
}
if (umlBuildCommandLine(conn, driver, vm, &keepfd,
&argv, &progenv) < 0) {
if (!(cmd = umlBuildCommandLine(conn, driver, vm))) {
VIR_FORCE_CLOSE(logfd);
virDomainConfVMNWFilterTeardown(vm);
umlCleanupTapDevices(conn, vm);
return -1;
}
tmp = progenv;
while (*tmp) {
if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
VIR_WARN("Unable to write envv to logfile: %s",
virStrerror(errno, ebuf, sizeof ebuf));
if (safewrite(logfd, " ", 1) < 0)
VIR_WARN("Unable to write envv to logfile: %s",
virStrerror(errno, ebuf, sizeof ebuf));
tmp++;
}
tmp = argv;
while (*tmp) {
if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
VIR_WARN("Unable to write argv to logfile: %s",
virStrerror(errno, ebuf, sizeof ebuf));
if (safewrite(logfd, " ", 1) < 0)
VIR_WARN("Unable to write argv to logfile: %s",
virStrerror(errno, ebuf, sizeof ebuf));
tmp++;
}
if (safewrite(logfd, "\n", 1) < 0)
VIR_WARN("Unable to write argv to logfile: %s",
virStrerror(errno, ebuf, sizeof ebuf));
virCommandWriteArgLog(cmd, logfd);
priv->monitor = -1;
ret = virExecDaemonize(argv, progenv, &keepfd, &pid,
-1, &logfd, &logfd,
VIR_EXEC_CLEAR_CAPS,
NULL, NULL, NULL);
virCommandClearCaps(cmd);
virCommandSetOutputFD(cmd, &logfd);
virCommandSetErrorFD(cmd, &logfd);
virCommandDaemonize(cmd);
ret = virCommandRun(cmd, NULL);
VIR_FORCE_CLOSE(logfd);
if (ret < 0)
goto cleanup;
ret = virDomainObjSetDefTransient(driver->caps, vm);
cleanup:
/*
* At the moment, the only thing that populates keepfd is
* umlBuildCommandLineChr. We want to close every fd it opens.
*/
for (i = 0; i < FD_SETSIZE; i++)
if (FD_ISSET(i, &keepfd)) {
int tmpfd = i;
VIR_FORCE_CLOSE(tmpfd);
}
for (i = 0 ; argv[i] ; i++)
VIR_FREE(argv[i]);
VIR_FREE(argv);
for (i = 0 ; progenv[i] ; i++)
VIR_FREE(progenv[i]);
VIR_FREE(progenv);
virCommandFree(cmd);
if (ret < 0) {
virDomainConfVMNWFilterTeardown(vm);