From 12c395b56052af36901ab3ed1a366ed8985740eb Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 25 Nov 2015 14:37:40 +0530 Subject: [PATCH] CLOUDSTACK-9083: Add disk serial to kvm virt xml Adds disk serial ids based on volume uuids to the virt xml. This may be useful for appliances/software that needs some serial ids on the VM disks. This does not impact existing/running VMs, the vm virt xmls will be updates for running VMs the next time they are stopped/started. For testing, disk serial (of debian based systemvm) in the virt xml matched that in /sys/devices/pci0000:00:0000:00:07.0/virtio4/block/vda/serial. We currently don't support scsi-blcok devices for which serial is not supported, for this we've added a DeviceType (LUN) which may be used in future and a check to not add the serial to the xml if disk type is LUN. Refer: https://libvirt.org/formatdomain.html#elementsDisks Signed-off-by: Rohit Yadav --- .../kvm/resource/LibvirtComputingResource.java | 6 ++++++ .../cloud/hypervisor/kvm/resource/LibvirtVMDef.java | 11 ++++++++++- .../hypervisor/kvm/storage/KVMStorageProcessor.java | 9 ++++++--- .../kvm/resource/LibvirtComputingResourceTest.java | 8 ++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 11317afe5e2c..a7777cc31407 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -2140,6 +2140,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { if (data instanceof VolumeObjectTO) { final VolumeObjectTO volumeObjectTO = (VolumeObjectTO)data; + disk.setSerial(diskUuidToSerial(volumeObjectTO.getUuid())); if (volumeObjectTO.getBytesReadRate() != null && volumeObjectTO.getBytesReadRate() > 0) { disk.setBytesReadRate(volumeObjectTO.getBytesReadRate()); } @@ -2419,6 +2420,11 @@ public StartupCommand[] initialize() { } } + public String diskUuidToSerial(String uuid) { + String uuidWithoutHyphen = uuid.replace("-",""); + return uuidWithoutHyphen.substring(0, Math.min(uuidWithoutHyphen.length(), 20)); + } + private String getIqn() { try { final String textToFind = "InitiatorName="; diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index 5ab842948df0..fb1b1340115c 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -419,7 +419,7 @@ public List getInterfaces() { public static class DiskDef { public enum DeviceType { - FLOPPY("floppy"), DISK("disk"), CDROM("cdrom"); + FLOPPY("floppy"), DISK("disk"), CDROM("cdrom"), LUN("lun"); String _type; DeviceType(String type) { @@ -524,6 +524,7 @@ public String toString() { private Long _iopsReadRate; private Long _iopsWriteRate; private DiskCacheMode _diskCacheMode; + private String _serial; private boolean qemuDriver = true; public void setDeviceType(DeviceType deviceType) { @@ -708,6 +709,10 @@ public void setQemuDriver(boolean qemuDriver){ this.qemuDriver = qemuDriver; } + public void setSerial(String serial) { + this._serial = serial; + } + @Override public String toString() { StringBuilder diskBuilder = new StringBuilder(); @@ -761,6 +766,10 @@ public String toString() { } diskBuilder.append("/>\n"); + if (_serial != null && !_serial.isEmpty() && _deviceType != DeviceType.LUN) { + diskBuilder.append("" + _serial + ""); + } + if ((_deviceType != DeviceType.CDROM) && (s_libvirtVersion >= 9008) && (s_qemuVersion >= 1001000) && diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index 08ce05ad3eaf..995941346c6d 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -950,7 +950,7 @@ protected synchronized String attachOrDetachDevice(final Connect conn, final boo return null; } - protected synchronized String attachOrDetachDisk(final Connect conn, final boolean attach, final String vmName, final KVMPhysicalDisk attachingDisk, final int devId) throws LibvirtException, + protected synchronized String attachOrDetachDisk(final Connect conn, final boolean attach, final String vmName, final KVMPhysicalDisk attachingDisk, final int devId, final String serial) throws LibvirtException, InternalErrorException { List disks = null; Domain dm = null; @@ -986,6 +986,7 @@ protected synchronized String attachOrDetachDisk(final Connect conn, final boole } } else { diskdef = new DiskDef(); + diskdef.setSerial(serial); if (attachingPool.getType() == StoragePoolType.RBD) { if(resource.getHypervisorType() == Hypervisor.HypervisorType.LXC){ // For LXC, map image to host and then attach to Vm @@ -1028,6 +1029,7 @@ public Answer attachVolume(final AttachCommand cmd) { final VolumeObjectTO vol = (VolumeObjectTO)disk.getData(); final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore(); final String vmName = cmd.getVmName(); + final String serial = resource.diskUuidToSerial(vol.getUuid()); try { final Connect conn = LibvirtConnection.getConnectionByVmName(vmName); @@ -1035,7 +1037,7 @@ public Answer attachVolume(final AttachCommand cmd) { final KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath()); - attachOrDetachDisk(conn, true, vmName, phyDisk, disk.getDiskSeq().intValue()); + attachOrDetachDisk(conn, true, vmName, phyDisk, disk.getDiskSeq().intValue(), serial); return new AttachAnswer(disk); } catch (final LibvirtException e) { @@ -1054,12 +1056,13 @@ public Answer dettachVolume(final DettachCommand cmd) { final VolumeObjectTO vol = (VolumeObjectTO)disk.getData(); final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore(); final String vmName = cmd.getVmName(); + final String serial = resource.diskUuidToSerial(vol.getUuid()); try { final Connect conn = LibvirtConnection.getConnectionByVmName(vmName); final KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath()); - attachOrDetachDisk(conn, false, vmName, phyDisk, disk.getDiskSeq().intValue()); + attachOrDetachDisk(conn, false, vmName, phyDisk, disk.getDiskSeq().intValue(), serial); storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath()); diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index b15e1488b8c8..e0d99525f838 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -389,6 +389,14 @@ public void testGetNicStats() { assertNotNull(stats); } + @Test + public void diskUuidToSerialTest() { + String uuid = "38400000-8cf0-11bd-b24e-10b96e4ef00d"; + String expected = "384000008cf011bdb24e"; + LibvirtComputingResource lcr = new LibvirtComputingResource(); + Assert.assertEquals(expected, lcr.diskUuidToSerial(uuid)); + } + @Test public void testUUID() { String uuid = "1";