Add a XML element that will allow to specify maximum supportable memory
and the count of memory slots to use with memory hotplug.
To avoid possible confusion and misuse of the new element this patch
also explicitly forbids the use of the maxMemory setting in individual
drivers's post parse callbacks. This limitation will be lifted when the
support will be implemented.
---
docs/formatdomain.html.in | 19 +++++++++++
docs/schemas/domaincommon.rng | 8 +++++
src/bhyve/bhyve_domain.c | 4 +++
src/conf/domain_conf.c | 64 ++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 7 ++++
src/libvirt_private.syms | 1 +
src/libxl/libxl_domain.c | 5 +++
src/lxc/lxc_domain.c | 4 +++
src/openvz/openvz_driver.c | 11 +++++--
src/parallels/parallels_driver.c | 6 +++-
src/phyp/phyp_driver.c | 6 +++-
src/qemu/qemu_domain.c | 4 +++
src/uml/uml_driver.c | 6 +++-
src/vbox/vbox_common.c | 6 +++-
src/vmware/vmware_driver.c | 6 +++-
src/vmx/vmx.c | 6 +++-
src/xen/xen_driver.c | 4 +++
src/xenapi/xenapi_driver.c | 6 +++-
tests/domainschemadata/maxMemory.xml | 19 +++++++++++
19 files changed, 183 insertions(+), 9 deletions(-)
create mode 100644 tests/domainschemadata/maxMemory.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f8d5f89..12f7ede 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -664,6 +664,7 @@
<pre>
<domain>
...
+ <maxMemory slots='123'
unit='KiB'>1524288</maxMemory>
<memory unit='KiB'>524288</memory>
<currentMemory unit='KiB'>524288</currentMemory>
...
@@ -697,6 +698,24 @@
<span class='since'><code>unit</code> since
0.9.11</span>,
<span class='since'><code>dumpCore</code> since 0.10.2
(QEMU only)</span></dd>
+ <dt><code>maxMemory</code></dt>
+ <dd>The run time maximum memory allocation of the guest. The initial
+ memory specified by <code><memory></code> can be
increased by
+ hot-plugging of memory to the limit specified by this element.
+
+ The <code>unit</code> attribute behaves the same as for
+ <code>memory</code>.
+
+ The <code>slots</code> attribute specifies the number of slots
+ available for adding memory to the guest. The bounds are hypervisor
+ specific.
+
+ Note that due to alignment of the memory chunks added via memory
+ hotplug the full size allocation specified by this element may be
+ impossible to achieve.
+ <span class='since'>Since 1.2.12</span>
+ </dd>
+
<dt><code>currentMemory</code></dt>
<dd>The actual allocation of memory for the guest. This value can
be less than the maximum allocation, to allow for ballooning
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d467dce..2dbfbec 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -577,6 +577,14 @@
-->
<define name="resources">
<interleave>
+ <optional>
+ <element name="maxMemory">
+ <ref name="scaledInteger"/>
+ <attribute name="slots">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </element>
+ </optional>
<element name="memory">
<ref name='scaledInteger'/>
<optional>
diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index ecb1758..25ef852 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -67,6 +67,10 @@ bhyveDomainDefPostParse(virDomainDefPtr def,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
return -1;
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d562e1a..0cfc638 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -980,6 +980,27 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
}
+/**
+ * virDomainDefCheckUnsupportedMemoryHotplug:
+ * @def: domain definition
+ *
+ * Returns -1 if the domain definition would enable memory hotplug via the
+ * <maxMemory> tunable and reports an error. Otherwise returns 0.
+ */
+int
+virDomainDefCheckUnsupportedMemoryHotplug(virDomainDefPtr def)
+{
+ /* memory hotplug tunables are not supported by this driver */
+ if (def->mem.max_memory > 0 || def->mem.memory_slots > 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("memory hotplug tunables <maxMemory> are not "
+ "supported by this hypervisor driver"));
+ return -1;
+ }
+
+ return 0;
+}
+
static void
virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
@@ -12735,6 +12756,16 @@ virDomainDefParseXML(xmlDocPtr xml,
&def->mem.cur_balloon, false, true) < 0)
goto error;
+ if (virDomainParseMemory("./maxMemory[1]", NULL, ctxt,
+ &def->mem.max_memory, false, false) < 0)
+ goto error;
+
+ if (virXPathUInt("string(./maxMemory[1]/@slots)", ctxt,
&def->mem.memory_slots) == -2) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Failed to parse memory slot count"));
+ goto error;
+ }
+
/* and info about it */
if ((tmp = virXPathString("string(./memory[1]/@dumpCore)", ctxt))
&&
(def->mem.dump_core = virTristateSwitchTypeFromString(tmp)) <= 0) {
@@ -12764,6 +12795,21 @@ virDomainDefParseXML(xmlDocPtr xml,
def->mem.cur_balloon = def->mem.max_balloon;
}
+ if ((def->mem.max_memory || def->mem.memory_slots) &&
+ !(def->mem.max_memory && def->mem.memory_slots)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("both maximum memory size and "
+ "memory slot count must be sepcified"));
+ goto error;
+ }
+
+ if (def->mem.max_memory &&
+ def->mem.max_memory < def->mem.max_balloon) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("maximum memory size must be equal or greater than "
+ "the actual memory size"));
+ goto error;
+ }
if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt,
&nodes)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -15643,6 +15689,18 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
goto error;
}
}
+ if (src->mem.memory_slots != dst->mem.memory_slots) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain memory slots count '%u' doesn't
match source '%u"),
+ dst->mem.memory_slots, src->mem.memory_slots);
+ goto error;
+ }
+ if (src->mem.max_memory != dst->mem.max_memory) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target maximum memory size '%llu' doesn't
match source '%llu'"),
+ dst->mem.max_memory, src->mem.max_memory);
+ goto error;
+ }
if (src->vcpus != dst->vcpus) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -19311,6 +19369,12 @@ virDomainDefFormatInternal(virDomainDefPtr def,
xmlIndentTreeOutput = oldIndentTreeOutput;
}
+ if (def->mem.memory_slots && def->mem.max_memory) {
+ virBufferAsprintf(buf,
+ "<maxMemory slots='%u'
unit='KiB'>%llu</maxMemory>\n",
+ def->mem.memory_slots, def->mem.max_memory);
+ }
+
virBufferAddLit(buf, "<memory");
if (def->mem.dump_core)
virBufferAsprintf(buf, " dumpCore='%s'",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 93f2314..97be518 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2021,6 +2021,10 @@ struct _virDomainMemtune {
virDomainHugePagePtr hugepages;
size_t nhugepages;
+ /* maximum supported memory for a guest, for hotplugging */
+ unsigned long long max_memory; /* in kibibytes */
+ unsigned int memory_slots; /* maximum count of RAM memory slots */
+
bool nosharepages;
bool locked;
int dump_core; /* enum virTristateSwitch */
@@ -2312,6 +2316,9 @@ virDomainObjPtr virDomainObjListFindByName(virDomainObjListPtr
doms,
bool virDomainObjTaint(virDomainObjPtr obj,
virDomainTaintFlags taint);
+
+int virDomainDefCheckUnsupportedMemoryHotplug(virDomainDefPtr def);
+
void virDomainPanicDefFree(virDomainPanicDefPtr panic);
void virDomainResourceDefFree(virDomainResourceDefPtr resource);
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cf5ccaf..4bad7c6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -186,6 +186,7 @@ virDomainCpuPlacementModeTypeFromString;
virDomainCpuPlacementModeTypeToString;
virDomainDefAddImplicitControllers;
virDomainDefCheckABIStability;
+virDomainDefCheckUnsupportedMemoryHotplug;
virDomainDefClearCCWAddresses;
virDomainDefClearDeviceAliases;
virDomainDefClearPCIAddresses;
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 856cfb4..01fb79c 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -564,6 +564,11 @@ libxlDomainDefPostParse(virDomainDefPtr def,
def->nconsoles = 1;
def->consoles[0] = chrdef;
}
+
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c
index 55f5b49..1367b0c 100644
--- a/src/lxc/lxc_domain.c
+++ b/src/lxc/lxc_domain.c
@@ -94,6 +94,10 @@ virLXCDomainDefPostParse(virDomainDefPtr def,
!(def->emulator = virDomainDefGetDefaultEmulator(def, caps)))
return -1;
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 556f626..796044a 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -96,8 +96,15 @@ openvzDomainDefPostParse(virDomainDefPtr def,
void *opaque ATTRIBUTE_UNUSED)
{
/* fill the init path */
- if (STREQ(def->os.type, "exe") && !def->os.init)
- return VIR_STRDUP(def->os.init, "/sbin/init") < 0 ? -1 : 0;
+ if (STREQ(def->os.type, "exe") && !def->os.init) {
+ if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
+ return -1;
+ }
+
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index b569160..334081c 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -154,10 +154,14 @@ parallelsConnectGetCapabilities(virConnectPtr conn)
}
static int
-parallelsDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+parallelsDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 6c5a91e..3703eab 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -1094,10 +1094,14 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
static int
-phypDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+phypDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 99c46d4..085bc81 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1040,6 +1040,10 @@ qemuDomainDefPostParse(virDomainDefPtr def,
VIR_DOMAIN_INPUT_BUS_USB) < 0)
return -1;
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 6ca038a..546ad48 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -444,10 +444,14 @@ umlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
static int
-umlDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+umlDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index bd3f50c..f6ad6de 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -249,10 +249,14 @@ static char *vboxGenerateMediumName(PRUint32 storageBus,
}
static int
-vboxDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+vboxDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
index 2d7ba04..f0a0b5b 100644
--- a/src/vmware/vmware_driver.c
+++ b/src/vmware/vmware_driver.c
@@ -83,10 +83,14 @@ vmwareDataFreeFunc(void *data)
}
static int
-vmwareDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+vmwareDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index 2a794c7..0262f75 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -524,10 +524,14 @@ VIR_ENUM_IMPL(virVMXControllerModelSCSI,
VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
* Helpers
*/
static int
-vmxDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+vmxDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 5e6ef68..f603477 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -390,6 +390,10 @@ xenDomainDefPostParse(virDomainDefPtr def,
def->memballoon = memballoon;
}
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 0902f9a..3b44a46 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -70,10 +70,14 @@ xenapiDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
static int
-xenapiDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+xenapiDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ /* memory hotplug tunables are not supported by this driver */
+ if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/tests/domainschemadata/maxMemory.xml b/tests/domainschemadata/maxMemory.xml
new file mode 100644
index 0000000..df2e3d8
--- /dev/null
+++ b/tests/domainschemadata/maxMemory.xml
@@ -0,0 +1,19 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <maxMemory slots='9' unit='KiB'>1233456789</maxMemory>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ </devices>
+</domain>
--
2.2.2