conf: Add support for parsing and formatting max memory and slot count

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 is implemented.
This commit is contained in:
Peter Krempa 2014-08-11 17:40:32 +02:00
parent 19e85d8454
commit bffb9163a1
19 changed files with 186 additions and 9 deletions

View File

@ -675,6 +675,7 @@
<pre> <pre>
&lt;domain&gt; &lt;domain&gt;
... ...
&lt;maxMemory slots='16' unit='KiB'&gt;1524288&lt;/maxMemory&gt;
&lt;memory unit='KiB'&gt;524288&lt;/memory&gt; &lt;memory unit='KiB'&gt;524288&lt;/memory&gt;
&lt;currentMemory unit='KiB'&gt;524288&lt;/currentMemory&gt; &lt;currentMemory unit='KiB'&gt;524288&lt;/currentMemory&gt;
... ...
@ -708,6 +709,25 @@
<span class='since'><code>unit</code> since 0.9.11</span>, <span class='since'><code>unit</code> since 0.9.11</span>,
<span class='since'><code>dumpCore</code> since 0.10.2 <span class='since'><code>dumpCore</code> since 0.10.2
(QEMU only)</span></dd> (QEMU only)</span></dd>
<dt><code>maxMemory</code></dt>
<dd>The run time maximum memory allocation of the guest. The initial
memory specified by either the <code>&lt;memory&gt;</code> element or
the NUMA cell size configuration 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>&lt;memory&gt;</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.14</span>
</dd>
<dt><code>currentMemory</code></dt> <dt><code>currentMemory</code></dt>
<dd>The actual allocation of memory for the guest. This value can <dd>The actual allocation of memory for the guest. This value can
be less than the maximum allocation, to allow for ballooning be less than the maximum allocation, to allow for ballooning

View File

@ -592,6 +592,14 @@
</optional> </optional>
</element> </element>
</optional> </optional>
<optional>
<element name="maxMemory">
<ref name="scaledInteger"/>
<attribute name="slots">
<ref name="unsignedInt"/>
</attribute>
</element>
</optional>
<optional> <optional>
<element name="currentMemory"> <element name="currentMemory">
<ref name='scaledInteger'/> <ref name='scaledInteger'/>

View File

