Index: libvirt/include/libvirt/libvirt.h
===================================================================
RCS file: /data/cvs/libvirt/include/libvirt/libvirt.h,v
retrieving revision 1.39
diff -u -p -r1.39 libvirt.h
--- libvirt/include/libvirt/libvirt.h	6 Mar 2007 21:55:44 -0000	1.39
+++ libvirt/include/libvirt/libvirt.h	8 Mar 2007 00:46:35 -0000
@@ -231,6 +231,8 @@ int			virConnectClose		(virConnectPtr co
 const char *		virConnectGetType	(virConnectPtr conn);
 int			virConnectGetVersion	(virConnectPtr conn,
 						 unsigned long *hvVer);
+int			virConnectGetMaxVcpus	(virConnectPtr conn,
+						 const char *type);
 int			virNodeGetInfo		(virConnectPtr conn,
 						 virNodeInfoPtr info);
 
@@ -310,6 +312,8 @@ int			virDomainSetMaxMemory	(virDomainPt
 						 unsigned long memory);
 int			virDomainSetMemory	(virDomainPtr domain,
 						 unsigned long memory);
+int			virDomainGetMaxVcpus	(virDomainPtr domain);
+
 /*
  * XML domain description
  */
Index: libvirt/include/libvirt/libvirt.h.in
===================================================================
RCS file: /data/cvs/libvirt/include/libvirt/libvirt.h.in,v
retrieving revision 1.24
diff -u -p -r1.24 libvirt.h.in
--- libvirt/include/libvirt/libvirt.h.in	6 Mar 2007 21:55:44 -0000	1.24
+++ libvirt/include/libvirt/libvirt.h.in	8 Mar 2007 00:46:35 -0000
@@ -231,6 +231,8 @@ int			virConnectClose		(virConnectPtr co
 const char *		virConnectGetType	(virConnectPtr conn);
 int			virConnectGetVersion	(virConnectPtr conn,
 						 unsigned long *hvVer);
+int			virConnectGetMaxVcpus	(virConnectPtr conn,
+						 const char *type);
 int			virNodeGetInfo		(virConnectPtr conn,
 						 virNodeInfoPtr info);
 
@@ -310,6 +312,8 @@ int			virDomainSetMaxMemory	(virDomainPt
 						 unsigned long memory);
 int			virDomainSetMemory	(virDomainPtr domain,
 						 unsigned long memory);
+int			virDomainGetMaxVcpus	(virDomainPtr domain);
+
 /*
  * XML domain description
  */
Index: libvirt/src/driver.h
===================================================================
RCS file: /data/cvs/libvirt/src/driver.h,v
retrieving revision 1.22
diff -u -p -r1.22 driver.h
--- libvirt/src/driver.h	6 Mar 2007 21:55:44 -0000	1.22
+++ libvirt/src/driver.h	8 Mar 2007 00:46:35 -0000
@@ -44,6 +44,8 @@ typedef int
 	(*virDrvGetVersion)		(virConnectPtr conn,
 					 unsigned long *hvVer);
 typedef int
+	(*virDrvGetMaxVcpus)		(virConnectPtr conn);
+typedef int
 	(*virDrvNodeGetInfo)		(virConnectPtr conn,
 					 virNodeInfoPtr info);
 typedef int
@@ -129,6 +131,8 @@ typedef int
 					 unsigned char *cpumaps,
 					 int maplen);
 typedef int
+	(*virDrvDomainGetMaxVcpus)	(virDomainPtr domain);
+typedef int
 	(*virDrvDomainAttachDevice)	(virDomainPtr domain,
 					 char *xml);
 typedef int
@@ -158,6 +162,7 @@ struct _virDriver {
 	virDrvClose			close;
 	virDrvGetType			type;
 	virDrvGetVersion		version;
+	virDrvGetMaxVcpus		getMaxVcpus;
 	virDrvNodeGetInfo		nodeGetInfo;
 	virDrvListDomains		listDomains;
 	virDrvNumOfDomains		numOfDomains;
@@ -181,6 +186,7 @@ struct _virDriver {
 	virDrvDomainSetVcpus		domainSetVcpus;
 	virDrvDomainPinVcpu		domainPinVcpu;
 	virDrvDomainGetVcpus		domainGetVcpus;
+	virDrvDomainGetMaxVcpus		domainGetMaxVcpus;
 	virDrvDomainDumpXML		domainDumpXML;
 	virDrvListDefinedDomains	listDefinedDomains;
 	virDrvNumOfDefinedDomains	numOfDefinedDomains;
Index: libvirt/src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.59
diff -u -p -r1.59 libvirt.c
--- libvirt/src/libvirt.c	6 Mar 2007 21:55:44 -0000	1.59
+++ libvirt/src/libvirt.c	8 Mar 2007 00:46:35 -0000
@@ -523,6 +523,44 @@ virConnectGetVersion(virConnectPtr conn,
 }
 
 /**
+ * virConnectGetMaxVcpus:
+ * @conn: pointer to the hypervisor connection
+ * @type: value of the 'type' attribute in the <domain> element
+ *
+ * Returns the maximum number of virtual CPUs supported for a guest VM of a
+ * specific type. The 'type' parameter here corresponds to the 'type'
+ * attribute in the <domain> element of the XML.
+ *
+ * Returns the maximum of virtual CPU or -1 in case of error.
+ */
+int
+virConnectGetMaxVcpus(virConnectPtr conn,
+                      const char *type)
+{
+    int ret = -1;
+    int i;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (type == NULL)
+        type = "Xen";
+    for (i = 0;i < MAX_DRIVERS;i++) {
+        if ((virDriverTab[i] != NULL) &&
+           (!strcmp(virDriverTab[i]->name, type))) {
+            ret = conn->drivers[i]->getMaxVcpus(conn);
+            if (ret >= 0)
+                return(ret);
+        }
+    }
+
+    return (-1);
+
+}
+
+/**
  * virConnectListDomains:
  * @conn: pointer to the hypervisor connection
  * @ids: array to collect the list of IDs of active domains
@@ -2110,6 +2148,44 @@ virDomainGetVcpus(virDomainPtr domain, v
 }
 
 /**
+ * virDomainGetMaxVcpus:
+ * @domain: pointer to domain object
+ * 
+ *  Returns the maximum number of virtual CPUs supported for
+ *  the guest VM. If the guest is inactive, this is basically
+ *  the same as virConnectGetMaxVcpus. If the guest is running
+ *  this will reflect the maximum number of virtual CPUs the
+ *  guest was booted with.
+ *
+ * Returns the maximum of virtual CPU or -1 in case of error.
+ */
+int
+virDomainGetMaxVcpus(virDomainPtr domain) {
+    int i;
+    int ret = 0;
+    virConnectPtr conn;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = domain->conn;
+
+    for (i = 0;i < conn->nb_drivers;i++) {
+	if ((conn->drivers[i] != NULL) &&
+	    (conn->drivers[i]->domainGetMaxVcpus != NULL)) {
+	    ret = conn->drivers[i]->domainGetMaxVcpus(domain);
+	    if (ret != 0)
+	        return(ret);
+	}
+    }
+    virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
+    return (-1);
+}
+
+
+/**
  * virDomainAttachDevice:
  * @domain: pointer to domain object
  * @xml: pointer to XML description of one device
Index: libvirt/src/libvirt_sym.version
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt_sym.version,v
retrieving revision 1.16
diff -u -p -r1.16 libvirt_sym.version
--- libvirt/src/libvirt_sym.version	23 Feb 2007 08:51:30 -0000	1.16
+++ libvirt/src/libvirt_sym.version	8 Mar 2007 00:46:36 -0000
@@ -36,6 +36,7 @@
 	virDomainSuspend;
 	virConnectListDefinedDomains;
 	virConnectNumOfDefinedDomains;
+	virConnectGetMaxVcpus;
 	virDomainUndefine;
 	virDomainGetAutostart;
 	virDomainSetAutostart;
@@ -56,6 +57,7 @@
 	virDomainSetVcpus;
 	virDomainPinVcpu;
 	virDomainGetVcpus;
+	virDomainGetMaxVcpus;
 
     virDomainAttachDevice;
     virDomainDetachDevice;
Index: libvirt/src/proxy_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/proxy_internal.c,v
retrieving revision 1.22
diff -u -p -r1.22 proxy_internal.c
--- libvirt/src/proxy_internal.c	23 Feb 2007 08:51:30 -0000	1.22
+++ libvirt/src/proxy_internal.c	8 Mar 2007 00:46:36 -0000
@@ -50,6 +50,7 @@ static virDriver xenProxyDriver = {
     xenProxyClose, /* close */
     NULL, /* type */
     xenProxyGetVersion, /* version */
+    NULL, /* getMaxVcpus */
     xenProxyNodeGetInfo, /* nodeGetInfo */
     xenProxyListDomains, /* listDomains */
     xenProxyNumOfDomains, /* numOfDomains */
@@ -73,6 +74,7 @@ static virDriver xenProxyDriver = {
     NULL, /* domainSetVcpus */
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
     xenProxyDomainDumpXML, /* domainDumpXML */
     NULL, /* listDefinedDomains */
     NULL, /* numOfDefinedDomains */
Index: libvirt/src/qemu_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_internal.c,v
retrieving revision 1.14
diff -u -p -r1.14 qemu_internal.c
--- libvirt/src/qemu_internal.c	6 Mar 2007 21:55:44 -0000	1.14
+++ libvirt/src/qemu_internal.c	8 Mar 2007 00:46:36 -0000
@@ -1167,6 +1167,7 @@ static virDriver qemuDriver = {
     qemuClose, /* close */
     NULL, /* type */
     qemuGetVersion, /* version */
+    NULL, /* getMaxVcpus */
     qemuNodeGetInfo, /* nodeGetInfo */
     qemuListDomains, /* listDomains */
     qemuNumOfDomains, /* numOfDomains */
@@ -1190,6 +1191,7 @@ static virDriver qemuDriver = {
     NULL, /* domainSetVcpus */
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
     qemuDomainDumpXML, /* domainDumpXML */
     qemuListDefinedDomains, /* listDomains */
     qemuNumOfDefinedDomains, /* numOfDomains */
Index: libvirt/src/test.c
===================================================================
RCS file: /data/cvs/libvirt/src/test.c,v
retrieving revision 1.21
diff -u -p -r1.21 test.c
--- libvirt/src/test.c	6 Mar 2007 21:55:44 -0000	1.21
+++ libvirt/src/test.c	8 Mar 2007 00:46:36 -0000
@@ -94,6 +94,7 @@ static virDriver testDriver = {
     testClose, /* close */
     NULL, /* type */
     testGetVersion, /* version */
+    NULL, /* getMaxVcpus */
     testNodeGetInfo, /* nodeGetInfo */
     testListDomains, /* listDomains */
     testNumOfDomains, /* numOfDomains */
@@ -117,6 +118,7 @@ static virDriver testDriver = {
     testSetVcpus, /* domainSetVcpus */
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
     testDomainDumpXML, /* domainDumpXML */
     testListDefinedDomains, /* listDefinedDomains */
     testNumOfDefinedDomains, /* numOfDefinedDomains */
Index: libvirt/src/virsh.c
===================================================================
RCS file: /data/cvs/libvirt/src/virsh.c,v
retrieving revision 1.59
diff -u -p -r1.59 virsh.c
--- libvirt/src/virsh.c	6 Mar 2007 21:55:44 -0000	1.59
+++ libvirt/src/virsh.c	8 Mar 2007 00:46:37 -0000
@@ -1383,6 +1383,7 @@ cmdSetvcpus(vshControl * ctl, vshCmd * c
 {
     virDomainPtr dom;
     int count;
+    int maxcpu;
     int ret = TRUE;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
@@ -1397,6 +1398,18 @@ cmdSetvcpus(vshControl * ctl, vshCmd * c
         return FALSE;
     }
 
+    maxcpu = virDomainGetMaxVcpus(dom);
+    if (!maxcpu) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    if (count > maxcpu) {
+        vshError(ctl, FALSE, _("Too many virtual CPU's."));
+        virDomainFree(dom);
+        return FALSE;
+    }
+
     if (virDomainSetVcpus(dom, count) != 0) {
         ret = FALSE;
     }
Index: libvirt/src/xen_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_internal.c,v
retrieving revision 1.59
diff -u -p -r1.59 xen_internal.c
--- libvirt/src/xen_internal.c	6 Mar 2007 21:55:44 -0000	1.59
+++ libvirt/src/xen_internal.c	8 Mar 2007 00:46:37 -0000
@@ -190,6 +190,11 @@ typedef union xen_getdomaininfolist xen_
      dominfo.v0.nr_online_vcpus :               \
      dominfo.v2.nr_online_vcpus)
 
+#define XEN_GETDOMAININFO_MAXCPUID(dominfo)  \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.max_vcpu_id :                   \
+     dominfo.v2.max_vcpu_id)
+
 #define XEN_GETDOMAININFO_FLAGS(dominfo)        \
     (hypervisor_version < 2 ?                   \
      dominfo.v0.flags :                         \
@@ -423,6 +428,7 @@ static virDriver xenHypervisorDriver = {
     xenHypervisorClose, /* close */
     xenHypervisorGetType, /* type */
     xenHypervisorGetVersion, /* version */
+    xenHypervisorNumOfMaxVcpus, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     xenHypervisorListDomains, /* listDomains */
     xenHypervisorNumOfDomains, /* numOfDomains */
@@ -446,6 +452,7 @@ static virDriver xenHypervisorDriver = {
     xenHypervisorSetVcpus, /* domainSetVcpus */
     xenHypervisorPinVcpu, /* domainPinVcpu */
     xenHypervisorGetVcpus, /* domainGetVcpus */
+    xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
     NULL, /* domainDumpXML */
     NULL, /* listDefinedDomains */
     NULL, /* numOfDefinedDomains */
@@ -1448,6 +1455,20 @@ xenHypervisorListDomains(virConnectPtr c
 }
 
 /**
+ * xenHypervisorNumOfMaxVcpus:
+ *
+ * Returns the maximum of CPU defined by Xen.
+ */
+int
+xenHypervisorNumOfMaxVcpus(virConnectPtr conn)
+{
+    if ((conn == NULL) || (conn->handle < 0))
+        return (-1);
+
+    return MAX_VIRT_CPUS;
+}
+
+/**
  * xenHypervisorGetDomMaxMemory:
  * @conn: connection data
  * @id: domain id
@@ -1824,6 +1845,41 @@ xenHypervisorGetVcpus(virDomainPtr domai
 }
 #endif
 
+/**
+ * xenHypervisorGetVcpuMax:
+ *
+ *  Returns the maximum number of virtual CPUs supported for
+ *  the guest VM. If the guest is inactive, this is the maximum
+ *  of CPU defined by Xen. If the guest is running this reflect
+ *  the maximum number of virtual CPUs the guest was booted with.
+ */
+int
+xenHypervisorGetVcpuMax(virDomainPtr domain)
+{
+    xen_getdomaininfo dominfo;
+    int ret;
+    int maxcpu;
+
+    if ((domain == NULL) || (domain->conn == NULL) ||
+        (domain->conn->handle < 0))
+        return (-1);
+
+    /* inactive domain */
+    if (domain->id < 0) {
+        maxcpu = MAX_VIRT_CPUS;
+    } else {
+        XEN_GETDOMAININFO_CLEAR(dominfo);
+        ret = virXen_getdomaininfo(domain->conn->handle, domain->id,
+                                   &dominfo);
+
+        if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id))
+            return (-1);
+        maxcpu = XEN_GETDOMAININFO_MAXCPUID(dominfo) + 1;
+    }
+
+    return maxcpu;
+}
+
 /*
  * Local variables:
  *  indent-tabs-mode: nil
Index: libvirt/src/xen_internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/xen_internal.h,v
retrieving revision 1.14
diff -u -p -r1.14 xen_internal.h
--- libvirt/src/xen_internal.h	4 Aug 2006 10:41:05 -0000	1.14
+++ libvirt/src/xen_internal.h	8 Mar 2007 00:46:37 -0000
@@ -32,6 +32,7 @@ int	xenHypervisorNumOfDomains	(virConnec
 int	xenHypervisorListDomains	(virConnectPtr conn,
 					 int *ids,
 					 int maxids);
+int	xenHypervisorNumOfMaxVcpus	(virConnectPtr conn);
 int	xenHypervisorDestroyDomain	(virDomainPtr domain);
 int	xenHypervisorResumeDomain	(virDomainPtr domain);
 int	xenHypervisorPauseDomain	(virDomainPtr domain);
@@ -55,6 +56,7 @@ int	xenHypervisorGetVcpus		(virDomainPtr
 					 int maxinfo,
 					 unsigned char *cpumaps,
 					 int maplen);
+int	xenHypervisorGetVcpuMax		(virDomainPtr domain);
 
 #ifdef __cplusplus
 }
Index: libvirt/src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.99
diff -u -p -r1.99 xend_internal.c
--- libvirt/src/xend_internal.c	6 Mar 2007 21:55:44 -0000	1.99
+++ libvirt/src/xend_internal.c	8 Mar 2007 00:46:37 -0000
@@ -66,6 +66,7 @@ static virDriver xenDaemonDriver = {
     xenDaemonClose, /* close */
     xenDaemonGetType, /* type */
     xenDaemonGetVersion, /* version */
+    NULL, /* getMaxVcpus */
     xenDaemonNodeGetInfo, /* nodeGetInfo */
     xenDaemonListDomains, /* listDomains */
     xenDaemonNumOfDomains, /* numOfDomains */
@@ -89,6 +90,7 @@ static virDriver xenDaemonDriver = {
     xenDaemonDomainSetVcpus, /* domainSetVcpus */
     xenDaemonDomainPinVcpu, /* domainPinVcpu */
     xenDaemonDomainGetVcpus, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
     xenDaemonDomainDumpXML, /* domainDumpXML */
     xenDaemonListDefinedDomains, /* listDefinedDomains */
     xenDaemonNumOfDefinedDomains, /* numOfDefinedDomains */
Index: libvirt/src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.16
diff -u -p -r1.16 xm_internal.c
--- libvirt/src/xm_internal.c	6 Mar 2007 21:55:44 -0000	1.16
+++ libvirt/src/xm_internal.c	8 Mar 2007 00:46:38 -0000
@@ -75,6 +75,7 @@ static virDriver xenXMDriver = {
     xenXMClose, /* close */
     xenXMGetType, /* type */
     NULL, /* version */
+    NULL, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     NULL, /* listDomains */
     NULL, /* numOfDomains */
@@ -98,6 +99,7 @@ static virDriver xenXMDriver = {
     xenXMDomainSetVcpus, /* domainSetVcpus */
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
     xenXMDomainDumpXML, /* domainDumpXML */
     xenXMListDefinedDomains, /* listDefinedDomains */
     xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
Index: libvirt/src/xs_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xs_internal.c,v
retrieving revision 1.32
diff -u -p -r1.32 xs_internal.c
--- libvirt/src/xs_internal.c	23 Feb 2007 08:51:30 -0000	1.32
+++ libvirt/src/xs_internal.c	8 Mar 2007 00:46:38 -0000
@@ -44,6 +44,7 @@ static virDriver xenStoreDriver = {
     xenStoreClose, /* close */
     NULL, /* type */
     NULL, /* version */
+    NULL, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     xenStoreListDomains, /* listDomains */
     NULL, /* numOfDomains */
@@ -67,6 +68,7 @@ static virDriver xenStoreDriver = {
     NULL, /* domainSetVcpus */
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
     NULL, /* domainDumpXML */
     NULL, /* listDefinedDomains */
     NULL, /* numOfDefinedDomains */
