mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-21 10:52:22 +00:00
qemu: Allow the user to specify vendor and product for disk
QEMU supports setting vendor and product strings for disk since 1.2.0 (only scsi-disk, scsi-hd, scsi-cd support it), this patch exposes it with new XML elements <vendor> and <product> of disk device.
This commit is contained in:
parent
dfa1e1dd53
commit
b718ded39a
@ -1657,6 +1657,18 @@
|
|||||||
of 16 hexadecimal digits.
|
of 16 hexadecimal digits.
|
||||||
<span class='since'>Since 0.10.1</span>
|
<span class='since'>Since 0.10.1</span>
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>vendor</code></dt>
|
||||||
|
<dd>If present, this element specifies the vendor of a virtual hard
|
||||||
|
disk or CD-ROM device. It must not be longer than 8 printable
|
||||||
|
characters.
|
||||||
|
<span class='since'>Since 1.0.1</span>
|
||||||
|
</dd>
|
||||||
|
<dt><code>product</code></dt>
|
||||||
|
<dd>If present, this element specifies the product of a virtual hard
|
||||||
|
disk or CD-ROM device. It must not be longer than 16 printable
|
||||||
|
characters.
|
||||||
|
<span class='since'>Since 1.0.1</span>
|
||||||
|
</dd>
|
||||||
<dt><code>host</code></dt>
|
<dt><code>host</code></dt>
|
||||||
<dd>The <code>host</code> element supports 4 attributes, viz. "name",
|
<dd>The <code>host</code> element supports 4 attributes, viz. "name",
|
||||||
"port", "transport" and "socket", which specify the hostname, the port
|
"port", "transport" and "socket", which specify the hostname, the port
|
||||||
|
@ -905,6 +905,20 @@
|
|||||||
<ref name="wwn"/>
|
<ref name="wwn"/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<element name="vendor">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[x20-x7E]{0,8}</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<element name="product">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[x20-x7E]{0,16}</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
</interleave>
|
</interleave>
|
||||||
</define>
|
</define>
|
||||||
<define name="snapshot">
|
<define name="snapshot">
|
||||||
|
@ -985,6 +985,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
|
|||||||
VIR_FREE(def->mirror);
|
VIR_FREE(def->mirror);
|
||||||
VIR_FREE(def->auth.username);
|
VIR_FREE(def->auth.username);
|
||||||
VIR_FREE(def->wwn);
|
VIR_FREE(def->wwn);
|
||||||
|
VIR_FREE(def->vendor);
|
||||||
|
VIR_FREE(def->product);
|
||||||
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE)
|
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE)
|
||||||
VIR_FREE(def->auth.secret.usage);
|
VIR_FREE(def->auth.secret.usage);
|
||||||
virStorageEncryptionFree(def->encryption);
|
virStorageEncryptionFree(def->encryption);
|
||||||
@ -3505,6 +3507,8 @@ cleanup:
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VENDOR_LEN 8
|
||||||
|
#define PRODUCT_LEN 16
|
||||||
|
|
||||||
/* Parse the XML definition for a disk
|
/* Parse the XML definition for a disk
|
||||||
* @param node XML nodeset to parse for disk definition
|
* @param node XML nodeset to parse for disk definition
|
||||||
@ -3558,6 +3562,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
char *logical_block_size = NULL;
|
char *logical_block_size = NULL;
|
||||||
char *physical_block_size = NULL;
|
char *physical_block_size = NULL;
|
||||||
char *wwn = NULL;
|
char *wwn = NULL;
|
||||||
|
char *vendor = NULL;
|
||||||
|
char *product = NULL;
|
||||||
|
|
||||||
if (VIR_ALLOC(def) < 0) {
|
if (VIR_ALLOC(def) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -3926,6 +3932,36 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
|
|
||||||
if (!virValidateWWN(wwn))
|
if (!virValidateWWN(wwn))
|
||||||
goto error;
|
goto error;
|
||||||
|
} else if (!vendor &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "vendor")) {
|
||||||
|
vendor = (char *)xmlNodeGetContent(cur);
|
||||||
|
|
||||||
|
if (strlen(vendor) > VENDOR_LEN) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("disk vendor is more than 8 characters"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!virStrIsPrint(vendor)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("disk vendor is not printable string"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (!product &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "product")) {
|
||||||
|
product = (char *)xmlNodeGetContent(cur);
|
||||||
|
|
||||||
|
if (strlen(vendor) > PRODUCT_LEN) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("disk product is more than 16 characters"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!virStrIsPrint(product)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("disk product is not printable string"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
|
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
|
||||||
/* boot is parsed as part of virDomainDeviceInfoParseXML */
|
/* boot is parsed as part of virDomainDeviceInfoParseXML */
|
||||||
}
|
}
|
||||||
@ -4222,6 +4258,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
serial = NULL;
|
serial = NULL;
|
||||||
def->wwn = wwn;
|
def->wwn = wwn;
|
||||||
wwn = NULL;
|
wwn = NULL;
|
||||||
|
def->vendor = vendor;
|
||||||
|
vendor = NULL;
|
||||||
|
def->product = product;
|
||||||
|
product = NULL;
|
||||||
|
|
||||||
if (driverType) {
|
if (driverType) {
|
||||||
def->format = virStorageFileFormatTypeFromString(driverType);
|
def->format = virStorageFileFormatTypeFromString(driverType);
|
||||||
@ -4296,6 +4336,8 @@ cleanup:
|
|||||||
VIR_FREE(logical_block_size);
|
VIR_FREE(logical_block_size);
|
||||||
VIR_FREE(physical_block_size);
|
VIR_FREE(physical_block_size);
|
||||||
VIR_FREE(wwn);
|
VIR_FREE(wwn);
|
||||||
|
VIR_FREE(vendor);
|
||||||
|
VIR_FREE(product);
|
||||||
|
|
||||||
ctxt->node = save_ctxt;
|
ctxt->node = save_ctxt;
|
||||||
return def;
|
return def;
|
||||||
@ -12144,6 +12186,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
virBufferAddLit(buf, " <transient/>\n");
|
virBufferAddLit(buf, " <transient/>\n");
|
||||||
virBufferEscapeString(buf, " <serial>%s</serial>\n", def->serial);
|
virBufferEscapeString(buf, " <serial>%s</serial>\n", def->serial);
|
||||||
virBufferEscapeString(buf, " <wwn>%s</wwn>\n", def->wwn);
|
virBufferEscapeString(buf, " <wwn>%s</wwn>\n", def->wwn);
|
||||||
|
virBufferEscapeString(buf, " <vendor>%s</vendor>\n", def->vendor);
|
||||||
|
virBufferEscapeString(buf, " <product>%s</product>\n", def->product);
|
||||||
if (def->encryption) {
|
if (def->encryption) {
|
||||||
virBufferAdjustIndent(buf, 6);
|
virBufferAdjustIndent(buf, 6);
|
||||||
if (virStorageEncryptionFormat(buf, def->encryption) < 0)
|
if (virStorageEncryptionFormat(buf, def->encryption) < 0)
|
||||||
|
@ -602,6 +602,8 @@ struct _virDomainDiskDef {
|
|||||||
|
|
||||||
char *serial;
|
char *serial;
|
||||||
char *wwn;
|
char *wwn;
|
||||||
|
char *vendor;
|
||||||
|
char *product;
|
||||||
int cachemode;
|
int cachemode;
|
||||||
int error_policy; /* enum virDomainDiskErrorPolicy */
|
int error_policy; /* enum virDomainDiskErrorPolicy */
|
||||||
int rerror_policy; /* enum virDomainDiskErrorPolicy */
|
int rerror_policy; /* enum virDomainDiskErrorPolicy */
|
||||||
|
@ -1298,6 +1298,7 @@ virSetUIDGID;
|
|||||||
virSkipSpaces;
|
virSkipSpaces;
|
||||||
virSkipSpacesAndBackslash;
|
virSkipSpacesAndBackslash;
|
||||||
virSkipSpacesBackwards;
|
virSkipSpacesBackwards;
|
||||||
|
virStrIsPrint;
|
||||||
virStrToDouble;
|
virStrToDouble;
|
||||||
virStrToLong_i;
|
virStrToLong_i;
|
||||||
virStrToLong_l;
|
virStrToLong_l;
|
||||||
|
@ -2576,6 +2576,13 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((disk->vendor || disk->product) &&
|
||||||
|
disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Only scsi disk supports vendor and product"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||||
/* make sure that both the bus and the qemu binary support
|
/* make sure that both the bus and the qemu binary support
|
||||||
* type='lun' (SG_IO).
|
* type='lun' (SG_IO).
|
||||||
@ -2603,6 +2610,12 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
|
|||||||
_("Setting wwn is not supported for lun device"));
|
_("Setting wwn is not supported for lun device"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (disk->vendor || disk->product) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Setting vendor or product is not supported "
|
||||||
|
"for lun device"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (disk->bus) {
|
switch (disk->bus) {
|
||||||
@ -2652,6 +2665,17 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Properties wwn, vendor and product were introduced in the
|
||||||
|
* same QEMU release (1.2.0).
|
||||||
|
*/
|
||||||
|
if ((disk->vendor || disk->product) &&
|
||||||
|
!qemuCapsGet(caps, QEMU_CAPS_SCSI_DISK_WWN)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Setting vendor or product for scsi disk is not "
|
||||||
|
"supported by this QEMU"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
controllerModel =
|
controllerModel =
|
||||||
virDomainDiskFindControllerModel(def, disk,
|
virDomainDiskFindControllerModel(def, disk,
|
||||||
VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
|
VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
|
||||||
@ -2797,6 +2821,12 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
|
|||||||
if (disk->wwn)
|
if (disk->wwn)
|
||||||
virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
|
virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
|
||||||
|
|
||||||
|
if (disk->vendor)
|
||||||
|
virBufferAsprintf(&opt, ",vendor=%s", disk->vendor);
|
||||||
|
|
||||||
|
if (disk->product)
|
||||||
|
virBufferAsprintf(&opt, ",product=%s", disk->product);
|
||||||
|
|
||||||
if (virBufferError(&opt)) {
|
if (virBufferError(&opt)) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -3131,3 +3131,15 @@ virValidateWWN(const char *wwn) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
virStrIsPrint(const char *str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; str[i]; i++)
|
||||||
|
if (!c_isprint(str[i]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -280,4 +280,5 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
|
|||||||
|
|
||||||
bool virValidateWWN(const char *wwn);
|
bool virValidateWWN(const char *wwn);
|
||||||
|
|
||||||
|
bool virStrIsPrint(const char *str);
|
||||||
#endif /* __VIR_UTIL_H__ */
|
#endif /* __VIR_UTIL_H__ */
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<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>
|
||||||
|
<disk type='block' device='cdrom'>
|
||||||
|
<source dev='/dev/HostVG/QEMUGuest1'/>
|
||||||
|
<target dev='sda' bus='virtio'/>
|
||||||
|
<vendor>SEAGATE</vendor>
|
||||||
|
<product>ST3146707LC</product>
|
||||||
|
</disk>
|
||||||
|
<disk type='block' device='disk'>
|
||||||
|
<source dev='/dev/HostVG/QEMUGuest2'/>
|
||||||
|
<target dev='sdb' bus='scsi'/>
|
||||||
|
<vendor>SEAGATE</vendor>
|
||||||
|
<product>ST3567807GD</product>
|
||||||
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||||
|
</disk>
|
||||||
|
<controller type='usb' index='0'/>
|
||||||
|
<controller type='scsi' index='0' model='virtio-scsi'/>
|
||||||
|
<controller type='scsi' index='1' model='lsilogic'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
13
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
Normal file
13
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
|
||||||
|
/usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
|
||||||
|
-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
|
||||||
|
-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
|
||||||
|
-device lsi,id=scsi1,bus=pci.0,addr=0x4 \
|
||||||
|
-usb \
|
||||||
|
-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-scsi0-0-0-0 \
|
||||||
|
-device scsi-cd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,\
|
||||||
|
id=scsi0-0-0-0,vendor=SEAGATE,product=ST3146707LC \
|
||||||
|
-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-scsi1-0-0 \
|
||||||
|
-device scsi-hd,bus=scsi1.0,scsi-id=0,drive=drive-scsi1-0-0,\
|
||||||
|
id=scsi1-0-0,vendor=SEAGATE,product=ST3567807GD \
|
||||||
|
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
|
38
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
Normal file
38
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<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>
|
||||||
|
<disk type='block' device='cdrom'>
|
||||||
|
<source dev='/dev/HostVG/QEMUGuest1'/>
|
||||||
|
<target dev='sda' bus='scsi'/>
|
||||||
|
<readonly/>
|
||||||
|
<vendor>SEAGATE</vendor>
|
||||||
|
<product>ST3146707LC</product>
|
||||||
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||||
|
</disk>
|
||||||
|
<disk type='block' device='disk'>
|
||||||
|
<source dev='/dev/HostVG/QEMUGuest2'/>
|
||||||
|
<target dev='sdb' bus='scsi'/>
|
||||||
|
<readonly/>
|
||||||
|
<vendor>SEAGATE</vendor>
|
||||||
|
<product>ST3567807GD</product>
|
||||||
|
<address type='drive' controller='1' bus='0' target='0' unit='0'/>
|
||||||
|
</disk>
|
||||||
|
<controller type='usb' index='0'/>
|
||||||
|
<controller type='scsi' index='0' model='virtio-scsi'/>
|
||||||
|
<controller type='scsi' index='1' model='lsilogic'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -507,6 +507,14 @@ mymain(void)
|
|||||||
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||||
QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
|
QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
|
||||||
QEMU_CAPS_SCSI_DISK_WWN);
|
QEMU_CAPS_SCSI_DISK_WWN);
|
||||||
|
DO_TEST("disk-scsi-disk-vpd",
|
||||||
|
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||||
|
QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
|
||||||
|
QEMU_CAPS_SCSI_DISK_WWN);
|
||||||
|
DO_TEST_FAILURE("disk-scsi-disk-vpd-build-error",
|
||||||
|
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||||
|
QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
|
||||||
|
QEMU_CAPS_SCSI_DISK_WWN);
|
||||||
DO_TEST("disk-scsi-vscsi",
|
DO_TEST("disk-scsi-vscsi",
|
||||||
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
||||||
DO_TEST("disk-scsi-virtio-scsi",
|
DO_TEST("disk-scsi-virtio-scsi",
|
||||||
|
@ -239,6 +239,8 @@ mymain(void)
|
|||||||
DO_TEST("seclabel-none");
|
DO_TEST("seclabel-none");
|
||||||
DO_TEST("numad-static-vcpu-no-numatune");
|
DO_TEST("numad-static-vcpu-no-numatune");
|
||||||
|
|
||||||
|
DO_TEST("disk-scsi-disk-vpd");
|
||||||
|
|
||||||
/* These tests generate different XML */
|
/* These tests generate different XML */
|
||||||
DO_TEST_DIFFERENT("balloon-device-auto");
|
DO_TEST_DIFFERENT("balloon-device-auto");
|
||||||
DO_TEST_DIFFERENT("channel-virtio-auto");
|
DO_TEST_DIFFERENT("channel-virtio-auto");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user