mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-25 10:03:49 +03:00
xml: allow scaled memory on input
Output is still in kibibytes, but input can now be in different scales for ease of typing. * src/conf/domain_conf.c (virDomainParseMemory): New helper. (virDomainDefParseXML): Use it when parsing. * docs/schemas/domaincommon.rng: Expand XML; rename memoryKBElement to memoryElement and update callers. * docs/formatdomain.html.in (elementsMemoryAllocation): Document scaling. * tests/qemuxml2argvdata/qemuxml2argv-memtune.xml: Adjust test. * tests/qemuxml2xmltest.c: Likewise. * tests/qemuxml2xmloutdata/qemuxml2xmlout-memtune.xml: New file.
This commit is contained in:
parent
4888f0fb56
commit
2e22f23bde
@ -415,8 +415,8 @@
|
|||||||
<pre>
|
<pre>
|
||||||
<domain>
|
<domain>
|
||||||
...
|
...
|
||||||
<memory>524288</memory>
|
<memory unit='KiB'>524288</memory>
|
||||||
<currentMemory>524288</currentMemory>
|
<currentMemory unit='KiB'>524288</currentMemory>
|
||||||
...
|
...
|
||||||
</domain>
|
</domain>
|
||||||
</pre>
|
</pre>
|
||||||
@ -424,12 +424,31 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><code>memory</code></dt>
|
<dt><code>memory</code></dt>
|
||||||
<dd>The maximum allocation of memory for the guest at boot time.
|
<dd>The maximum allocation of memory for the guest at boot time.
|
||||||
The units for this value are kibibytes (i.e. blocks of 1024 bytes)</dd>
|
The units for this value are determined by the optional
|
||||||
|
atttribute <code>unit</code>, which defaults to "KiB"
|
||||||
|
(kibibytes, 2<sup>10</sup> or blocks of 1024 bytes). Valid
|
||||||
|
units are "b" or "bytes" for bytes, "KB" for kilobytes
|
||||||
|
(10<sup>3</sup> or 1,000 bytes), "k" or "KiB" for kibibytes
|
||||||
|
(1024 bytes), "MB" for megabytes (10<sup>6</sup> or 1,000,000
|
||||||
|
bytes), "M" or "MiB" for mebibytes (2<sup>20</sup> or
|
||||||
|
1,048,576 bytes), "GB" for gigabytes (10<sup>9</sup> or
|
||||||
|
1,000,000,000 bytes), "G" or "GiB" for gibibytes
|
||||||
|
(2<sup>30</sup> or 1,073,741,824 bytes), "TB" for terabytes
|
||||||
|
(10<sup>12</sup> or 1,000,000,000,000 bytes), or "T" or "TiB"
|
||||||
|
for tebibytes (2<sup>40</sup> or 1,099,511,627,776 bytes).
|
||||||
|
However, the value will be rounded up to the nearest kibibyte
|
||||||
|
by libvirt, and may be further rounded to the granularity
|
||||||
|
supported by the hypervisor. Some hypervisors also enforce a
|
||||||
|
minimum, such as
|
||||||
|
4000KiB. <span class='since'><code>unit</code> since
|
||||||
|
0.9.11</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
|
||||||
up the guests memory on the fly. If this is omitted, it defaults
|
up the guests memory on the fly. If this is omitted, it defaults
|
||||||
to the same value as the <code>memory</code> element</dd>
|
to the same value as the <code>memory</code> element.
|
||||||
|
The <code>unit</code> attribute behaves the same as
|
||||||
|
for <code>memory</code>.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
@ -460,10 +479,10 @@
|
|||||||
<domain>
|
<domain>
|
||||||
...
|
...
|
||||||
<memtune>
|
<memtune>
|
||||||
<hard_limit>1048576</hard_limit>
|
<hard_limit unit='G'>1</hard_limit>
|
||||||
<soft_limit>131072</soft_limit>
|
<soft_limit unit='M'>128</soft_limit>
|
||||||
<swap_hard_limit>2097152</swap_hard_limit>
|
<swap_hard_limit unit='G'>2</swap_hard_limit>
|
||||||
<min_guarantee>65536</min_guarantee>
|
<min_guarantee unit='bytes'>67108864</min_guarantee>
|
||||||
</memtune>
|
</memtune>
|
||||||
...
|
...
|
||||||
</domain>
|
</domain>
|
||||||
@ -477,7 +496,13 @@
|
|||||||
parameters are applied to the QEMU process as a whole. Thus, when
|
parameters are applied to the QEMU process as a whole. Thus, when
|
||||||
counting them, one needs to add up guest RAM, guest video RAM, and
|
counting them, one needs to add up guest RAM, guest video RAM, and
|
||||||
some memory overhead of QEMU itself. The last piece is hard to
|
some memory overhead of QEMU itself. The last piece is hard to
|
||||||
determine so one needs guess and try.</dd>
|
determine so one needs guess and try. For each tunable, it
|
||||||
|
is possible to designate which unit the number is in on
|
||||||
|
input, using the same values as
|
||||||
|
for <code><memory></code>. For backwards
|
||||||
|
compatibility, output is always in
|
||||||
|
KiB. <span class='since'><code>unit</code>
|
||||||
|
since 0.9.11</span></dd>
|
||||||
<dt><code>hard_limit</code></dt>
|
<dt><code>hard_limit</code></dt>
|
||||||
<dd> The optional <code>hard_limit</code> element is the maximum memory
|
<dd> The optional <code>hard_limit</code> element is the maximum memory
|
||||||
the guest can use. The units for this value are kibibytes (i.e. blocks
|
the guest can use. The units for this value are kibibytes (i.e. blocks
|
||||||
|
@ -412,11 +412,11 @@
|
|||||||
<define name="resources">
|
<define name="resources">
|
||||||
<interleave>
|
<interleave>
|
||||||
<element name="memory">
|
<element name="memory">
|
||||||
<ref name='memoryKBElement'/>
|
<ref name='scaledInteger'/>
|
||||||
</element>
|
</element>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="currentMemory">
|
<element name="currentMemory">
|
||||||
<ref name='memoryKBElement'/>
|
<ref name='scaledInteger'/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
@ -461,25 +461,25 @@
|
|||||||
<!-- Maximum memory the VM can use -->
|
<!-- Maximum memory the VM can use -->
|
||||||
<optional>
|
<optional>
|
||||||
<element name="hard_limit">
|
<element name="hard_limit">
|
||||||
<ref name='memoryKBElement'/>
|
<ref name='scaledInteger'/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
<!-- Minimum memory ascertained for the VM during contention -->
|
<!-- Minimum memory ascertained for the VM during contention -->
|
||||||
<optional>
|
<optional>
|
||||||
<element name="soft_limit">
|
<element name="soft_limit">
|
||||||
<ref name='memoryKBElement'/>
|
<ref name='scaledInteger'/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
<!-- Minimum amount of memory required to start the VM -->
|
<!-- Minimum amount of memory required to start the VM -->
|
||||||
<optional>
|
<optional>
|
||||||
<element name="min_guarantee">
|
<element name="min_guarantee">
|
||||||
<ref name='memoryKBElement'/>
|
<ref name='scaledInteger'/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
<!-- Maximum swap area the VM can use -->
|
<!-- Maximum swap area the VM can use -->
|
||||||
<optional>
|
<optional>
|
||||||
<element name="swap_hard_limit">
|
<element name="swap_hard_limit">
|
||||||
<ref name='memoryKBElement'/>
|
<ref name='scaledInteger'/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
@ -3132,17 +3132,6 @@
|
|||||||
<param name="pattern">[0-9]+</param>
|
<param name="pattern">[0-9]+</param>
|
||||||
</data>
|
</data>
|
||||||
</define>
|
</define>
|
||||||
<!-- Memory as an element, with optional unit attribute -->
|
|
||||||
<define name='memoryKBElement'>
|
|
||||||
<optional>
|
|
||||||
<attribute name='unit'>
|
|
||||||
<value>KiB</value>
|
|
||||||
</attribute>
|
|
||||||
</optional>
|
|
||||||
<data type='unsignedInt'>
|
|
||||||
<param name='pattern'>[0-9]+</param>
|
|
||||||
</data>
|
|
||||||
</define>
|
|
||||||
<define name="domainName">
|
<define name="domainName">
|
||||||
<data type="string">
|
<data type="string">
|
||||||
<!-- Use literal newline instead of \n for bug in libxml2 2.7.6 -->
|
<!-- Use literal newline instead of \n for bug in libxml2 2.7.6 -->
|
||||||
|
@ -7491,6 +7491,60 @@ static int virDomainDefMaybeAddController(virDomainDefPtr def,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse a memory element located at XPATH within CTXT, and store the
|
||||||
|
* result into MEM. If REQUIRED, then the value must exist;
|
||||||
|
* otherwise, the value is optional. The value is in blocks of 1024.
|
||||||
|
* Return 0 on success, -1 on failure after issuing error. */
|
||||||
|
static int
|
||||||
|
virDomainParseMemory(const char *xpath, xmlXPathContextPtr ctxt,
|
||||||
|
unsigned long long *mem, bool required)
|
||||||
|
{
|
||||||
|
char *xpath_full = NULL;
|
||||||
|
char *unit = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
unsigned long long bytes;
|
||||||
|
unsigned long long max;
|
||||||
|
|
||||||
|
*mem = 0;
|
||||||
|
if (virAsprintf(&xpath_full, "string(%s)", xpath) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (virXPathULongLong(xpath_full, ctxt, &bytes) < 0) {
|
||||||
|
if (required)
|
||||||
|
virDomainReportError(VIR_ERR_XML_ERROR,
|
||||||
|
"%s", _("missing memory element"));
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
VIR_FREE(xpath_full);
|
||||||
|
|
||||||
|
if (virAsprintf(&xpath_full, "string(%s/@unit)", xpath) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
unit = virXPathString(xpath_full, ctxt);
|
||||||
|
/* On 32-bit machines, our bound is 0xffffffff * KiB. On 64-bit
|
||||||
|
* machines, our bound is off_t (2^63). */
|
||||||
|
if (sizeof(unsigned long) < sizeof(long long))
|
||||||
|
max = 1024ull * ULONG_MAX;
|
||||||
|
else
|
||||||
|
max = LLONG_MAX;
|
||||||
|
if (virScaleInteger(&bytes, unit, 1024, max) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Yes, we really do use kibibytes for our internal sizing. */
|
||||||
|
*mem = VIR_DIV_UP(bytes, 1024);
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(xpath_full);
|
||||||
|
VIR_FREE(unit);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
||||||
xmlDocPtr xml,
|
xmlDocPtr xml,
|
||||||
xmlNodePtr root,
|
xmlNodePtr root,
|
||||||
@ -7614,22 +7668,21 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Extract domain memory */
|
/* Extract domain memory */
|
||||||
if (virXPathULongLong("string(./memory[1])", ctxt,
|
if (virDomainParseMemory("./memory[1]", ctxt,
|
||||||
&def->mem.max_balloon) < 0) {
|
&def->mem.max_balloon, true) < 0)
|
||||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("missing memory element"));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
if (virXPathULongLong("string(./currentMemory[1])", ctxt,
|
if (virDomainParseMemory("./currentMemory[1]", ctxt,
|
||||||
&def->mem.cur_balloon) < 0)
|
&def->mem.cur_balloon, false) < 0)
|
||||||
def->mem.cur_balloon = def->mem.max_balloon;
|
goto error;
|
||||||
|
|
||||||
if (def->mem.cur_balloon > def->mem.max_balloon) {
|
if (def->mem.cur_balloon > def->mem.max_balloon) {
|
||||||
virDomainReportError(VIR_ERR_XML_ERROR,
|
virDomainReportError(VIR_ERR_XML_ERROR,
|
||||||
_("current memory '%lluk' exceeds maximum '%lluk'"),
|
_("current memory '%lluk' exceeds maximum '%lluk'"),
|
||||||
def->mem.cur_balloon, def->mem.max_balloon);
|
def->mem.cur_balloon, def->mem.max_balloon);
|
||||||
goto error;
|
goto error;
|
||||||
|
} else if (def->mem.cur_balloon == 0) {
|
||||||
|
def->mem.cur_balloon = def->mem.max_balloon;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = virXPathNode("./memoryBacking/hugepages", ctxt);
|
node = virXPathNode("./memoryBacking/hugepages", ctxt);
|
||||||
@ -7668,21 +7721,21 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
VIR_FREE(nodes);
|
VIR_FREE(nodes);
|
||||||
|
|
||||||
/* Extract other memory tunables */
|
/* Extract other memory tunables */
|
||||||
if (virXPathULongLong("string(./memtune/hard_limit)", ctxt,
|
if (virDomainParseMemory("./memtune/hard_limit[1]", ctxt,
|
||||||
&def->mem.hard_limit) < 0)
|
&def->mem.hard_limit, false) < 0)
|
||||||
def->mem.hard_limit = 0;
|
goto error;
|
||||||
|
|
||||||
if (virXPathULongLong("string(./memtune/soft_limit[1])", ctxt,
|
if (virDomainParseMemory("./memtune/soft_limit[1]", ctxt,
|
||||||
&def->mem.soft_limit) < 0)
|
&def->mem.soft_limit, false) < 0)
|
||||||
def->mem.soft_limit = 0;
|
goto error;
|
||||||
|
|
||||||
if (virXPathULongLong("string(./memtune/min_guarantee[1])", ctxt,
|
if (virDomainParseMemory("./memtune/min_guarantee[1]", ctxt,
|
||||||
&def->mem.min_guarantee) < 0)
|
&def->mem.min_guarantee, false) < 0)
|
||||||
def->mem.min_guarantee = 0;
|
goto error;
|
||||||
|
|
||||||
if (virXPathULongLong("string(./memtune/swap_hard_limit[1])", ctxt,
|
if (virDomainParseMemory("./memtune/swap_hard_limit[1]", ctxt,
|
||||||
&def->mem.swap_hard_limit) < 0)
|
&def->mem.swap_hard_limit, false) < 0)
|
||||||
def->mem.swap_hard_limit = 0;
|
goto error;
|
||||||
|
|
||||||
n = virXPathULong("string(./vcpu[1])", ctxt, &count);
|
n = virXPathULong("string(./vcpu[1])", ctxt, &count);
|
||||||
if (n == -2) {
|
if (n == -2) {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<domain type='qemu'>
|
<domain type='qemu'>
|
||||||
<name>QEMUGuest1</name>
|
<name>QEMUGuest1</name>
|
||||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
<memory unit='KiB'>219136</memory>
|
<memory unit='MiB'>214</memory>
|
||||||
<currentMemory unit='KiB'>219136</currentMemory>
|
<currentMemory unit='KiB'>219136</currentMemory>
|
||||||
<memtune>
|
<memtune>
|
||||||
<hard_limit unit='KiB'>512000</hard_limit>
|
<hard_limit unit='KiB'>512000</hard_limit>
|
||||||
<soft_limit unit='KiB'>128000</soft_limit>
|
<soft_limit unit='bytes'>131071999</soft_limit>
|
||||||
<swap_hard_limit unit='KiB'>1024000</swap_hard_limit>
|
<swap_hard_limit unit='KB'>1048576</swap_hard_limit>
|
||||||
</memtune>
|
</memtune>
|
||||||
<vcpu>1</vcpu>
|
<vcpu>1</vcpu>
|
||||||
<os>
|
<os>
|
||||||
|
31
tests/qemuxml2xmloutdata/qemuxml2xmlout-memtune.xml
Normal file
31
tests/qemuxml2xmloutdata/qemuxml2xmlout-memtune.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory unit='KiB'>219136</memory>
|
||||||
|
<currentMemory unit='KiB'>219136</currentMemory>
|
||||||
|
<memtune>
|
||||||
|
<hard_limit unit='KiB'>512000</hard_limit>
|
||||||
|
<soft_limit unit='KiB'>128000</soft_limit>
|
||||||
|
<swap_hard_limit unit='KiB'>1024000</swap_hard_limit>
|
||||||
|
</memtune>
|
||||||
|
<vcpu>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>
|
||||||
|
<disk type='block' device='disk'>
|
||||||
|
<source dev='/dev/HostVG/QEMUGuest1'/>
|
||||||
|
<target dev='hda' bus='ide'/>
|
||||||
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||||
|
</disk>
|
||||||
|
<controller type='usb' index='0'/>
|
||||||
|
<controller type='ide' index='0'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -195,7 +195,7 @@ mymain(void)
|
|||||||
DO_TEST("pci-rom");
|
DO_TEST("pci-rom");
|
||||||
|
|
||||||
DO_TEST("encrypted-disk");
|
DO_TEST("encrypted-disk");
|
||||||
DO_TEST("memtune");
|
DO_TEST_DIFFERENT("memtune");
|
||||||
DO_TEST("blkiotune");
|
DO_TEST("blkiotune");
|
||||||
DO_TEST("blkiotune-device");
|
DO_TEST("blkiotune-device");
|
||||||
DO_TEST("cputune");
|
DO_TEST("cputune");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user