The attached patch implements the domain autostart commands for
xen. The xen sexpr (since at least 3.0.4 = 1.5 years) has a
on_xend_start field which can be used to autostart a domain.
A couple things:
1) This works on a running guest, but will only show the
sexpr changes after the guest is restarted. Just curious
if there is any better way to do this?
2) This isn't implemented for the xm config file driver. I
figured this is fine since this is inherently dependent
on inactive domain management.
Any feedback is appreciated.
Thanks,
Cole
diff --git a/src/xen_unified.c b/src/xen_unified.c
index 91502dc..cf0a68d 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -1128,6 +1128,34 @@ xenUnifiedDomainDetachDevice (virDomainPtr dom, const char *xml)
return -1;
}
+static int
+xenUnifiedDomainGetAutostart (virDomainPtr dom, int *autostart)
+{
+ GET_PRIVATE(dom->conn);
+ int i;
+
+ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+ if (priv->opened[i] && drivers[i]->domainGetAutostart &&
+ drivers[i]->domainGetAutostart (dom, autostart) == 0)
+ return 0;
+
+ return -1;
+}
+
+static int
+xenUnifiedDomainSetAutostart (virDomainPtr dom, int autostart)
+{
+ GET_PRIVATE(dom->conn);
+ int i;
+
+ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+ if (priv->opened[i] && drivers[i]->domainSetAutostart &&
+ drivers[i]->domainSetAutostart (dom, autostart) == 0)
+ return 0;
+
+ return -1;
+}
+
static char *
xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams)
{
@@ -1291,6 +1319,8 @@ static virDriver xenUnifiedDriver = {
.domainUndefine = xenUnifiedDomainUndefine,
.domainAttachDevice = xenUnifiedDomainAttachDevice,
.domainDetachDevice = xenUnifiedDomainDetachDevice,
+ .domainGetAutostart = xenUnifiedDomainGetAutostart,
+ .domainSetAutostart = xenUnifiedDomainSetAutostart,
.domainGetSchedulerType = xenUnifiedDomainGetSchedulerType,
.domainGetSchedulerParameters = xenUnifiedDomainGetSchedulerParameters,
.domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters,
diff --git a/src/xend_internal.c b/src/xend_internal.c
index f9db571..226ba8e 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -115,8 +115,8 @@ struct xenUnifiedDriver xenDaemonDriver = {
xenDaemonDomainUndefine, /* domainUndefine */
xenDaemonAttachDevice, /* domainAttachDevice */
xenDaemonDetachDevice, /* domainDetachDevice */
- NULL, /* domainGetAutostart */
- NULL, /* domainSetAutostart */
+ xenDaemonDomainGetAutostart, /* domainGetAutostart */
+ xenDaemonDomainSetAutostart, /* domainSetAutostart */
xenDaemonGetSchedulerType, /* domainGetSchedulerType */
xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */
xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */
@@ -3718,6 +3718,99 @@ xenDaemonDetachDevice(virDomainPtr domain, const char *xml)
"type", class, "dev", ref, "force", "0",
"rm_cfg", "1", NULL));
}
+int
+xenDaemonDomainGetAutostart(virDomainPtr domain,
+ int *autostart)
+{
+ struct sexpr *root;
+ const char *tmp;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return (-1);
+ }
+
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1",
domain->name);
+ if (root == NULL) {
+ virXendError (domain->conn, VIR_ERR_XEN_CALL,
+ _("xenDaemonGetAutostart failed to find this domain"));
+ return (-1);
+ }
+
+ *autostart = 0;
+
+ tmp = sexpr_node(root, "domain/on_xend_start");
+ if (tmp && STREQ(tmp, "start")) {
+ *autostart = 1;
+ }
+
+ sexpr_free(root);
+ return 0;
+}
+
+int
+xenDaemonDomainSetAutostart(virDomainPtr domain,
+ int autostart)
+{
+ struct sexpr *root, *autonode;
+ const char *autostr;
+ char buf[4096];
+ int ret = -1;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ virXendError((domain ? domain->conn : NULL), VIR_ERR_INTERNAL_ERROR,
+ __FUNCTION__);
+ return (-1);
+ }
+
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1",
domain->name);
+ if (root == NULL) {
+ virXendError (domain->conn, VIR_ERR_XEN_CALL,
+ _("xenDaemonSetAutostart failed to find this domain"));
+ return (-1);
+ }
+
+ autostr = sexpr_node(root, "domain/on_xend_start");
+ if (autostr) {
+ if (!STREQ(autostr, "ignore") && !STREQ(autostr,
"start")) {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected value from on_xend_start"));
+ goto error;
+ }
+
+ // Change the autostart value in place, then define the new sexpr
+ autonode = sexpr_lookup(root, "domain/on_xend_start");
+ free(autonode->u.s.car->u.value);
+ autonode->u.s.car->u.value = (autostart ? strdup("start")
+ : strdup("ignore"));
+ if (!(autonode->u.s.car->u.value)) {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("no memory"));
+ goto error;
+ }
+
+ if (sexpr2string(root, buf, 4096) == 0) {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("sexpr2string failed"));
+ goto error;
+ }
+ if (xend_op(domain->conn, "", "op", "new",
"config", buf, NULL) != 0) {
+ virXendError(domain->conn, VIR_ERR_XEN_CALL,
+ _("Failed to redefine sexpr"));
+ goto error;
+ }
+ } else {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("on_xend_start not present in sexpr"));
+ goto error;
+ }
+
+ ret = 0;
+ error:
+ sexpr_free(root);
+ return ret;
+}
int
xenDaemonDomainMigratePrepare (virConnectPtr dconn,
diff --git a/src/xend_internal.h b/src/xend_internal.h
index 80ef4f6..97f98f2 100644
--- a/src/xend_internal.h
+++ b/src/xend_internal.h
@@ -229,6 +229,10 @@ int xenDaemonDomainGetVcpus (virDomainPtr domain,
int maxinfo,
unsigned char *cpumaps,
int maplen);
+int xenDaemonDomainGetAutostart (virDomainPtr dom,
+ int *autostart);
+int xenDaemonDomainSetAutostart (virDomainPtr domain,
+ int autostart);
/* xen_unified calls through here. */
extern struct xenUnifiedDriver xenDaemonDriver;