[libvirt] [PATCH] Implement autostart commands for xen

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;

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.
It is a good patch for me. It moved without a problem when I tested it. By the way, I have a question. What is "getAutostart" used by? "getAutostart" seems to be used from no virsh command. Thanks, Shigeki Sakamoto.

On Thu, May 08, 2008 at 06:42:13PM +0900, S.Sakamoto wrote:
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.
It is a good patch for me. It moved without a problem when I tested it.
By the way, I have a question. What is "getAutostart" used by? "getAutostart" seems to be used from no virsh command.
Well virt-manager will call it and display the autostart status. I don't know what virsh doesn't use it. It should really show the autostart status when display a 'virsh domiinfo' Dan. -- |: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

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.
It is a good patch for me. It moved without a problem when I tested it.
By the way, I have a question. What is "getAutostart" used by? "getAutostart" seems to be used from no virsh command.
Well virt-manager will call it and display the autostart status. I don't know what virsh doesn't use it. It should really show the autostart status when display a 'virsh domiinfo'
Thanks! I understand that "getAutostart" was made to confirm an autostart parameter. thanks, Shigeki Sakamoto.

Hi, Cole Cole Robinson <crobinso@redhat.com> wrote:
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?
This is current Xen behavior. If you need to work as you hope, you should change Xend. Your code seems good to me. Thanks Atsushi SAKAI

On Wed, May 07, 2008 at 04:21:25PM -0400, Cole Robinson wrote:
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?
That's just the way XenD works - nothing we can do about this AFAICT
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.
This would need a completely separate approach - symlinking the config files from /etc/xen into /etc/xen/auto Dan. -- |: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, May 07, 2008 at 04:21:25PM -0400, Cole Robinson wrote:
+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); + }
Since this only works in Xen 3.0.4 or later can you add in: /* xm_internal.c (the support for defined domains from /etc/xen * config files used by old Xen) will handle this. */ if (priv->xendConfigVersion < 3) return(-1); This ensures that users will get a 'operation not supported' error for older XenD - at least until we implement the alternate /etc/xen/auto symlink scheme for xm_internal.c driver.
+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); + }
Same here - add a xendConfigVersion check.
+ 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) {
Use sizeof(buf) here instead of duplicating 4096 constant. Regards, Dan. -- |: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Cole Robinson wrote:
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.
Updated patch with fixes Dan recommended. 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 6d64509..90d3f4f 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 */ @@ -3728,6 +3728,115 @@ 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; + xenUnifiedPrivatePtr priv; + + if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { + virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, + __FUNCTION__); + return (-1); + } + + /* xm_internal.c (the support for defined domains from /etc/xen + * config files used by old Xen) will handle this. + */ + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; + if (priv->xendConfigVersion < 3) + 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; + xenUnifiedPrivatePtr priv; + + if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { + virXendError((domain ? domain->conn : NULL), VIR_ERR_INTERNAL_ERROR, + __FUNCTION__); + return (-1); + } + + /* xm_internal.c (the support for defined domains from /etc/xen + * config files used by old Xen) will handle this. + */ + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; + if (priv->xendConfigVersion < 3) + 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, sizeof(buf)) == 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;

On Thu, May 08, 2008 at 01:49:15PM -0400, Cole Robinson wrote:
Cole Robinson wrote:
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.
Updated patch with fixes Dan recommended.
Okidoc, applied and commited, thanks a lot ! Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/
participants (5)
-
Atsushi SAKAI
-
Cole Robinson
-
Daniel P. Berrange
-
Daniel Veillard
-
S.Sakamoto