Actually implement the autostart API in qemud by saving
autostart configs to a specific directory.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
Index: libvirt/qemud/conf.c
===================================================================
--- libvirt.orig/qemud/conf.c
+++ libvirt/qemud/conf.c
@@ -1147,7 +1147,7 @@ static int qemudSaveConfig(struct qemud_
return -1;
}
- if ((err = qemudEnsureDir(server->configDir))) {
+ if ((err = qemudEnsureDir(!vm->autostart ? server->configDir :
server->autostartConfigDir))) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot create config directory %s: %s",
server->configDir, strerror(err));
@@ -1195,7 +1195,8 @@ static int qemudSaveConfig(struct qemud_
struct qemud_vm *qemudLoadConfigXML(struct qemud_server *server,
const char *file,
const char *doc,
- int save) {
+ int save,
+ int isAutostart) {
struct qemud_vm_def *def = NULL;
struct qemud_vm *vm = NULL;
xmlDocPtr xml;
@@ -1239,12 +1240,15 @@ struct qemud_vm *qemudLoadConfigXML(stru
newVM = 1;
}
+ vm->autostart = (isAutostart != 0);
+
if (file) {
strncpy(vm->configFile, file, PATH_MAX);
vm->configFile[PATH_MAX-1] = '\0';
} else {
if (save) {
- if (qemudMakeConfigPath(server->configDir, vm->def->name,
".xml", vm->configFile, PATH_MAX) < 0) {
+ if (qemudMakeConfigPath(!vm->autostart ? server->configDir :
server->autostartConfigDir,
+ vm->def->name, ".xml",
vm->configFile, PATH_MAX) < 0) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot construct config file path");
if (newVM)
@@ -1283,7 +1287,7 @@ static int qemudSaveNetworkConfig(struct
return -1;
}
- if ((err = qemudEnsureDir(server->networkConfigDir))) {
+ if ((err = qemudEnsureDir(!network->autostart ? server->networkConfigDir :
server->autostartNetworkConfigDir))) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot create config directory %s: %s",
server->networkConfigDir, strerror(err));
@@ -1550,7 +1554,8 @@ static struct qemud_network_def *qemudPa
struct qemud_network *qemudLoadNetworkConfigXML(struct qemud_server *server,
const char *file,
const char *doc,
- int save) {
+ int save,
+ int isAutostart) {
struct qemud_network_def *def = NULL;
struct qemud_network *network = NULL;
xmlDocPtr xml;
@@ -1588,12 +1593,15 @@ struct qemud_network *qemudLoadNetworkCo
newNetwork = 1;
}
+ network->autostart = (isAutostart != 0);
+
if (file) {
strncpy(network->configFile, file, PATH_MAX);
network->configFile[PATH_MAX-1] = '\0';
} else {
if (save) {
- if (qemudMakeConfigPath(server->networkConfigDir,
network->def->name, ".xml", network->configFile, PATH_MAX) < 0) {
+ if (qemudMakeConfigPath(!network->autostart ? server->networkConfigDir
: server->autostartNetworkConfigDir,
+ network->def->name, ".xml",
network->configFile, PATH_MAX) < 0) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot construct
config file path");
if (newNetwork)
qemudFreeNetwork(network);
@@ -1623,7 +1631,8 @@ struct qemud_network *qemudLoadNetworkCo
/* Load a guest from its persistent config file */
static void qemudLoadConfig(struct qemud_server *server,
const char *file,
- int isGuest) {
+ int isGuest,
+ int isAutostart) {
FILE *fh;
struct stat st;
char xml[QEMUD_MAX_XML_LEN];
@@ -1651,9 +1660,9 @@ static void qemudLoadConfig(struct qemud
xml[st.st_size] = '\0';
if (isGuest) {
- qemudLoadConfigXML(server, file, xml, 1);
+ qemudLoadConfigXML(server, file, xml, 1, isAutostart);
} else {
- qemudLoadNetworkConfigXML(server, file, xml, 1);
+ qemudLoadNetworkConfigXML(server, file, xml, 1, isAutostart);
}
cleanup:
fclose(fh);
@@ -1663,7 +1672,8 @@ static void qemudLoadConfig(struct qemud
static
int qemudScanConfigDir(struct qemud_server *server,
const char *configDir,
- int isGuest) {
+ int isGuest,
+ int isAutostart) {
DIR *dir;
struct dirent *entry;
@@ -1683,7 +1693,7 @@ int qemudScanConfigDir(struct qemud_serv
if (qemudMakeConfigPath(configDir, entry->d_name, NULL, file, PATH_MAX) <
0)
continue;
- qemudLoadConfig(server, file, isGuest);
+ qemudLoadConfig(server, file, isGuest, isAutostart);
}
closedir(dir);
@@ -1693,9 +1703,13 @@ int qemudScanConfigDir(struct qemud_serv
/* Scan for all guest and network config files */
int qemudScanConfigs(struct qemud_server *server) {
- if (qemudScanConfigDir(server, server->configDir, 1) < 0)
+ if (qemudScanConfigDir(server, server->configDir, 1, 0) < 0 ||
+ qemudScanConfigDir(server, server->autostartConfigDir, 1, 1) < 0)
return -1;
- return qemudScanConfigDir(server, server->networkConfigDir, 0);
+ if (qemudScanConfigDir(server, server->networkConfigDir, 0, 0) < 0 ||
+ qemudScanConfigDir(server, server->autostartNetworkConfigDir, 0, 1) < 0)
+ return -1;
+ return 0;
}
/* Simple grow-on-demand string buffer */
Index: libvirt/qemud/conf.h
===================================================================
--- libvirt.orig/qemud/conf.h
+++ libvirt/qemud/conf.h
@@ -40,7 +40,8 @@ void qemudFreeVM(struct qemud_vm *vm);
struct qemud_vm *qemudLoadConfigXML(struct qemud_server *server,
const char *file,
const char *doc,
- int persist);
+ int persist,
+ int isAutostart);
char *qemudGenerateXML(struct qemud_server *server,
struct qemud_vm *vm, int live);
@@ -49,7 +50,8 @@ void qemudFreeNetwork(struct qemud_netwo
struct qemud_network *qemudLoadNetworkConfigXML(struct qemud_server *server,
const char *file,
const char *doc,
- int persist);
+ int persist,
+ int isAutostart);
char *qemudGenerateNetworkXML(struct qemud_server *server,
struct qemud_network *network,
int live);
Index: libvirt/qemud/internal.h
===================================================================
--- libvirt.orig/qemud/internal.h
+++ libvirt/qemud/internal.h
@@ -294,6 +294,8 @@ struct qemud_server {
iptablesContext *iptables;
char configDir[PATH_MAX];
char networkConfigDir[PATH_MAX];
+ char autostartConfigDir[PATH_MAX];
+ char autostartNetworkConfigDir[PATH_MAX];
char errorMessage[QEMUD_MAX_ERROR_LEN];
int errorCode;
unsigned int shutdown : 1;
Index: libvirt/qemud/qemud.c
===================================================================
--- libvirt.orig/qemud/qemud.c
+++ libvirt/qemud/qemud.c
@@ -357,6 +357,8 @@ static int qemudListenUnix(struct qemud_
static int qemudInitPaths(int sys,
char *configDir,
char *networkConfigDir,
+ char *autostartConfigDir,
+ char *autostartNetworkConfigDir,
char *sockname,
char *roSockname,
int maxlen) {
@@ -376,6 +378,12 @@ static int qemudInitPaths(int sys,
if (snprintf(networkConfigDir, maxlen, "%s/libvirt/qemu/networks",
SYSCONF_DIR) >= maxlen)
goto snprintf_error;
+ if (snprintf(autostartConfigDir, maxlen, "%s/libvirt/qemu/autostart",
SYSCONF_DIR) >= maxlen)
+ goto snprintf_error;
+
+ if (snprintf(autostartNetworkConfigDir, maxlen,
"%s/libvirt/qemu/networks/autostart", SYSCONF_DIR) >= maxlen)
+ goto snprintf_error;
+
if (snprintf(sockname, maxlen, "%s/run/libvirt/qemud-sock",
LOCAL_STATE_DIR) >= maxlen)
goto snprintf_error;
@@ -400,6 +408,12 @@ static int qemudInitPaths(int sys,
if (snprintf(networkConfigDir, maxlen, "%s/.libvirt/qemu/networks",
pw->pw_dir) >= maxlen)
goto snprintf_error;
+ if (snprintf(autostartConfigDir, maxlen, "%s/.libvirt/qemu/autostart",
pw->pw_dir) >= maxlen)
+ goto snprintf_error;
+
+ if (snprintf(autostartNetworkConfigDir, maxlen,
"%s/.libvirt/qemu/networks/autostart", pw->pw_dir) >= maxlen)
+ goto snprintf_error;
+
if (snprintf(sockname, maxlen, "(a)%s/.libvirt/qemud-sock",
pw->pw_dir) >= maxlen)
goto snprintf_error;
}
@@ -430,6 +444,7 @@ static struct qemud_server *qemudInitial
roSockname[0] = '\0';
if (qemudInitPaths(sys, server->configDir, server->networkConfigDir,
+ server->autostartConfigDir,
server->autostartNetworkConfigDir,
sockname, roSockname, PATH_MAX) < 0)
goto cleanup;
Index: libvirt/qemud/driver.c
===================================================================
--- libvirt.orig/qemud/driver.c
+++ libvirt/qemud/driver.c
@@ -281,7 +281,7 @@ int qemudNumDomains(struct qemud_server
struct qemud_vm *qemudDomainCreate(struct qemud_server *server, const char *xml) {
struct qemud_vm *vm;
- if (!(vm = qemudLoadConfigXML(server, NULL, xml, 0))) {
+ if (!(vm = qemudLoadConfigXML(server, NULL, xml, 0, 0))) {
return NULL;
}
@@ -464,7 +464,7 @@ int qemudDomainStart(struct qemud_server
struct qemud_vm *qemudDomainDefine(struct qemud_server *server, const char *xml) {
- return qemudLoadConfigXML(server, NULL, xml, 1);
+ return qemudLoadConfigXML(server, NULL, xml, 1, 0);
}
int qemudDomainUndefine(struct qemud_server *server, const unsigned char *uuid) {
@@ -525,6 +525,9 @@ int qemudDomainSetAutostart(struct qemud
const unsigned char *uuid,
int autostart) {
struct qemud_vm *vm = qemudFindVMByUUID(server, uuid);
+ char oldConfig[PATH_MAX];
+ char *xml;
+ int ret = -1;
if (!vm) {
qemudReportError(server, VIR_ERR_INVALID_DOMAIN, "no domain with matching
uuid");
@@ -536,9 +539,35 @@ int qemudDomainSetAutostart(struct qemud
if (vm->autostart == autostart)
return 0;
+ if (!(xml = qemudGenerateXML(server, vm, 0)))
+ goto error;
+
+ strncpy(oldConfig, vm->configFile, PATH_MAX);
+ oldConfig[PATH_MAX-1] = '\0';
+
+ if (!qemudLoadConfigXML(server, NULL, xml, 1, autostart))
+ goto error;
+
+ if (oldConfig[0] && qemudDeleteConfig(server, oldConfig, vm->def->name)
< 0) {
+ if (unlink(vm->configFile) < 0)
+ qemudLog(QEMUD_ERR, "Failed to unlink '%s' in order to roll
"
+ "back in qemudDomainSetAutostart(): %s",
strerror(errno));
+
+ strncpy(vm->configFile, oldConfig, PATH_MAX);
+ vm->configFile[PATH_MAX-1] = '\0';
+
+ goto error;
+ }
+
vm->autostart = autostart;
- return 0;
+ ret = 0;
+
+ error:
+ if (xml)
+ free(xml);
+
+ return ret;
}
struct qemud_network *qemudFindNetworkByUUID(const struct qemud_server *server,
@@ -606,7 +635,7 @@ int qemudListDefinedNetworks(struct qemu
struct qemud_network *qemudNetworkCreate(struct qemud_server *server, const char *xml) {
struct qemud_network *network;
- if (!(network = qemudLoadNetworkConfigXML(server, NULL, xml, 0))) {
+ if (!(network = qemudLoadNetworkConfigXML(server, NULL, xml, 0, 0))) {
return NULL;
}
@@ -619,7 +648,7 @@ struct qemud_network *qemudNetworkCreate
}
struct qemud_network *qemudNetworkDefine(struct qemud_server *server, const char *xml) {
- return qemudLoadNetworkConfigXML(server, NULL, xml, 1);
+ return qemudLoadNetworkConfigXML(server, NULL, xml, 1, 0);
}
int qemudNetworkUndefine(struct qemud_server *server, const unsigned char *uuid) {
@@ -730,6 +759,9 @@ int qemudNetworkSetAutostart(struct qemu
const unsigned char *uuid,
int autostart) {
struct qemud_network *network = qemudFindNetworkByUUID(server, uuid);
+ char oldConfig[PATH_MAX];
+ char *xml;
+ int ret = -1;
if (!network) {
qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching
uuid");
@@ -741,9 +773,35 @@ int qemudNetworkSetAutostart(struct qemu
if (network->autostart == autostart)
return 0;
+ if (!(xml = qemudGenerateNetworkXML(server, network, 0)))
+ goto error;
+
+ strncpy(oldConfig, network->configFile, PATH_MAX);
+ oldConfig[PATH_MAX-1] = '\0';
+
+ if (!qemudLoadNetworkConfigXML(server, NULL, xml, 1, autostart))
+ goto error;
+
+ if (oldConfig[0] && qemudDeleteConfig(server, oldConfig,
network->def->name) < 0) {
+ if (unlink(network->configFile) < 0)
+ qemudLog(QEMUD_ERR, "Failed to unlink '%s' in order to roll
"
+ "back in qemudNetworkSetAutostart(): %s",
strerror(errno));
+
+ strncpy(network->configFile, oldConfig, PATH_MAX);
+ network->configFile[PATH_MAX-1] = '\0';
+
+ goto error;
+ }
+
network->autostart = autostart;
- return 0;
+ ret = 0;
+
+ error:
+ if (xml)
+ free(xml);
+
+ return ret;
}
/*
--