mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-30 11:25:47 +00:00
conf: introduce support for Fibre Channel VMID
Signed-off-by: Pavel Hrdina <phrdina@redhat.com> Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
parent
9ea9f7dab2
commit
38b5f4faab
@ -1221,6 +1221,27 @@ Resource partitions are currently supported by the QEMU and LXC drivers, which
|
|||||||
map partition paths to cgroups directories, in all mounted controllers.
|
map partition paths to cgroups directories, in all mounted controllers.
|
||||||
:since:`Since 1.0.5`
|
:since:`Since 1.0.5`
|
||||||
|
|
||||||
|
Fibre Channel VMID
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The FC SAN can provide various QoS levels and access control depending on the
|
||||||
|
VMID. It can also collect telemetry data at per-VM level which can be used
|
||||||
|
to enhance the IO performance of the VM. This can be configured by using
|
||||||
|
the ``appid`` attribute of ``fibrechannel`` element. The attribute contains
|
||||||
|
single string (max 128 bytes) and it is used by kernel to create VMID.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
...
|
||||||
|
<resource>
|
||||||
|
<fibrechannel appid='userProvidedID'/>
|
||||||
|
</resource>
|
||||||
|
...
|
||||||
|
|
||||||
|
Using this feature requires Fibre Channel capable HW, kernel compiled with
|
||||||
|
option ``CONFIG_BLK_CGROUP_FC_APPID`` and ``nvme_fc`` kernel module loaded.
|
||||||
|
:since:`Since 7.7.0`
|
||||||
|
|
||||||
:anchor:`<a id="elementsCPU"/>`
|
:anchor:`<a id="elementsCPU"/>`
|
||||||
|
|
||||||
CPU model and topology
|
CPU model and topology
|
||||||
|
@ -576,6 +576,17 @@
|
|||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name="fibrechannel">
|
||||||
|
<element name="fibrechannel">
|
||||||
|
<attribute name="appid">
|
||||||
|
<data type="string">
|
||||||
|
<!-- All printable characters -->
|
||||||
|
<param name="pattern">[ -~]{1,128}</param>
|
||||||
|
</data>
|
||||||
|
</attribute>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The Identifiers can be:
|
The Identifiers can be:
|
||||||
- an optional id attribute with a number on the domain element
|
- an optional id attribute with a number on the domain element
|
||||||
@ -1177,6 +1188,9 @@
|
|||||||
<ref name="absFilePath"/>
|
<ref name="absFilePath"/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="fibrechannel"/>
|
||||||
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
@ -3446,6 +3446,7 @@ virDomainResourceDefFree(virDomainResourceDef *resource)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
g_free(resource->partition);
|
g_free(resource->partition);
|
||||||
|
g_free(resource->appid);
|
||||||
g_free(resource);
|
g_free(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17285,16 +17286,19 @@ virDomainResourceDefParse(xmlNodePtr node,
|
|||||||
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
||||||
virDomainResourceDef *def = NULL;
|
virDomainResourceDef *def = NULL;
|
||||||
char *partition = NULL;
|
char *partition = NULL;
|
||||||
|
char *appid = NULL;
|
||||||
|
|
||||||
ctxt->node = node;
|
ctxt->node = node;
|
||||||
|
|
||||||
partition = virXPathString("string(./partition)", ctxt);
|
partition = virXPathString("string(./partition)", ctxt);
|
||||||
|
appid = virXPathString("string(./fibrechannel/@appid)", ctxt);
|
||||||
|
|
||||||
if (!partition)
|
if (!partition && !appid)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
def = g_new0(virDomainResourceDef, 1);
|
def = g_new0(virDomainResourceDef, 1);
|
||||||
def->partition = partition;
|
def->partition = partition;
|
||||||
|
def->appid = appid;
|
||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
@ -26769,6 +26773,9 @@ virDomainResourceDefFormat(virBuffer *buf,
|
|||||||
if (def->partition)
|
if (def->partition)
|
||||||
virBufferEscapeString(&childBuf, "<partition>%s</partition>\n", def->partition);
|
virBufferEscapeString(&childBuf, "<partition>%s</partition>\n", def->partition);
|
||||||
|
|
||||||
|
if (def->appid)
|
||||||
|
virBufferEscapeString(&childBuf, "<fibrechannel appid='%s'/>\n", def->appid);
|
||||||
|
|
||||||
virXMLFormatElement(buf, "resource", NULL, &childBuf);
|
virXMLFormatElement(buf, "resource", NULL, &childBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2538,6 +2538,7 @@ void virBlkioDeviceArrayClear(virBlkioDevice *deviceWeights,
|
|||||||
|
|
||||||
struct _virDomainResourceDef {
|
struct _virDomainResourceDef {
|
||||||
char *partition;
|
char *partition;
|
||||||
|
char *appid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _virDomainHugePage {
|
struct _virDomainHugePage {
|
||||||
|
@ -55,6 +55,37 @@ virDomainDefBootValidate(const virDomainDef *def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define APPID_LEN_MIN 1
|
||||||
|
#define APPID_LEN_MAX 128
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainDefResourceValidate(const virDomainDef *def)
|
||||||
|
{
|
||||||
|
if (!def->resource)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (def->resource->appid) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!virStringIsPrintable(def->resource->appid)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Fibre Channel 'appid' is not a printable string"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(def->resource->appid);
|
||||||
|
if (len < APPID_LEN_MIN || len > APPID_LEN_MAX) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("Fibre Channel 'appid' string length must be between [%d, %d]"),
|
||||||
|
APPID_LEN_MIN, APPID_LEN_MAX);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainDefVideoValidate(const virDomainDef *def)
|
virDomainDefVideoValidate(const virDomainDef *def)
|
||||||
{
|
{
|
||||||
@ -1538,6 +1569,9 @@ static int
|
|||||||
virDomainDefValidateInternal(const virDomainDef *def,
|
virDomainDefValidateInternal(const virDomainDef *def,
|
||||||
virDomainXMLOption *xmlopt)
|
virDomainXMLOption *xmlopt)
|
||||||
{
|
{
|
||||||
|
if (virDomainDefResourceValidate(def) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (virDomainDefDuplicateDiskInfoValidate(def) < 0)
|
if (virDomainDefDuplicateDiskInfoValidate(def) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
21
tests/genericxml2xmlindata/fibrechannel-appid.xml
Normal file
21
tests/genericxml2xmlindata/fibrechannel-appid.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory unit='KiB'>219100</memory>
|
||||||
|
<currentMemory unit='KiB'>219100</currentMemory>
|
||||||
|
<vcpu placement='static'>4</vcpu>
|
||||||
|
<resource>
|
||||||
|
<fibrechannel appid='someapp:c7a5fdbd-edaf-9455-926a-d65c16db1809'/>
|
||||||
|
</resource>
|
||||||
|
<os>
|
||||||
|
<type arch='x86_64' machine='q35'>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-system-x86_64</emulator>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -225,6 +225,8 @@ mymain(void)
|
|||||||
DO_TEST_DIFFERENT("cputune");
|
DO_TEST_DIFFERENT("cputune");
|
||||||
DO_TEST("device-backenddomain");
|
DO_TEST("device-backenddomain");
|
||||||
|
|
||||||
|
DO_TEST("fibrechannel-appid");
|
||||||
|
|
||||||
#define DO_TEST_BACKUP_FULL(name, intrnl) \
|
#define DO_TEST_BACKUP_FULL(name, intrnl) \
|
||||||
do { \
|
do { \
|
||||||
const struct testCompareBackupXMLData data = { .testname = name, \
|
const struct testCompareBackupXMLData data = { .testname = name, \
|
||||||
|
Loading…
Reference in New Issue
Block a user