Actually implement the autostart API in qemud by saving autostart configs to a specific directory. Signed-off-by: Mark McLoughlin <markmc@xxxxxxxxxx> 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, "@%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; } /* --