@ -67,6 +67,10 @@ bhyveDomainDefPostParse(virDomainDefPtr def,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0) VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
return -1; return -1;
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -981,6 +981,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 static void
virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
@ -3238,6 +3259,22 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
def->mem.cur_balloon = virDomainDefGetMemoryActual(def); def->mem.cur_balloon = virDomainDefGetMemoryActual(def);
} }
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 specified"));
return -1;
}
if (def->mem.max_memory &&
def->mem.max_memory < virDomainDefGetMemoryActual(def)) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("maximum memory size must be equal or greater than "
"the actual memory size"));
return -1;
}
/* /*
* Some really crazy backcompat stuff for consoles * Some really crazy backcompat stuff for consoles
* *
@ -13264,6 +13301,16 @@ virDomainDefParseXML(xmlDocPtr xml,
&def->mem.cur_balloon, false, true) < 0) &def->mem.cur_balloon, false, true) < 0)
goto error; 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 */ /* and info about it */
if ((tmp = virXPathString("string(./memory[1]/@dumpCore)", ctxt)) && if ((tmp = virXPathString("string(./memory[1]/@dumpCore)", ctxt)) &&
(def->mem.dump_core = virTristateSwitchTypeFromString(tmp)) <= 0) { (def->mem.dump_core = virTristateSwitchTypeFromString(tmp)) <= 0) {
@ -16190,6 +16237,19 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
if (!virDomainNumaCheckABIStability(src->numa, dst->numa)) if (!virDomainNumaCheckABIStability(src->numa, dst->numa))
goto error; 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) { if (src->vcpus != dst->vcpus) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target domain vCPU count %d does not match source %d"), _("Target domain vCPU count %d does not match source %d"),
@ -19879,6 +19939,12 @@ virDomainDefFormatInternal(virDomainDefPtr def,
xmlIndentTreeOutput = oldIndentTreeOutput; xmlIndentTreeOutput = oldIndentTreeOutput;
} }
if (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"); virBufferAddLit(buf, "<memory");
if (def->mem.dump_core) if (def->mem.dump_core)
virBufferAsprintf(buf, " dumpCore='%s'", virBufferAsprintf(buf, " dumpCore='%s'",

View File

@ -2041,6 +2041,10 @@ struct _virDomainMemtune {
virDomainHugePagePtr hugepages; virDomainHugePagePtr hugepages;
size_t nhugepages; 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 nosharepages;
bool locked; bool locked;
int dump_core; /* enum virTristateSwitch */ int dump_core; /* enum virTristateSwitch */
@ -2336,6 +2340,9 @@ virDomainObjPtr virDomainObjListFindByName(virDomainObjListPtr doms,
bool virDomainObjTaint(virDomainObjPtr obj, bool virDomainObjTaint(virDomainObjPtr obj,
virDomainTaintFlags taint); virDomainTaintFlags taint);
int virDomainDefCheckUnsupportedMemoryHotplug(virDomainDefPtr def);
void virDomainPanicDefFree(virDomainPanicDefPtr panic); void virDomainPanicDefFree(virDomainPanicDefPtr panic);
void virDomainResourceDefFree(virDomainResourceDefPtr resource); void virDomainResourceDefFree(virDomainResourceDefPtr resource);
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def);

View File

@ -187,6 +187,7 @@ virDomainCpuPlacementModeTypeFromString;
virDomainCpuPlacementModeTypeToString; virDomainCpuPlacementModeTypeToString;
virDomainDefAddImplicitControllers; virDomainDefAddImplicitControllers;
virDomainDefCheckABIStability; virDomainDefCheckABIStability;
virDomainDefCheckUnsupportedMemoryHotplug;
virDomainDefClearCCWAddresses; virDomainDefClearCCWAddresses;
virDomainDefClearDeviceAliases; virDomainDefClearDeviceAliases;
virDomainDefClearPCIAddresses; virDomainDefClearPCIAddresses;

View File

@ -567,6 +567,11 @@ libxlDomainDefPostParse(virDomainDefPtr def,
def->nconsoles = 1; def->nconsoles = 1;
def->consoles[0] = chrdef; def->consoles[0] = chrdef;
} }
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -94,6 +94,10 @@ virLXCDomainDefPostParse(virDomainDefPtr def,
!(def->emulator = virDomainDefGetDefaultEmulator(def, caps))) !(def->emulator = virDomainDefGetDefaultEmulator(def, caps)))
return -1; return -1;
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -96,8 +96,15 @@ openvzDomainDefPostParse(virDomainDefPtr def,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* fill the init path */ /* fill the init path */
if (STREQ(def->os.type, "exe") && !def->os.init) if (STREQ(def->os.type, "exe") && !def->os.init) {
return VIR_STRDUP(def->os.init, "/sbin/init") < 0 ? -1 : 0; 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; return 0;
} }

View File

@ -161,10 +161,14 @@ parallelsConnectGetCapabilities(virConnectPtr conn)
} }
static int static int
parallelsDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, parallelsDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -1094,10 +1094,14 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
static int static int
phypDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, phypDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -1052,6 +1052,10 @@ qemuDomainDefPostParse(virDomainDefPtr def,
VIR_DOMAIN_INPUT_BUS_USB) < 0) VIR_DOMAIN_INPUT_BUS_USB) < 0)
return -1; return -1;
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -444,10 +444,14 @@ umlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
static int static int
umlDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, umlDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -249,10 +249,14 @@ static char *vboxGenerateMediumName(PRUint32 storageBus,
} }
static int static int
vboxDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, vboxDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -83,10 +83,14 @@ vmwareDataFreeFunc(void *data)
} }
static int static int
vmwareDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, vmwareDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -524,10 +524,14 @@ VIR_ENUM_IMPL(virVMXControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
* Helpers * Helpers
*/ */
static int static int
vmxDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, vmxDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -388,6 +388,10 @@ xenDomainDefPostParse(virDomainDefPtr def,
def->memballoon = memballoon; def->memballoon = memballoon;
} }
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -70,10 +70,14 @@ xenapiDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
static int static int
xenapiDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED, xenapiDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED, virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
/* memory hotplug tunables are not supported by this driver */
if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
return -1;
return 0; return 0;
} }

View File

@ -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>