Skip to content

Commit 77fbaba

Browse files
author
Gean Jair Silva
committed
Fix the calculation of a volume's physical size
1 parent 9030443 commit 77fbaba

3 files changed

Lines changed: 65 additions & 1 deletion

File tree

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtStorageVolumeDef.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ public VolumeFormat getFormat() {
8383
return this._volFormat;
8484
}
8585

86+
public Long getVolSize() {
87+
return _volSize;
88+
}
89+
8690
@Override
8791
public String toString() {
8892
StringBuilder storageVolBuilder = new StringBuilder();

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtStorageVolumeXMLParser.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import javax.xml.parsers.DocumentBuilder;
2323
import javax.xml.parsers.ParserConfigurationException;
2424

25+
import com.cloud.utils.StringUtils;
2526
import org.apache.cloudstack.utils.security.ParserUtils;
2627
import org.apache.logging.log4j.Logger;
2728
import org.apache.logging.log4j.LogManager;
@@ -35,6 +36,35 @@
3536
public class LibvirtStorageVolumeXMLParser {
3637
protected Logger logger = LogManager.getLogger(getClass());
3738

39+
public String getBackingFileNameIfExists(String volXML) {
40+
try {
41+
DocumentBuilder builder = ParserUtils.getSaferDocumentBuilderFactory().newDocumentBuilder();
42+
43+
InputSource is = new InputSource();
44+
is.setCharacterStream(new StringReader(volXML));
45+
Document doc = builder.parse(is);
46+
47+
Element rootElement = doc.getDocumentElement();
48+
NodeList backingStores = rootElement.getElementsByTagName("backingStore");
49+
if (backingStores.getLength() > 0) {
50+
Element backingStore = (Element) backingStores.item(0);
51+
NodeList pathNodes = backingStore.getElementsByTagName("path");
52+
if (pathNodes.getLength() > 0) {
53+
String path = pathNodes.item(0).getTextContent();
54+
if (StringUtils.isBlank(path)) {
55+
return null;
56+
}
57+
path = path.trim();
58+
int lastSlash = path.lastIndexOf('/');
59+
return lastSlash >= 0 ? path.substring(lastSlash + 1) : path;
60+
}
61+
}
62+
} catch (ParserConfigurationException | SAXException | IOException e) {
63+
logger.error(e.toString(), e);
64+
}
65+
return null;
66+
}
67+
3868
public LibvirtStorageVolumeDef parseStorageVolumeXML(String volXML) {
3969
DocumentBuilder builder;
4070
try {
@@ -50,6 +80,7 @@ public LibvirtStorageVolumeDef parseStorageVolumeXML(String volXML) {
5080
Element target = (Element)rootElement.getElementsByTagName("target").item(0);
5181
String format = getAttrValue("type", "format", target);
5282
Long capacity = Long.parseLong(getTagValue("capacity", rootElement));
83+
5384
return new LibvirtStorageVolumeDef(VolName, capacity, LibvirtStorageVolumeDef.VolumeFormat.getFormat(format), null, null);
5485
} catch (ParserConfigurationException e) {
5586
logger.debug(e.toString());

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,12 @@ public LibvirtStoragePoolDef getStoragePoolDef(Connect conn, StoragePool pool) t
505505
return parser.parseStoragePoolXML(poolDefXML);
506506
}
507507

508+
private String getBackingFileOfVolumeIfExists(StorageVol vol) throws LibvirtException {
509+
String volDefXML = vol.getXMLDesc(0);
510+
LibvirtStorageVolumeXMLParser parser = new LibvirtStorageVolumeXMLParser();
511+
return parser.getBackingFileNameIfExists(volDefXML);
512+
}
513+
508514
public LibvirtStorageVolumeDef getStorageVolumeDef(Connect conn, StorageVol vol) throws LibvirtException {
509515
String volDefXML = vol.getXMLDesc(0);
510516
LibvirtStorageVolumeXMLParser parser = new LibvirtStorageVolumeXMLParser();
@@ -655,6 +661,28 @@ public KVMStoragePool getStoragePool(String uuid, boolean refreshInfo) {
655661
}
656662
}
657663

664+
private Long getBackingFileSizes(StoragePool pool, StorageVol vol) throws LibvirtException {
665+
long total = 0L;
666+
Set<String> visited = new HashSet<>();
667+
StorageVol current = vol;
668+
669+
while (current != null) {
670+
total += current.getInfo().allocation;
671+
String backingName = getBackingFileOfVolumeIfExists(current);
672+
if (StringUtils.isBlank(backingName) || !visited.add(backingName)) {
673+
break;
674+
}
675+
try {
676+
current = getVolume(pool, backingName);
677+
} catch (CloudRuntimeException e) {
678+
logger.error("Unable to resolve backing volume {} in pool {}: {}", backingName, pool.getName(), e.getMessage());
679+
break;
680+
}
681+
}
682+
683+
return total;
684+
}
685+
658686
@Override
659687
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
660688
LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool;
@@ -663,8 +691,9 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
663691
StorageVol vol = getVolume(libvirtPool.getPool(), volumeUuid);
664692
KVMPhysicalDisk disk;
665693
LibvirtStorageVolumeDef voldef = getStorageVolumeDef(libvirtPool.getPool().getConnect(), vol);
694+
Long allSizes = getBackingFileSizes(libvirtPool.getPool(), vol);
666695
disk = new KVMPhysicalDisk(vol.getPath(), vol.getName(), pool);
667-
disk.setSize(vol.getInfo().allocation);
696+
disk.setSize(allSizes);
668697
disk.setVirtualSize(vol.getInfo().capacity);
669698

670699
/**

0 commit comments

Comments
 (0)