Skip to content

Commit

Permalink
Add Qcow2BitmapInfo data to GetQemuImageInfo
Browse files Browse the repository at this point in the history
Extend the GetQemuImageInfoVDSCommand command to also provide
information about the bitmaps.

This data will only be valid when the hypervisor has the
qemu_image_info_bitmaps capability.

The bitmap information can be used to validate the engine's bitmap data
with the qemu-img info.

VDSM PR: oVirt/vdsm#394

Signed-off-by: Jean-Louis Dupond <[email protected]>
  • Loading branch information
dupondje authored and sandrobonazzola committed Oct 4, 2024
1 parent 1e10b6e commit 2c818d8
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ public VDS clone() {
vds.setBootUuid(getBootUuid());
vds.setCdChangePdiv(isCdChangePdiv());
vds.setOvnConfigured(isOvnConfigured());
vds.setQemuImageInfoBitmaps(isQemuImageInfoBitmaps());
return vds;
}

Expand Down Expand Up @@ -1906,4 +1907,12 @@ public String getVdsmCpusAffinity() {
public void setVdsmCpusAffinity(String value) {
vdsDynamic.setVdsmCpusAffinity(value);
}

public boolean isQemuImageInfoBitmaps() {
return vdsDynamic.isQemuImageInfoBitmaps();
}

public void setQemuImageInfoBitmaps(boolean qemuImageInfoBitmaps) {
vdsDynamic.setQemuImageInfoBitmaps(qemuImageInfoBitmaps);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ public class VdsDynamic implements BusinessEntityWithStatus<Guid, VDSStatus> {

private String vdsmCpusAffinity;

private boolean qemuImageInfoBitmaps;

public VdsDynamic() {
rpmVersion = new RpmVersion();
libvirtVersion = new RpmVersion();
Expand Down Expand Up @@ -1028,6 +1030,14 @@ public String getVdsmCpusAffinity() {
return vdsmCpusAffinity;
}

public boolean isQemuImageInfoBitmaps() {
return qemuImageInfoBitmaps;
}

public void setQemuImageInfoBitmaps(boolean qemuImageInfoBitmaps) {
this.qemuImageInfoBitmaps = qemuImageInfoBitmaps;
}


@Override
public int hashCode() {
Expand Down Expand Up @@ -1113,7 +1123,8 @@ public int hashCode() {
cdChangePdiv,
ovnConfigured,
cpuTopology,
vdsmCpusAffinity
vdsmCpusAffinity,
qemuImageInfoBitmaps
);
}

Expand Down Expand Up @@ -1209,6 +1220,7 @@ public boolean equals(Object obj) {
&& cdChangePdiv == other.cdChangePdiv
&& ovnConfigured == other.ovnConfigured
&& Objects.equals(cpuTopology, other.cpuTopology)
&& Objects.equals(vdsmCpusAffinity, other.vdsmCpusAffinity);
&& Objects.equals(vdsmCpusAffinity, other.vdsmCpusAffinity)
&& qemuImageInfoBitmaps == other.qemuImageInfoBitmaps;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.ovirt.engine.core.common.businessentities.storage;

import java.util.List;

import org.ovirt.engine.core.compat.Guid;

public class Qcow2BitmapInfo {

private Guid name;
private long granularity;
private List<Qcow2BitmapInfoFlags> flags;


public Guid getName() {
return name;
}

public void setName(Guid name) {
this.name = name;
}

public long getGranularity() {
return granularity;
}

public void setGranularity(long granularity) {
this.granularity = granularity;
}

public List<Qcow2BitmapInfoFlags> getFlags() {
return flags;
}

public void setFlags(List<Qcow2BitmapInfoFlags> flags) {
this.flags = flags;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.ovirt.engine.core.common.businessentities.storage;

import java.util.HashMap;
import java.util.Map;

public enum Qcow2BitmapInfoFlags {
IN_USE("in-use"),
AUTO("auto");

private String value;
private static Map<String, Qcow2BitmapInfoFlags> mappings;

static {
mappings = new HashMap<>();
for (Qcow2BitmapInfoFlags error : values()) {
mappings.put(error.getValue(), error);
}
}

Qcow2BitmapInfoFlags(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public static Qcow2BitmapInfoFlags forValue(String value) {
return mappings.get(value);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.ovirt.engine.core.common.businessentities.storage;

import java.util.List;

import org.ovirt.engine.core.compat.Guid;

public class QemuImageInfo {
Expand All @@ -13,6 +15,7 @@ public class QemuImageInfo {
private long clusterSize;
private String backingFile;
private QcowCompat qcowCompat;
private List<Qcow2BitmapInfo> qcow2bitmaps;

public Guid getImageId() {
return imageId;
Expand Down Expand Up @@ -85,4 +88,12 @@ public QcowCompat getQcowCompat() {
public void setQcowCompat(QcowCompat qcowCompat) {
this.qcowCompat = qcowCompat;
}

public List<Qcow2BitmapInfo> getQcow2bitmaps() {
return qcow2bitmaps;
}

public void setQcow2bitmaps(List<Qcow2BitmapInfo> qcow2bitmaps) {
this.qcow2bitmaps = qcow2bitmaps;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ public List<VDS> getAllWithoutNetwork(Guid networkId) {
entity.setOvnConfigured(rs.getBoolean("ovn_configured"));
entity.setCpuTopology(SerializationFactory.getDeserializer().deserialize(rs.getString("cpu_topology"), ArrayList.class));
entity.setVdsmCpusAffinity(rs.getString("vdsm_cpus_affinity"));
entity.setQemuImageInfoBitmaps(rs.getBoolean("qemu_image_info_bitmaps"));
return entity;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public VdsDynamicDaoImpl() {
entity.setOvnConfigured(rs.getBoolean("ovn_configured"));
entity.setCpuTopology(SerializationFactory.getDeserializer().deserialize(rs.getString("cpu_topology"), ArrayList.class));
entity.setVdsmCpusAffinity(rs.getString("vdsm_cpus_affinity"));
entity.setQemuImageInfoBitmaps(rs.getBoolean("qemu_image_info_bitmaps"));

return entity;
};
Expand Down Expand Up @@ -352,7 +353,8 @@ protected MapSqlParameterSource createFullParametersMapper(VdsDynamic vds) {
.addValue("cd_change_pdiv", vds.isCdChangePdiv())
.addValue("ovn_configured", vds.isOvnConfigured())
.addValue("cpu_topology", SerializationFactory.getSerializer().serialize(vds.getCpuTopology()))
.addValue("vdsm_cpus_affinity", vds.getVdsmCpusAffinity());
.addValue("vdsm_cpus_affinity", vds.getVdsmCpusAffinity())
.addValue("qemu_image_info_bitmaps", vds.isQemuImageInfoBitmaps());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import java.util.Map;

import javax.inject.Inject;

import org.ovirt.engine.core.common.businessentities.storage.QcowCompat;
import org.ovirt.engine.core.common.businessentities.storage.QemuImageInfo;
import org.ovirt.engine.core.common.businessentities.storage.QemuVolumeFormat;
import org.ovirt.engine.core.common.utils.EnumUtils;
import org.ovirt.engine.core.common.vdscommands.GetVolumeInfoVDSCommandParameters;

public class GetQemuImageInfoVDSCommand<P extends GetVolumeInfoVDSCommandParameters> extends VdsBrokerCommand<P> {
@Inject
private VdsBrokerObjectsBuilder vdsBrokerObjectsBuilder;

private QemuImageInfoReturn result;

public GetQemuImageInfoVDSCommand(P parameters) {
Expand Down Expand Up @@ -61,6 +66,10 @@ public QemuImageInfo buildImageEntity(Map<String, Object> struct) {
if (struct.containsKey("clustersize")) {
qemuImageInfo.setClusterSize(Long.parseLong(struct.get("clustersize").toString()));
}
if (struct.containsKey("bitmaps") && struct.get("bitmaps") != null) {
Object[] bitmaps = (Object[]) struct.get("bitmaps");
qemuImageInfo.setQcow2bitmaps(vdsBrokerObjectsBuilder.buildQcow2Bitmaps(bitmaps));
}
} catch (RuntimeException ex) {
log.error("Failed building Qemu image: {}", ex.getMessage());
printReturnValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
import org.ovirt.engine.core.common.businessentities.storage.DiskVmElement;
import org.ovirt.engine.core.common.businessentities.storage.LUNs;
import org.ovirt.engine.core.common.businessentities.storage.LeaseJobStatus;
import org.ovirt.engine.core.common.businessentities.storage.Qcow2BitmapInfo;
import org.ovirt.engine.core.common.businessentities.storage.Qcow2BitmapInfoFlags;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat;
import org.ovirt.engine.core.common.businessentities.storage.VolumeType;
Expand Down Expand Up @@ -1040,6 +1042,7 @@ public void updateVDSDynamicData(VDS vds, Map<String, String> vdsmNameMap, Map<S
vds.setCdChangePdiv(assignBoolValue(struct, VdsProperties.CD_CHANGE_PDIV));
vds.setOvnConfigured(assignBoolValue(struct, VdsProperties.OVN_CONFIGURED));
vds.setVdsmCpusAffinity(assignStringValueFromArray(struct, VdsProperties.vdsm_cpus_affinity));
vds.setQemuImageInfoBitmaps(assignBoolValue(struct, VdsProperties.QEMU_IMAGE_INFO_BITMAPS));
}

private void setDnsResolverConfigurationData(VDS vds, Map<String, Object> struct) {
Expand Down Expand Up @@ -2824,4 +2827,23 @@ public LeaseStatus buildLeaseStatus(Map<String, Object> struct) {

return leaseStatus;
}

public List<Qcow2BitmapInfo> buildQcow2Bitmaps(Object[] struct) {
ArrayList<Qcow2BitmapInfo> bitmaps = new ArrayList<>();

for (Map<String, Object> bitmap : (Map<String, Object>[]) struct) {
Qcow2BitmapInfo bitmapInfo = new Qcow2BitmapInfo();
bitmapInfo.setName(Guid.createGuidFromString(bitmap.get("name").toString()));
bitmapInfo.setGranularity((Long)bitmap.get("granularity"));

Object[] flags = (Object[]) bitmap.get("flags");
List<Qcow2BitmapInfoFlags> qcow2BitmapInfoFlags = Arrays.stream(flags)
.map(flag -> Qcow2BitmapInfoFlags.forValue(flag.toString())).collect(Collectors.toList());
bitmapInfo.setFlags(qcow2BitmapInfoFlags);

bitmaps.add(bitmapInfo);
}

return bitmaps;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -591,4 +591,6 @@ public final class VdsProperties {
public static final String BOOT_UUID = "boot_uuid";

public static final String CD_CHANGE_PDIV = "cd_change_pdiv";

public static final String QEMU_IMAGE_INFO_BITMAPS = "qemu_image_info_bitmaps";
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;
import org.ovirt.engine.core.common.businessentities.LeaseStatus;
Expand All @@ -25,6 +26,8 @@
import org.ovirt.engine.core.common.businessentities.network.VmInterfaceType;
import org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface;
import org.ovirt.engine.core.common.businessentities.storage.DiskImageDynamic;
import org.ovirt.engine.core.common.businessentities.storage.Qcow2BitmapInfo;
import org.ovirt.engine.core.common.businessentities.storage.Qcow2BitmapInfoFlags;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.utils.serialization.json.JsonObjectDeserializer;

Expand Down Expand Up @@ -481,4 +484,26 @@ private Map<String, Object> createCpuTopologyStruct() {
new Object[] { cpuCapability1, cpuCapability2, cpuCapability3, cpuCapability4 });
return struct;
}

@Test
private static Map<String, Object> getBitmapAsMap(String name, Long granularity, List<Qcow2BitmapInfoFlags> flags) {
Map<String, Object> bitmap = new HashMap<>();
bitmap.put("name", name);
bitmap.put("granularity", granularity);
flags.stream().map(flag -> flag.getValue()).collect(Collectors.toList()).toArray();
return bitmap;
}

public void testBitmapList() {
Object[] bitmaps = new Object[2];
bitmaps[0] = getBitmapAsMap("old-bitmap", 65536L, Arrays.asList(Qcow2BitmapInfoFlags.AUTO));
bitmaps[1] = getBitmapAsMap("new-bitmap", 65536L, Arrays.asList(Qcow2BitmapInfoFlags.AUTO));
List<Qcow2BitmapInfo> info = getBitmapInfo(bitmaps);
assertEquals("old-bitmap", info.get(0).getName());
assertEquals("new-bitmap", info.get(1).getName());
}

private List<Qcow2BitmapInfo> getBitmapInfo(Object[] bitmaps) {
return vdsBrokerObjectsBuilder.buildQcow2Bitmaps(bitmaps);
}
}
6 changes: 4 additions & 2 deletions packaging/dbscripts/create_views.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,8 @@ SELECT cluster.cluster_id AS cluster_id,
vds_dynamic.ovn_configured AS ovn_configured,
vds_static.ssh_public_key AS ssh_public_key,
vds_dynamic.cpu_topology AS cpu_topology,
vds_dynamic.vdsm_cpus_affinity AS vdsm_cpus_affinity
vds_dynamic.vdsm_cpus_affinity AS vdsm_cpus_affinity,
vds_dynamic.qemu_image_info_bitmaps AS qemu_image_info_bitmaps
FROM cluster
INNER JOIN vds_static
ON cluster.cluster_id = vds_static.cluster_id
Expand Down Expand Up @@ -2102,7 +2103,8 @@ SELECT cluster.cluster_id,
vds_dynamic.ovn_configured AS ovn_configured,
vds_static.ssh_public_key AS ssh_public_key,
vds_dynamic.cpu_topology AS cpu_topology,
vds_dynamic.vdsm_cpus_affinity AS vdsm_cpus_affinity
vds_dynamic.vdsm_cpus_affinity AS vdsm_cpus_affinity,
vds_dynamic.qemu_image_info_bitmaps AS qemu_image_info_bitmaps
FROM cluster
INNER JOIN vds_static
ON cluster.cluster_id = vds_static.cluster_id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select fn_db_add_column('vds_dynamic', 'qemu_image_info_bitmaps', 'BOOLEAN NOT NULL DEFAULT FALSE');
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,4 @@ SELECT fn_db_add_column_to_object_white_list('vds', 'backup_enabled');
SELECT fn_db_add_column_to_object_white_list('vds', 'cold_backup_enabled');
SELECT fn_db_add_column_to_object_white_list('vds', 'clear_bitmaps_enabled');
SELECT fn_db_add_column_to_object_white_list('vds', 'cd_change_pdiv');
SELECT fn_db_add_column_to_object_white_list('vds', 'qemu_image_info_bitmaps');
15 changes: 10 additions & 5 deletions packaging/dbscripts/vds_sp.sql
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ CREATE OR REPLACE FUNCTION InsertVdsDynamic (
v_cd_change_pdiv BOOLEAN,
v_ovn_configured BOOLEAN,
v_cpu_topology JSONB,
v_vdsm_cpus_affinity VARCHAR(256)
v_vdsm_cpus_affinity VARCHAR(256),
v_qemu_image_info_bitmaps BOOLEAN
)
RETURNS VOID AS $FUNCTION$
BEGIN
Expand Down Expand Up @@ -360,7 +361,8 @@ BEGIN
cd_change_pdiv,
ovn_configured,
cpu_topology,
vdsm_cpus_affinity
vdsm_cpus_affinity,
qemu_image_info_bitmaps
)
VALUES (
v_cpu_cores,
Expand Down Expand Up @@ -440,7 +442,8 @@ BEGIN
v_cd_change_pdiv,
v_ovn_configured,
v_cpu_topology,
v_vdsm_cpus_affinity
v_vdsm_cpus_affinity,
v_qemu_image_info_bitmaps
);
END;

Expand Down Expand Up @@ -545,7 +548,8 @@ CREATE OR REPLACE FUNCTION UpdateVdsDynamic (
v_cd_change_pdiv BOOLEAN,
v_ovn_configured BOOLEAN,
v_cpu_topology JSONB,
v_vdsm_cpus_affinity VARCHAR(256)
v_vdsm_cpus_affinity VARCHAR(256),
v_qemu_image_info_bitmaps BOOLEAN
)
RETURNS VOID
--The [vds_dynamic] table doesn't have a timestamp column. Optimistic concurrency logic cannot be generated
Expand Down Expand Up @@ -633,7 +637,8 @@ BEGIN
cd_change_pdiv = v_cd_change_pdiv,
ovn_configured = v_ovn_configured,
cpu_topology = v_cpu_topology,
vdsm_cpus_affinity = v_vdsm_cpus_affinity
vdsm_cpus_affinity = v_vdsm_cpus_affinity,
qemu_image_info_bitmaps = v_qemu_image_info_bitmaps
WHERE vds_id = v_vds_id;
END;

Expand Down

0 comments on commit 2c818d8

Please sign in to comment.