diff --git a/ChangeLog b/ChangeLog index f1cca3e869..11294b77f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri Jun 16 12:44:02 EDT 2006 Daniel Veillard + + * src/libvirt.c src/xen_internal.c src/xend_internal.c: more driver + related cleanups, nearly finished + Thu Jun 15 14:57:39 EDT 2006 Daniel Veillard * src/libvirt.c src/xend_internal.c src/xend_internal.h diff --git a/src/libvirt.c b/src/libvirt.c index d8b33f57f1..c5fe275d07 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -516,14 +516,11 @@ virConnectNumOfDomains(virConnectPtr conn) * Returns a new domain object or NULL in case of failure */ virDomainPtr -virDomainCreateLinux(virConnectPtr conn, - const char *xmlDesc, - unsigned int flags ATTRIBUTE_UNUSED) +virDomainCreateLinux(virConnectPtr conn, const char *xmlDesc, + unsigned int flags) { - int ret; - char *sexpr; - char *name = NULL; - virDomainPtr dom; + virDomainPtr ret; + int i; if (!VIR_IS_CONNECT(conn)) { virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -534,49 +531,15 @@ virDomainCreateLinux(virConnectPtr conn, return (NULL); } - sexpr = virDomainParseXMLDesc(xmlDesc, &name); - if ((sexpr == NULL) || (name == NULL)) { - if (sexpr != NULL) - free(sexpr); - if (name != NULL) - free(name); - - return (NULL); + for (i = 0;i < conn->nb_drivers;i++) { + if ((conn->drivers[i] != NULL) && + (conn->drivers[i]->domainCreateLinux != NULL)) { + ret = conn->drivers[i]->domainCreateLinux(conn, xmlDesc, flags); + if (ret != NULL) + return(ret); + } } - - ret = xenDaemonDomainCreateLinux(conn, sexpr); - free(sexpr); - if (ret != 0) { - fprintf(stderr, "Failed to create domain %s\n", name); - goto error; - } - - ret = xend_wait_for_devices(conn, name); - if (ret != 0) { - fprintf(stderr, "Failed to get devices for domain %s\n", name); - goto error; - } - - dom = virDomainLookupByName(conn, name); - if (dom == NULL) { - goto error; - } - - ret = xenDaemonDomainResume(dom); - if (ret != 0) { - fprintf(stderr, "Failed to resume new domain %s\n", name); - xenDaemonDomainDestroy(dom); - goto error; - } - - dom = virDomainLookupByName(conn, name); - free(name); - - return (dom); - error: - if (name != NULL) - free(name); - return (NULL); + return(NULL); } @@ -865,7 +828,7 @@ virDomainSuspend(virDomainPtr domain) int virDomainResume(virDomainPtr domain) { - int ret = -1, i; + int i; virConnectPtr conn; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { @@ -884,16 +847,12 @@ virDomainResume(virDomainPtr domain) if ((conn->drivers[i] != NULL) && (conn->drivers[i]->domainResume != NULL)) { if (conn->drivers[i]->domainResume(domain) == 0) - ret = 0; + return(0); } } - if (ret != 0) { - virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); - return (ret); - } - - return (ret); + virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return (-1); } /** @@ -911,13 +870,15 @@ virDomainResume(virDomainPtr domain) int virDomainSave(virDomainPtr domain, const char *to) { - int ret; + int ret, i; char filepath[4096]; + virConnectPtr conn; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } + conn = domain->conn; if (to == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); return (-1); @@ -943,8 +904,17 @@ virDomainSave(virDomainPtr domain, const char *to) } - ret = xenDaemonDomainSave(domain, to); - return (ret); + /* Go though the driver registered entry points */ + for (i = 0;i < conn->nb_drivers;i++) { + if ((conn->drivers[i] != NULL) && + (conn->drivers[i]->domainSave != NULL)) { + ret = conn->drivers[i]->domainSave(domain, to); + if (ret == 0) + return(0); + } + } + virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return (-1); } /** @@ -959,7 +929,7 @@ virDomainSave(virDomainPtr domain, const char *to) int virDomainRestore(virConnectPtr conn, const char *from) { - int ret; + int ret, i; char filepath[4096]; if (!VIR_IS_CONNECT(conn)) { @@ -990,8 +960,17 @@ virDomainRestore(virConnectPtr conn, const char *from) from = &filepath[0]; } - ret = xenDaemonDomainRestore(conn, from); - return (ret); + /* Go though the driver registered entry points */ + for (i = 0;i < conn->nb_drivers;i++) { + if ((conn->drivers[i] != NULL) && + (conn->drivers[i]->domainSave != NULL)) { + ret = conn->drivers[i]->domainRestore(conn, from); + if (ret == 0) + return(0); + } + } + virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return (-1); } /** @@ -1242,28 +1221,30 @@ unsigned long virDomainGetMaxMemory(virDomainPtr domain) { unsigned long ret = 0; + virConnectPtr conn; + int i; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (0); } - /* - * try first with the hypervisor if available - */ - if (!(domain->conn->flags & VIR_CONNECT_RO)) { - virDomainInfo dominfo; - int tmp; + conn = domain->conn; - tmp = xenHypervisorGetDomainInfo(domain, &dominfo); - if (tmp >= 0) - return(dominfo.maxMem); + /* + * in that case instead of trying only though one method try all availble. + * If needed that can be changed back if it's a performcance problem. + */ + for (i = 0;i < conn->nb_drivers;i++) { + if ((conn->drivers[i] != NULL) && + (conn->drivers[i]->domainGetMaxMemory != NULL)) { + ret = conn->drivers[i]->domainGetMaxMemory(domain); + if (ret != 0) + return(ret); + } } - ret = xenStoreDomainGetMaxMemory(domain); - if (ret > 0) - return(ret); - ret = xenDaemonDomainGetMaxMemory(domain); - return (ret); + virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return (-1); } /** @@ -1384,7 +1365,6 @@ virDomainSetMemory(virDomainPtr domain, unsigned long memory) int virDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { - int ret; int i; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { diff --git a/src/xen_internal.c b/src/xen_internal.c index 6ab54779dc..0f8dada3e2 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -41,6 +41,7 @@ typedef struct hypercall_struct { #define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd" static const char * xenHypervisorGetType(virConnectPtr conn); +static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain); static virDriver xenHypervisorDriver = { "Xen", @@ -69,7 +70,7 @@ static virDriver xenHypervisorDriver = { NULL, /* domainGetID */ NULL, /* domainGetUUID */ NULL, /* domainGetOSType */ - NULL, /* domainGetMaxMemory */ + xenHypervisorGetMaxMemory, /* domainGetMaxMemory */ xenHypervisorSetMaxMemory, /* domainSetMaxMemory */ NULL, /* domainSetMemory */ xenHypervisorGetDomainInfo, /* domainGetInfo */ @@ -396,6 +397,56 @@ xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids) return (nbids); } +/** + * xenHypervisorGetMaxMemory: + * @domain: a domain object or NULL + * + * Retrieve the maximum amount of physical memory allocated to a + * domain. If domain is NULL, then this get the amount of memory reserved + * to Domain0 i.e. the domain where the application runs. + * + * Returns the memory size in kilobytes or 0 in case of error. + */ +static unsigned long +xenHypervisorGetMaxMemory(virDomainPtr domain) +{ + dom0_op_t op; + dom0_getdomaininfo_t dominfo; + int ret; + + if ((domain == NULL) || (domain->conn == NULL) || + (domain->conn->handle < 0)) + return (0); + + memset(&dominfo, 0, sizeof(dom0_getdomaininfo_t)); + + if (mlock(&dominfo, sizeof(dom0_getdomaininfo_t)) < 0) { + virXenError(VIR_ERR_XEN_CALL, " locking", + sizeof(dom0_getdomaininfo_t)); + return (0); + } + + op.cmd = DOM0_GETDOMAININFOLIST; + op.u.getdomaininfolist.first_domain = (domid_t) domain->handle; + op.u.getdomaininfolist.max_domains = 1; + op.u.getdomaininfolist.buffer = &dominfo; + op.u.getdomaininfolist.num_domains = 1; + dominfo.domain = domain->handle; + + ret = xenHypervisorDoOp(domain->conn->handle, &op); + + if (munlock(&dominfo, sizeof(dom0_getdomaininfo_t)) < 0) { + virXenError(VIR_ERR_XEN_CALL, " release", + sizeof(dom0_getdomaininfo_t)); + ret = -1; + } + + if (ret < 0) + return (0); + + return((unsigned long) dominfo.max_pages * 4); +} + /** * xenHypervisorGetDomainInfo: * @domain: pointer to the domain block diff --git a/src/xend_internal.c b/src/xend_internal.c index 1a4f124971..fc1ff7a41e 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -44,6 +44,9 @@ static int xenDaemonNumOfDomains(virConnectPtr conn); static virDomainPtr xenDaemonLookupByID(virConnectPtr conn, int id); static virDomainPtr xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +static virDomainPtr xenDaemonCreateLinux(virConnectPtr conn, + const char *xmlDesc, + unsigned int flags); static virDriver xenDaemonDriver = { "XenDaemon", @@ -58,7 +61,7 @@ static virDriver xenDaemonDriver = { xenDaemonNodeGetInfo, /* nodeGetInfo */ xenDaemonListDomains, /* listDomains */ xenDaemonNumOfDomains, /* numOfDomains */ - NULL, /* domainCreateLinux */ + xenDaemonCreateLinux, /* domainCreateLinux */ xenDaemonLookupByID, /* domainLookupByID */ xenDaemonLookupByUUID, /* domainLookupByUUID */ xenDaemonDomainLookupByName, /* domainLookupByName */ @@ -72,7 +75,7 @@ static virDriver xenDaemonDriver = { NULL, /* domainGetID */ NULL, /* domainGetUUID */ NULL, /* domainGetOSType */ - NULL, /* domainGetMaxMemory */ + xenDaemonDomainGetMaxMemory, /* domainGetMaxMemory */ xenDaemonDomainSetMaxMemory, /* domainSetMaxMemory */ xenDaemonDomainSetMemory, /* domainMaxMemory */ xenDaemonDomainGetInfo, /* domainGetInfo */ @@ -2340,3 +2343,79 @@ error: free(name); return (NULL); } + +/** + * xenDaemonCreateLinux: + * @conn: pointer to the hypervisor connection + * @xmlDesc: an XML description of the domain + * @flags: an optional set of virDomainFlags + * + * Launch a new Linux guest domain, based on an XML description similar + * to the one returned by virDomainGetXMLDesc() + * This function may requires priviledged access to the hypervisor. + * + * Returns a new domain object or NULL in case of failure + */ +static virDomainPtr +xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc, + unsigned int flags ATTRIBUTE_UNUSED) +{ + int ret; + char *sexpr; + char *name = NULL; + virDomainPtr dom; + + if (!VIR_IS_CONNECT(conn)) { + virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (xmlDesc == NULL) { + virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return (NULL); + } + + sexpr = virDomainParseXMLDesc(xmlDesc, &name); + if ((sexpr == NULL) || (name == NULL)) { + if (sexpr != NULL) + free(sexpr); + if (name != NULL) + free(name); + + return (NULL); + } + + ret = xenDaemonDomainCreateLinux(conn, sexpr); + free(sexpr); + if (ret != 0) { + fprintf(stderr, "Failed to create domain %s\n", name); + goto error; + } + + ret = xend_wait_for_devices(conn, name); + if (ret != 0) { + fprintf(stderr, "Failed to get devices for domain %s\n", name); + goto error; + } + + dom = virDomainLookupByName(conn, name); + if (dom == NULL) { + goto error; + } + + ret = xenDaemonDomainResume(dom); + if (ret != 0) { + fprintf(stderr, "Failed to resume new domain %s\n", name); + xenDaemonDomainDestroy(dom); + goto error; + } + + dom = virDomainLookupByName(conn, name); + free(name); + + return (dom); + error: + if (name != NULL) + free(name); + return (NULL); +} +