refactor, implement remaining endpoints

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2026-02-16 17:04:36 +05:30
parent 2352c83378
commit d9a7d2f097
60 changed files with 2432 additions and 1123 deletions

View File

@ -36,7 +36,9 @@ import org.apache.cloudstack.acl.Rule;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.command.admin.backup.FinalizeBackupCmd;
import org.apache.cloudstack.api.command.admin.vm.DeployVMCmdByAdmin;
import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
@ -56,16 +58,19 @@ import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.backup.BackupVO;
import org.apache.cloudstack.backup.ImageTransfer.Direction;
import org.apache.cloudstack.backup.ImageTransfer.Format;
import org.apache.cloudstack.backup.ImageTransferVO;
import org.apache.cloudstack.backup.IncrementalBackupService;
import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.ImageTransferDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.veeam.api.converter.AsyncJobJoinVOToJobConverter;
import org.apache.cloudstack.veeam.api.converter.BackupVOToBackupConverter;
import org.apache.cloudstack.veeam.api.converter.ClusterVOToClusterConverter;
import org.apache.cloudstack.veeam.api.converter.DataCenterJoinVOToDataCenterConverter;
import org.apache.cloudstack.veeam.api.converter.HostJoinVOToHostConverter;
@ -77,6 +82,8 @@ import org.apache.cloudstack.veeam.api.converter.StoreVOToStorageDomainConverter
import org.apache.cloudstack.veeam.api.converter.UserVmJoinVOToVmConverter;
import org.apache.cloudstack.veeam.api.converter.VmSnapshotVOToSnapshotConverter;
import org.apache.cloudstack.veeam.api.converter.VolumeJoinVOToDiskConverter;
import org.apache.cloudstack.veeam.api.dto.Backup;
import org.apache.cloudstack.veeam.api.dto.Checkpoint;
import org.apache.cloudstack.veeam.api.dto.Cluster;
import org.apache.cloudstack.veeam.api.dto.DataCenter;
import org.apache.cloudstack.veeam.api.dto.Disk;
@ -86,7 +93,6 @@ import org.apache.cloudstack.veeam.api.dto.ImageTransfer;
import org.apache.cloudstack.veeam.api.dto.Job;
import org.apache.cloudstack.veeam.api.dto.Network;
import org.apache.cloudstack.veeam.api.dto.Nic;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.ResourceAction;
import org.apache.cloudstack.veeam.api.dto.Snapshot;
import org.apache.cloudstack.veeam.api.dto.StorageDomain;
@ -246,6 +252,9 @@ public class ServerAdapter extends ManagerBase {
@Inject
VMSnapshotDao vmSnapshotDao;
@Inject
BackupDao backupDao;
//ToDo: check access on objects
protected Role createServiceAccountRole() {
@ -353,7 +362,7 @@ public class ServerAdapter extends ManagerBase {
}
public List<Host> listAllHosts() {
final List<HostJoinVO> hosts = hostJoinDao.listAll();
final List<HostJoinVO> hosts = hostJoinDao.listRoutingHostsByHypervisor(Hypervisor.HypervisorType.KVM);
return HostJoinVOToHostConverter.toHostList(hosts);
}
@ -410,11 +419,11 @@ public class ServerAdapter extends ManagerBase {
if (request == null) {
throw new InvalidParameterValueException("Request disk data is empty");
}
String name = request.name;
String name = request.getName();
Long zoneId = null;
Long clusterId = null;
if (request.cluster != null && StringUtils.isNotEmpty(request.cluster.id)) {
ClusterVO clusterVO = clusterDao.findByUuid(request.cluster.id);
if (request.getCluster() != null && StringUtils.isNotEmpty(request.getCluster().getId())) {
ClusterVO clusterVO = clusterDao.findByUuid(request.getCluster().getId());
if (clusterVO != null) {
zoneId = clusterVO.getDataCenterId();
clusterId = clusterVO.getId();
@ -425,14 +434,14 @@ public class ServerAdapter extends ManagerBase {
}
Integer cpu = null;
try {
cpu = request.cpu.topology.sockets;
cpu = request.getCpu().getTopology().getSockets();
} catch (Exception ignored) {}
if (cpu == null) {
throw new InvalidParameterValueException("CPU topology sockets must be specified");
}
Long memory = null;
try {
memory = Long.valueOf(request.memory);
memory = Long.valueOf(request.getMemory());
} catch (Exception ignored) {}
if (memory == null) {
throw new InvalidParameterValueException("Memory must be specified");
@ -443,7 +452,7 @@ public class ServerAdapter extends ManagerBase {
}
ApiConstants.BootType bootType = ApiConstants.BootType.BIOS;
ApiConstants.BootMode bootMode = ApiConstants.BootMode.LEGACY;
if (request.bios != null && StringUtils.isNotEmpty(request.bios.type) && request.bios.type.contains("secure")) {
if (request.getBios() != null && StringUtils.isNotEmpty(request.getBios().getType()) && request.getBios().getType().contains("secure")) {
bootType = ApiConstants.BootType.UEFI;
bootMode = ApiConstants.BootMode.SECURE;
}
@ -618,6 +627,40 @@ public class ServerAdapter extends ManagerBase {
return VolumeJoinVOToDiskConverter.toDisk(vo);
}
public Disk copyDisk(String uuid) {
throw new InvalidParameterValueException("Copy Disk with ID " + uuid + " not implemented");
// VolumeVO vo = volumeDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("Disk with ID " + uuid + " not found");
// }
// Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
// CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
// try {
// Volume volume = volumeApiService.copyVolume(vo.getId(), vo.getName() + "_copy", null, null);
// VolumeJoinVO copiedVolumeVO = volumeJoinDao.findById(volume.getId());
// return VolumeJoinVOToDiskConverter.toDisk(copiedVolumeVO);
// } finally {
// CallContext.unregister();
// }
}
public Disk reduceDisk(String uuid) {
throw new InvalidParameterValueException("Reduce Disk with ID " + uuid + " not implemented");
// VolumeVO vo = volumeDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("Disk with ID " + uuid + " not found");
// }
// Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
// CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
// try {
// Volume volume = volumeApiService.reduceDisk(vo.getId(), vo.getName() + "_copy", null, null);
// VolumeJoinVO copiedVolumeVO = volumeJoinDao.findById(volume.getId());
// return VolumeJoinVOToDiskConverter.toDisk(copiedVolumeVO);
// } finally {
// CallContext.unregister();
// }
}
protected List<DiskAttachment> listDiskAttachmentsByInstanceId(final long instanceId) {
List<VolumeJoinVO> kvmVolumes = volumeJoinDao.listByInstanceId(instanceId);
return VolumeJoinVOToDiskConverter.toDiskAttachmentList(kvmVolumes);
@ -636,12 +679,12 @@ public class ServerAdapter extends ManagerBase {
if (vmVo == null) {
throw new InvalidParameterValueException("VM with ID " + vmUuid + " not found");
}
if (request == null || request.disk == null || StringUtils.isEmpty(request.disk.id)) {
if (request == null || request.getDisk() == null || StringUtils.isEmpty(request.getDisk().getId())) {
throw new InvalidParameterValueException("Request disk data is empty");
}
VolumeVO volumeVO = volumeDao.findByUuid(request.disk.id);
VolumeVO volumeVO = volumeDao.findByUuid(request.getDisk().getId());
if (volumeVO == null) {
throw new InvalidParameterValueException("Disk with ID " + request.disk.id + " not found");
throw new InvalidParameterValueException("Disk with ID " + request.getDisk().getId() + " not found");
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
@ -666,23 +709,23 @@ public class ServerAdapter extends ManagerBase {
if (request == null) {
throw new InvalidParameterValueException("Request disk data is empty");
}
String name = request.name;
String name = request.getName();
if (StringUtils.isBlank(name) && !name.startsWith("Veeam_KvmBackupDisk_")) {
throw new InvalidParameterValueException("Only worker VM disk creation is supported");
}
if (request.storageDomains == null || CollectionUtils.isEmpty(request.storageDomains.storageDomain) ||
request.storageDomains.storageDomain.size() > 1) {
if (request.getStorageDomains() == null || CollectionUtils.isEmpty(request.getStorageDomains().getStorageDomain()) ||
request.getStorageDomains().getStorageDomain().size() > 1) {
throw new InvalidParameterValueException("Exactly one storage domain must be specified");
}
Ref domain = request.storageDomains.storageDomain.get(0);
if (domain == null || domain.id == null) {
StorageDomain domain = request.getStorageDomains().getStorageDomain().get(0);
if (domain == null || domain.getId() == null) {
throw new InvalidParameterValueException("Storage domain ID must be specified");
}
StoragePoolVO pool = primaryDataStoreDao.findByUuid(domain.id);
StoragePoolVO pool = primaryDataStoreDao.findByUuid(domain.getId());
if (pool == null) {
throw new InvalidParameterValueException("Storage domain with ID " + domain.id + " not found");
throw new InvalidParameterValueException("Storage domain with ID " + domain.getId() + " not found");
}
String sizeStr = request.provisionedSize;
String sizeStr = request.getProvisionedSize();
if (StringUtils.isBlank(sizeStr)) {
throw new InvalidParameterValueException("Provisioned size must be specified");
}
@ -697,9 +740,9 @@ public class ServerAdapter extends ManagerBase {
}
provisionedSizeInGb = Math.max(1L, provisionedSizeInGb / (1024L * 1024L * 1024L));
Long initialSize = null;
if (StringUtils.isNotBlank(request.initialSize)) {
if (StringUtils.isNotBlank(request.getInitialSize())) {
try {
initialSize = Long.parseLong(request.initialSize);
initialSize = Long.parseLong(request.getInitialSize());
} catch (NumberFormatException ignored) {}
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
@ -763,12 +806,12 @@ public class ServerAdapter extends ManagerBase {
if (vmVo == null) {
throw new InvalidParameterValueException("VM with ID " + vmUuid + " not found");
}
if (request == null || request.getVnicProfile() == null || StringUtils.isEmpty(request.getVnicProfile().id)) {
if (request == null || request.getVnicProfile() == null || StringUtils.isEmpty(request.getVnicProfile().getId())) {
throw new InvalidParameterValueException("Request nic data is empty");
}
NetworkVO networkVO = networkDao.findByUuid(request.getVnicProfile().id);
NetworkVO networkVO = networkDao.findByUuid(request.getVnicProfile().getId());
if (networkVO == null) {
throw new InvalidParameterValueException("VNic profile " + request.getVnicProfile().id+ " not found");
throw new InvalidParameterValueException("VNic profile " + request.getVnicProfile().getId() + " not found");
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
@ -808,12 +851,12 @@ public class ServerAdapter extends ManagerBase {
if (request == null) {
throw new InvalidParameterValueException("Request image transfer data is empty");
}
if (request.getDisk() == null || StringUtils.isBlank(request.getDisk().id)) {
if (request.getDisk() == null || StringUtils.isBlank(request.getDisk().getId())) {
throw new InvalidParameterValueException("Disk ID must be specified");
}
VolumeJoinVO volumeVO = volumeJoinDao.findByUuid(request.getDisk().id);
VolumeJoinVO volumeVO = volumeJoinDao.findByUuid(request.getDisk().getId());
if (volumeVO == null) {
throw new InvalidParameterValueException("Disk with ID " + request.getDisk().id + " not found");
throw new InvalidParameterValueException("Disk with ID " + request.getDisk().getId() + " not found");
}
Direction direction = EnumUtils.fromString(Direction.class, request.getDirection());
if (direction == null) {
@ -974,4 +1017,161 @@ public class ServerAdapter extends ManagerBase {
}
return action;
}
public ResourceAction revertToSnapshot(String uuid) {
throw new InvalidParameterValueException("revertToSnapshot with ID " + uuid + " not implemented");
// ResourceAction action = null;
// VMSnapshotVO vo = vmSnapshotDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("Snapshot with ID " + uuid + " not found");
// }
// Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
// CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
// try {
// RevertToVMSnapshotCmd cmd = new RevertToVMSnapshotCmd();
// ComponentContext.inject(cmd);
// Map<String, String> params = new HashMap<>();
// params.put(ApiConstants.VM_SNAPSHOT_ID, vo.getUuid());
// ApiServerService.AsyncCmdResult result =
// apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
// serviceUserAccount.second());
// AsyncJobJoinVO jobVo = asyncJobJoinDao.findById(result.jobId);
// if (jobVo == null) {
// throw new CloudRuntimeException("Failed to find job for snapshot revert");
// }
// action = AsyncJobJoinVOToJobConverter.toAction(jobVo);
// } catch (Exception e) {
// throw new CloudRuntimeException("Failed to revert to snapshot: " + e.getMessage(), e);
// } finally {
// CallContext.unregister();
// }
// return action;
}
public List<Backup> listBackupsByInstanceUuid(final String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
}
List<BackupVO> backups = backupDao.searchByVmIds(List.of(vo.getId()));
return BackupVOToBackupConverter.toBackupList(backups, id -> vo);
}
public Backup createInstanceBackup(final String vmUuid, final Backup request) {
UserVmVO vmVo = userVmDao.findByUuid(vmUuid);
if (vmVo == null) {
throw new InvalidParameterValueException("VM with ID " + vmUuid + " not found");
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
CreateBackupCmd cmd = new CreateBackupCmd();
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.VIRTUAL_MACHINE_ID, vmVo.getUuid());
params.put(ApiConstants.NAME, request.getName());
params.put(ApiConstants.DESCRIPTION, request.getDescription());
ApiServerService.AsyncCmdResult result =
apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
serviceUserAccount.second());
if (result.objectId == null) {
throw new CloudRuntimeException("No backup ID returned");
}
BackupVO vo = backupDao.findById(result.objectId);
if (vo == null) {
throw new CloudRuntimeException("Backup not found");
}
return BackupVOToBackupConverter.toBackup(vo, id -> vmVo);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to create backup: " + e.getMessage(), e);
} finally {
CallContext.unregister();
}
}
public Backup getBackup(String uuid) {
BackupVO vo = backupDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("Backup with ID " + uuid + " not found");
}
return BackupVOToBackupConverter.toBackup(vo, id -> userVmDao.findById(id));
}
public List<Disk> listDisksByBackupUuid(final String uuid) {
throw new InvalidParameterValueException("List Backup Disks with ID " + uuid + " not implmenented");
// BackupVO vo = backupDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("Backup with ID " + uuid + " not found");
// }
// return VolumeJoinVOToDiskConverter.toDiskList(volumes);
}
public void finalizeBackup(final String vmUuid, final String uuid, String data) {
ResourceAction action = null;
UserVmVO vmVo = userVmDao.findByUuid(vmUuid);
if (vmVo == null) {
throw new InvalidParameterValueException("Instance with ID " + vmUuid + " not found");
}
BackupVO vo = backupDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("Backup with ID " + uuid + " not found");
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
FinalizeBackupCmd cmd = new FinalizeBackupCmd();
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.VIRTUAL_MACHINE_ID, vmVo.getUuid());
params.put(ApiConstants.BACKUP_ID, vo.getUuid());
boolean result = incrementalBackupService.finalizeBackup(cmd);
if (!result) {
throw new CloudRuntimeException("Failed to finalize backup");
}
} catch (Exception e) {
throw new CloudRuntimeException("Failed to finalize backup: " + e.getMessage(), e);
} finally {
CallContext.unregister();
}
}
public List<Checkpoint> listCheckpointsByInstanceUuid(final String uuid) {
throw new InvalidParameterValueException("Checkpoints for VM with ID " + uuid + " not implemented");
// UserVmVO vo = userVmDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
// }
// List<CheckpointVO> checkpoints = checkpointDao.findByVmId(vo.getId());
// return CheckpointVOToCheckpointConverter.toCheckpointList(checkpoints, vo.getUuid());
}
public ResourceAction deleteCheckpoint(String uuid, boolean async) {
throw new InvalidParameterValueException("Delete Checkpoint with ID " + uuid + " not implemented");
// ResourceAction action = null;
// CheckpointVO vo = checkpointDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("Checkpoint with ID " + uuid + " not found");
// }
// Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
// CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
// try {
// DeleteCheckpointCmd cmd = new DeleteCheckpointCmd();
// ComponentContext.inject(cmd);
// Map<String, String> params = new HashMap<>();
// params.put(ApiConstants.CHECKPOINT_ID, vo.getUuid());
// ApiServerService.AsyncCmdResult result =
// apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
// serviceUserAccount.second());
// AsyncJobJoinVO jobVo = asyncJobJoinDao.findById(result.jobId);
// if (jobVo == null) {
// throw new CloudRuntimeException("Failed to find job for checkpoint deletion");
// }
// action = AsyncJobJoinVOToJobConverter.toAction(jobVo);
// } catch (Exception e) {
// throw new CloudRuntimeException("Failed to delete checkpoint: " + e.getMessage(), e);
// } finally {
// CallContext.unregister();
// }
// return action;
}
}

View File

@ -19,8 +19,6 @@ package org.apache.cloudstack.veeam.api;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -37,7 +35,6 @@ import org.apache.cloudstack.veeam.api.dto.EmptyElement;
import org.apache.cloudstack.veeam.api.dto.Link;
import org.apache.cloudstack.veeam.api.dto.ProductInfo;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.SpecialObjectRef;
import org.apache.cloudstack.veeam.api.dto.SpecialObjects;
import org.apache.cloudstack.veeam.api.dto.SummaryCount;
import org.apache.cloudstack.veeam.api.dto.Version;
@ -94,58 +91,59 @@ public class ApiService extends ManagerBase implements RouteHandler {
add(links, basePath + "/disks", "disks");
add(links, basePath + "/disks?search={query}", "disks/search");
api.link = links;
api.setLink(links);
/* ---------------- Engine backup ---------------- */
api.engineBackup = new EmptyElement();
api.setEngineBackup(new EmptyElement());
/* ---------------- Product info ---------------- */
ProductInfo productInfo = new ProductInfo();
productInfo.instanceId = UuidUtils.nameUUIDFromBytes(VeeamControlService.BindAddress.value().getBytes(StandardCharsets.UTF_8)).toString();
productInfo.setInstanceId(UuidUtils.nameUUIDFromBytes(
VeeamControlService.BindAddress.value().getBytes(StandardCharsets.UTF_8)).toString());
productInfo.name = "oVirt Engine";
Version version = new Version();
version.build = "8";
version.fullVersion = "4.5.8-0.master.fake.el9";
version.major = 4;
version.minor = 5;
version.revision = 0;
version.setBuild("8");
version.setFullVersion("4.5.8-0.master.fake.el9");
version.setMajor(4);
version.setMinor(5);
version.setRevision(0);
productInfo.version = version;
api.productInfo = productInfo;
api.setProductInfo(productInfo);
/* ---------------- Special objects ---------------- */
SpecialObjects specialObjects = new SpecialObjects();
specialObjects.blankTemplate = new SpecialObjectRef(
specialObjects.setBlankTemplate(Ref.of(
basePath + "/templates/00000000-0000-0000-0000-000000000000",
"00000000-0000-0000-0000-000000000000"
);
specialObjects.rootTag = new SpecialObjectRef(
));
specialObjects.setRootTag(Ref.of(
basePath + "/tags/00000000-0000-0000-0000-000000000000",
"00000000-0000-0000-0000-000000000000"
);
api.specialObjects = specialObjects;
));
api.setSpecialObjects(specialObjects);
/* ---------------- Summary ---------------- */
ApiSummary summary = new ApiSummary();
summary.hosts = new SummaryCount(1, 1);
summary.storageDomains = new SummaryCount(1, 2);
summary.users = new SummaryCount(1, 1);
summary.vms = new SummaryCount(1, 8);
api.summary = summary;
summary.setHosts(new SummaryCount(1, 1));
summary.setStorageDomains(new SummaryCount(1, 2));
summary.setUsers(new SummaryCount(1, 1));
summary.setVms(new SummaryCount(1, 8));
api.setSummary(summary);
/* ---------------- Time ---------------- */
api.time = OffsetDateTime.now(ZoneOffset.ofHours(2)).toInstant().toEpochMilli();
api.setTime(System.currentTimeMillis());
/* ---------------- Users ---------------- */
String userId = UUID.randomUUID().toString();
api.authenticatedUser = Ref.of(basePath + "/users/" + userId, userId);
api.effectiveUser = Ref.of(basePath + "/users/" + userId, userId);
api.setAuthenticatedUser(Ref.of(basePath + "/users/" + userId, userId));
api.setEffectiveUser(Ref.of(basePath + "/users/" + userId, userId));
return api;
}
private static void add(List<Link> links, String href, String rel) {
links.add(new Link(href, rel));
links.add(Link.of(href, rel));
}
}

View File

@ -118,7 +118,8 @@ public class DataCentersRouteHandler extends ManagerBase implements RouteHandler
final VeeamControlServlet io) throws IOException {
try {
List<StorageDomain> storageDomains = serverAdapter.listStorageDomainsByDcId(id);
StorageDomains response = new StorageDomains(storageDomains);
StorageDomains response = new StorageDomains();
response.setStorageDomain(storageDomains);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);

View File

@ -90,6 +90,23 @@ public class DisksRouteHandler extends ManagerBase implements RouteHandler {
handleDeleteById(id, resp, outFormat, io);
return;
}
} else if (idAndSubPath.size() == 2) {
String subPath = idAndSubPath.get(1);
if ("copy".equals(subPath)) {
if ("POST".equalsIgnoreCase(method)) {
handlePostDiskCopy(id, req, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "POST", outFormat);
}
return;
} else if ("reduce".equals(subPath)) {
if ("POST".equalsIgnoreCase(method)) {
handlePostDiskReduce(id, req, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "POST", outFormat);
}
return;
}
}
}
@ -136,4 +153,24 @@ public class DisksRouteHandler extends ManagerBase implements RouteHandler {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handlePostDiskCopy(final String id, final HttpServletRequest req, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
Disk response = serverAdapter.copyDisk(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handlePostDiskReduce(final String id, final HttpServletRequest req, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
Disk response = serverAdapter.reduceDisk(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -28,8 +28,14 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.cloudstack.veeam.RouteHandler;
import org.apache.cloudstack.veeam.VeeamControlServlet;
import org.apache.cloudstack.veeam.adapter.ServerAdapter;
import org.apache.cloudstack.veeam.api.dto.Backup;
import org.apache.cloudstack.veeam.api.dto.Checkpoint;
import org.apache.cloudstack.veeam.api.dto.Checkpoints;
import org.apache.cloudstack.veeam.api.dto.Disk;
import org.apache.cloudstack.veeam.api.dto.DiskAttachment;
import org.apache.cloudstack.veeam.api.dto.DiskAttachments;
import org.apache.cloudstack.veeam.api.dto.Disks;
import org.apache.cloudstack.veeam.api.dto.NamedList;
import org.apache.cloudstack.veeam.api.dto.Nic;
import org.apache.cloudstack.veeam.api.dto.Nics;
import org.apache.cloudstack.veeam.api.dto.ResourceAction;
@ -164,6 +170,22 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
handlePostSnapshotForVmId(id, req, resp, outFormat, io);
}
return;
} else if ("backups".equals(subPath)) {
if (!"GET".equalsIgnoreCase(method) && !"POST".equalsIgnoreCase(method)) {
io.methodNotAllowed(resp, "GET, POST", outFormat);
} else if ("GET".equalsIgnoreCase(method)) {
handleGetBackupsByVmId(id, resp, outFormat, io);
} else if ("POST".equalsIgnoreCase(method)) {
handlePostBackupForVmId(id, req, resp, outFormat, io);
}
return;
} else if ("checkpoints".equals(subPath)) {
if ("GET".equalsIgnoreCase(method)) {
handleGetCheckpointsByVmId(id, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "GET, POST", outFormat);
}
return;
}
} else if (idAndSubPath.size() == 3) {
String subPath = idAndSubPath.get(1);
@ -172,11 +194,25 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
if (!"GET".equalsIgnoreCase(method) && !"DELETE".equalsIgnoreCase(method)) {
io.methodNotAllowed(resp, "GET, DELETE", outFormat);
} else if ("GET".equalsIgnoreCase(method)) {
handleGetSnapshotsById(subId, resp, outFormat, io);
handleGetSnapshotById(subId, resp, outFormat, io);
} else if ("DELETE".equalsIgnoreCase(method)) {
handleDeleteSnapshotById(subId, req, resp, outFormat, io);
}
return;
} else if ("backups".equals(subPath)) {
if ("GET".equalsIgnoreCase(method)) {
handleGetBackupById(subId, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "GET", outFormat);
}
return;
} else if ("checkpoints".equals(subPath)) {
if ("DELETE".equalsIgnoreCase(method)) {
handleDeleteCheckpointById(subId, req, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "DELETE", outFormat);
}
return;
}
} else if (idAndSubPath.size() == 4) {
String subPath = idAndSubPath.get(1);
@ -189,6 +225,20 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
io.methodNotAllowed(resp, "POST", outFormat);
}
return;
} else if ("backups".equals(subPath) && "disks".equals(action)) {
if ("GET".equalsIgnoreCase(method)) {
handleGetBackupDisksById(subId, req, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "GET", outFormat);
}
return;
} else if ("backups".equals(subPath) && "finalize".equals(action)) {
if ("POST".equalsIgnoreCase(method)) {
handleFinalizeBackupById(id, subId, req, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "POST", outFormat);
}
return;
}
}
}
@ -405,8 +455,8 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
}
}
protected void handleGetSnapshotsById(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
protected void handleGetSnapshotById(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
Snapshot response = serverAdapter.getSnapshot(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
@ -435,7 +485,94 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
protected void handleRestoreSnapshotById(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
//ToDo: implement
String data = getRequestData(req);
io.badRequest(resp, "Not implemented", outFormat);
}
protected void handleGetBackupsByVmId(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
List<Backup> backups = serverAdapter.listBackupsByInstanceUuid(id);
NamedList<Backup> response = NamedList.of("backups", backups);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handlePostBackupForVmId(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String data = getRequestData(req);
try {
Backup request = io.getMapper().jsonMapper().readValue(data, Backup.class);
Backup response = serverAdapter.createInstanceBackup(id, request);
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleGetBackupById(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
Backup response = serverAdapter.getBackup(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleGetBackupDisksById(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
try {
List<Disk> disks = serverAdapter.listDisksByBackupUuid(id);
Disks response = new Disks(disks);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleFinalizeBackupById(final String vmId, final String backupId, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String data = getRequestData(req);
try {
serverAdapter.finalizeBackup(vmId, backupId, data);
io.getWriter().write(resp, HttpServletResponse.SC_OK, null, outFormat);
} catch (CloudRuntimeException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleGetCheckpointsByVmId(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
List<Checkpoint> checkpoints = serverAdapter.listCheckpointsByInstanceUuid(id);
Checkpoints response = new Checkpoints(checkpoints);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleDeleteCheckpointById(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String asyncStr = req.getParameter("async");
boolean async = !Boolean.FALSE.toString().equals(asyncStr);
try {
ResourceAction action = serverAdapter.deleteCheckpoint(id, async);
if (action != null) {
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, action, outFormat);
} else {
io.getWriter().write(resp, HttpServletResponse.SC_OK, null, outFormat);
}
} catch (CloudRuntimeException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -64,6 +64,7 @@ public class AsyncJobJoinVOToJobConverter {
job.setLastUpdated(System.currentTimeMillis());
job.setStartTime(vo.getCreated().getTime());
JobInfo.Status status = JobInfo.Status.values()[vo.getStatus()];
Long endTime = System.currentTimeMillis();
if (status == JobInfo.Status.SUCCEEDED) {
job.setStatus("finished");
job.setEndTime(System.currentTimeMillis());
@ -73,6 +74,10 @@ public class AsyncJobJoinVOToJobConverter {
job.setStatus("aborted");
} else {
job.setStatus("started");
endTime = null;
}
if (endTime != null) {
job.setEndTime(endTime);
}
job.setOwner(Ref.of(basePath + "/api/users/" + vo.getUserUuid(), vo.getUserUuid()));
job.setActions(new Actions());

View File

@ -0,0 +1,64 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.converter;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.cloudstack.backup.BackupVO;
import org.apache.cloudstack.veeam.VeeamControlService;
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
import org.apache.cloudstack.veeam.api.dto.Backup;
import org.apache.cloudstack.veeam.api.dto.Vm;
import com.cloud.vm.UserVmVO;
public class BackupVOToBackupConverter {
public static Backup toBackup(final BackupVO backupVO, final Function<Long, UserVmVO> vmResolver) {
Backup backup = new Backup();
final String basePath = VeeamControlService.ContextPath.value();
backup.setHref(basePath + VmsRouteHandler.BASE_ROUTE + "/backups/" + backupVO.getUuid());
backup.setId(backupVO.getUuid());
backup.setName(backupVO.getName());
backup.setDescription(backupVO.getDescription());
backup.setCreationDate(backupVO.getDate().getTime());
// backup.setPhase(backupVO.getPhase().name());
// if (backupVO.getFromCheckpointId() != null) {
// backup.setFromCheckpointId(backupVO.getFromCheckpointId().toString());
// }
// if (backupVO.getToCheckpointId() != null) {
// backup.setToCheckpointId(backupVO.getToCheckpointId().toString());
// }
if (vmResolver != null) {
final UserVmVO vmVO = vmResolver.apply(backupVO.getVmId());
if (vmVO != null) {
backup.setVm(Vm.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmVO.getUuid(), vmVO.getUuid()));
}
}
return backup;
}
public static List<Backup> toBackupList(final List<BackupVO> backupVOs, final Function<Long, UserVmVO> vmResolver) {
return backupVOs
.stream()
.map(backupVO -> toBackup(backupVO, vmResolver))
.collect(Collectors.toList());
}
}

View File

@ -27,8 +27,10 @@ import org.apache.cloudstack.veeam.api.ClustersRouteHandler;
import org.apache.cloudstack.veeam.api.DataCentersRouteHandler;
import org.apache.cloudstack.veeam.api.dto.Actions;
import org.apache.cloudstack.veeam.api.dto.Cluster;
import org.apache.cloudstack.veeam.api.dto.Cpu;
import org.apache.cloudstack.veeam.api.dto.Link;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.Version;
import com.cloud.api.query.vo.DataCenterJoinVO;
import com.cloud.dc.ClusterVO;
@ -43,115 +45,113 @@ public class ClusterVOToClusterConverter {
// - Prefer: store a UUID in details table and reuse it
// - Fallback: name-based UUID from "cluster:<id>"
final String clusterId = vo.getUuid();
c.id = clusterId;
c.href = basePath + ClustersRouteHandler.BASE_ROUTE + "/" + clusterId;
c.setId(clusterId);
c.setHref(basePath + ClustersRouteHandler.BASE_ROUTE + "/" + clusterId);
c.name = vo.getName();
c.description = vo.getName();
c.comment = "";
c.setName(vo.getName());
// --- sensible defaults (match your sample)
c.ballooningEnabled = "true";
c.biosType = "q35_ovmf"; // or "q35_secure_boot" if you want to align with VM BIOS you saw
c.fipsMode = "disabled";
c.firewallType = "firewalld";
c.glusterService = "false";
c.haReservation = "false";
c.switchType = "legacy";
c.threadsAsCores = "false";
c.trustedService = "false";
c.tunnelMigration = "false";
c.upgradeInProgress = "false";
c.upgradePercentComplete = "0";
c.virtService = "true";
c.vncEncryption = "false";
c.logMaxMemoryUsedThreshold = "95";
c.logMaxMemoryUsedThresholdType = "percentage";
c.setBallooningEnabled("true");
c.setBiosType("q35_ovmf"); // or "q35_secure_boot" if you want to align with VM BIOS you saw
c.setFipsMode("disabled");
c.setFirewallType("firewalld");
c.setGlusterService("false");
c.setHaReservation("false");
c.setSwitchType("legacy");
c.setThreadsAsCores("false");
c.setTrustedService("false");
c.setTunnelMigration("false");
c.setUpgradeInProgress("false");
c.setUpgradePercentComplete("0");
c.setVirtService("true");
c.setVncEncryption("false");
c.setLogMaxMemoryUsedThreshold("95");
c.setLogMaxMemoryUsedThresholdType("percentage");
// --- cpu (best-effort defaults)
final Cluster.ClusterCpu cpu = new Cluster.ClusterCpu();
cpu.architecture = "x86_64";
cpu.type = "x86_64"; // replace if you can detect host cpu model
c.cpu = cpu;
final Cpu cpu = new Cpu();
cpu.setArchitecture("x86_64");
cpu.setType("x86_64"); // replace if you can detect host cpu model
c.setCpu(cpu);
// --- version (ovirt engine version; keep fixed unless you want to expose something else)
final Cluster.Version ver = new Cluster.Version();
ver.major = "4";
ver.minor = "8";
c.version = ver;
final Version ver = new Version();
ver.setMajor(4);
ver.setMinor(8);
c.setVersion(ver);
// --- ksm / memory policy (defaults)
c.ksm = new Cluster.Ksm();
c.ksm.enabled = "true";
c.ksm.mergeAcrossNodes = "true";
c.setKsm(new Cluster.Ksm());
c.getKsm().enabled = "true";
c.getKsm().mergeAcrossNodes = "true";
c.memoryPolicy = new Cluster.MemoryPolicy();
c.memoryPolicy.overCommit = new Cluster.OverCommit();
c.memoryPolicy.overCommit.percent = "100";
c.memoryPolicy.transparentHugepages = new Cluster.TransparentHugepages();
c.memoryPolicy.transparentHugepages.enabled = "true";
c.setMemoryPolicy(new Cluster.MemoryPolicy());
c.getMemoryPolicy().overCommit = new Cluster.OverCommit();
c.getMemoryPolicy().overCommit.percent = "100";
c.getMemoryPolicy().transparentHugepages = new Cluster.TransparentHugepages();
c.getMemoryPolicy().transparentHugepages.enabled = "true";
// --- migration defaults
c.migration = new Cluster.Migration();
c.migration.autoConverge = "inherit";
c.migration.bandwidth = new Cluster.Bandwidth();
c.migration.bandwidth.assignmentMethod = "auto";
c.migration.compressed = "inherit";
c.migration.encrypted = "inherit";
c.migration.parallelMigrationsPolicy = "disabled";
c.setMigration(new Cluster.Migration());
c.getMigration().autoConverge = "inherit";
c.getMigration().bandwidth = new Cluster.Bandwidth();
c.getMigration().bandwidth.assignmentMethod = "auto";
c.getMigration().compressed = "inherit";
c.getMigration().encrypted = "inherit";
c.getMigration().parallelMigrationsPolicy = "disabled";
// policy ref (dummy but valid shape)
c.migration.policy = Ref.of(basePath + "/migrationpolicies/" + stableUuid("migrationpolicy:default"),
c.getMigration().policy = Ref.of(basePath + "/migrationpolicies/" + stableUuid("migrationpolicy:default"),
stableUuid("migrationpolicy:default")
);
// --- rng sources
c.requiredRngSources = new Cluster.RequiredRngSources();
c.requiredRngSources.requiredRngSource = Collections.singletonList("urandom");
c.setRequiredRngSources(new Cluster.RequiredRngSources());
c.getRequiredRngSources().requiredRngSource = Collections.singletonList("urandom");
// --- error handling
c.errorHandling = new Cluster.ErrorHandling();
c.errorHandling.onError = "migrate";
c.setErrorHandling(new Cluster.ErrorHandling());
c.getErrorHandling().onError = "migrate";
// --- fencing policy defaults
c.fencingPolicy = new Cluster.FencingPolicy();
c.fencingPolicy.enabled = "true";
c.fencingPolicy.skipIfConnectivityBroken = new Cluster.SkipIfConnectivityBroken();
c.fencingPolicy.skipIfConnectivityBroken.enabled = "false";
c.fencingPolicy.skipIfConnectivityBroken.threshold = "50";
c.fencingPolicy.skipIfGlusterBricksUp = "false";
c.fencingPolicy.skipIfGlusterQuorumNotMet = "false";
c.fencingPolicy.skipIfSdActive = new Cluster.SkipIfSdActive();
c.fencingPolicy.skipIfSdActive.enabled = "false";
c.setFencingPolicy(new Cluster.FencingPolicy());
c.getFencingPolicy().enabled = "true";
c.getFencingPolicy().skipIfConnectivityBroken = new Cluster.SkipIfConnectivityBroken();
c.getFencingPolicy().skipIfConnectivityBroken.enabled = "false";
c.getFencingPolicy().skipIfConnectivityBroken.threshold = "50";
c.getFencingPolicy().skipIfGlusterBricksUp = "false";
c.getFencingPolicy().skipIfGlusterQuorumNotMet = "false";
c.getFencingPolicy().skipIfSdActive = new Cluster.SkipIfSdActive();
c.getFencingPolicy().skipIfSdActive.enabled = "false";
// --- scheduling policy props (optional; dummy ok)
c.customSchedulingPolicyProperties = new Cluster.CustomSchedulingPolicyProperties();
c.setCustomSchedulingPolicyProperties(new Cluster.CustomSchedulingPolicyProperties());
final Cluster.Property p1 = new Cluster.Property(); p1.name = "HighUtilization"; p1.value = "80";
final Cluster.Property p2 = new Cluster.Property(); p2.name = "CpuOverCommitDurationMinutes"; p2.value = "2";
c.customSchedulingPolicyProperties.property = List.of(p1, p2);
c.getCustomSchedulingPolicyProperties().property = List.of(p1, p2);
// --- data_center ref mapping (CloudStack cluster -> pod -> zone)
if (dataCenterResolver != null) {
final DataCenterJoinVO zone = dataCenterResolver.apply(vo.getDataCenterId());
if (zone != null) {
c.dataCenter = Ref.of(basePath + DataCentersRouteHandler.BASE_ROUTE + "/" + zone.getUuid(), zone.getUuid());
c.setDataCenter(Ref.of(basePath + DataCentersRouteHandler.BASE_ROUTE + "/" + zone.getUuid(), zone.getUuid()));
}
}
// --- mac pool & scheduling policy refs (dummy but consistent)
c.macPool = Ref.of(basePath + "/macpools/" + stableUuid("macpool:default"),
stableUuid("macpool:default"));
c.schedulingPolicy = Ref.of(basePath + "/schedulingpolicies/" + stableUuid("schedpolicy:default"),
stableUuid("schedpolicy:default"));
c.setMacPool(Ref.of(basePath + "/macpools/" + stableUuid("macpool:default"),
stableUuid("macpool:default")));
c.setSchedulingPolicy(Ref.of(basePath + "/schedulingpolicies/" + stableUuid("schedpolicy:default"),
stableUuid("schedpolicy:default")));
// --- actions.links (can be omitted; but Veeam sometimes expects actions to exist)
final Actions actions = new Actions();
actions.link = Collections.emptyList();
c.actions = actions;
actions.setLink(Collections.emptyList());
c.setActions(actions);
// --- related links (optional)
c.link = List.of(
new Link("networks", c.href + "/networks")
);
c.setLink(List.of(
Link.of("networks", c.getHref() + "/networks")
));
return c;
}

View File

@ -41,32 +41,32 @@ public class DataCenterJoinVOToDataCenterConverter {
final DataCenter dc = new DataCenter();
// ---- Identity ----
dc.id = id;
dc.href = href;
dc.name = zone.getName();
dc.description = zone.getDescription();
dc.setId(id);
dc.setHref(href);
dc.setName(zone.getName());
dc.setDescription(zone.getDescription());
// ---- State ----
dc.status = Grouping.AllocationState.Enabled.equals(zone.getAllocationState()) ? "up" : "down";
dc.local = "false";
dc.quotaMode = "disabled";
dc.storageFormat = "v5";
dc.setStatus(Grouping.AllocationState.Enabled.equals(zone.getAllocationState()) ? "up" : "down");
dc.setLocal("false");
dc.setQuotaMode("disabled");
dc.setStorageFormat("v5");
// ---- Versions (static but valid) ----
final Version v48 = new Version();
v48.major = 4;
v48.minor = 8;
dc.version = v48;
dc.supportedVersions = new SupportedVersions(List.of(v48));
v48.setMajor(4);
v48.setMinor(8);
dc.setVersion(v48);
dc.setSupportedVersions(new SupportedVersions(List.of(v48)));
// ---- mac_pool (static placeholder) ----
dc.macPool = Ref.of(basePath + "/macpools/default","default");
dc.setMacPool(Ref.of(basePath + "/macpools/default", "default"));
// ---- Related links ----
dc.link = Arrays.asList(
new Link(href + "/clusters", "clusters"),
new Link(href + "/networks", "networks"),
new Link(href + "/storagedomains", "storagedomains")
Link.of(href + "/clusters", "clusters"),
Link.of(href + "/networks", "networks"),
Link.of(href + "/storagedomains", "storagedomains")
);
return dc;

View File

@ -68,12 +68,7 @@ public class HostJoinVOToHostConverter {
final Cpu cpu = new Cpu();
final Topology topo = new Topology();
// oVirt topology: sockets/cores/threads. We approximate.
// If CloudStack has cpuNumber = total cores, treat as sockets count w/ 1 core, 1 thread.
topo.sockets = vo.getCpuSockets();
topo.cores = vo.getCpus();
topo.threads = 1;
final Topology topo = new Topology(vo.getCpuSockets(), vo.getCpus(), 1);
// --- Memory ---
h.setMemory(String.valueOf(vo.getTotalMemory()));

View File

@ -85,9 +85,6 @@ public class ImageTransferVOToImageTransferConverter {
}
private static Link getLink(ImageTransfer it, String rel) {
final Link link = new Link();
link.rel = rel;
link.href = it.getHref() + "/" + rel;
return link;
return Link.of(rel, it.getHref() + "/" + rel);
}
}

View File

@ -31,6 +31,7 @@ import org.apache.cloudstack.veeam.api.dto.Nic;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.ReportedDevice;
import org.apache.cloudstack.veeam.api.dto.ReportedDevices;
import org.apache.cloudstack.veeam.api.dto.Vm;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@ -51,8 +52,9 @@ public class NicVOToNicConverter {
nic.setPlugged(Boolean.TRUE.toString());
nic.setSynced(Boolean.TRUE.toString());
if (StringUtils.isNotBlank(vmUuid)) {
nic.setVm(Ref.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid, vmUuid));
nic.setHref(nic.getVm().href + "/nics/" + vo.getUuid());
Vm vm = Vm.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid, vmUuid);
nic.setVm(vm);
nic.setHref(vm.getHref() + "/nics/" + vo.getUuid());
}
nic.setInterfaceType("virtio");
ReportedDevice device = getReportedDevice(vo, mac, nic.getVm());
@ -67,7 +69,7 @@ public class NicVOToNicConverter {
}
@NotNull
private static ReportedDevice getReportedDevice(NicVO vo, Mac mac, Ref vm) {
private static ReportedDevice getReportedDevice(NicVO vo, Mac mac, Vm vm) {
ReportedDevice device = new ReportedDevice();
device.setType("network");
device.setId(vo.getUuid());
@ -85,7 +87,7 @@ public class NicVOToNicConverter {
ip.setVersion("v6");
}
device.setIps(new Ips(List.of(ip)));
device.setHref(vm.href + "/reporteddevices/" + vo.getUuid());
device.setHref(vm.getHref() + "/reporteddevices/" + vo.getUuid());
device.setVm(vm);
return device;
}

View File

@ -41,47 +41,45 @@ public class StoreVOToStorageDomainConverter {
final String id = pool.getUuid();
StorageDomain sd = new StorageDomain();
sd.id = id;
sd.setId(id);
final String href = href(basePath, ApiService.BASE_ROUTE + "/storagedomains/" + id);
sd.href = href;
sd.setHref(href);
sd.name = pool.getName();
sd.description = ""; // oVirt often returns empty string
sd.comment = "";
sd.setName(pool.getName());
// oVirt sample returns numbers as strings
sd.available = Long.toString(pool.getCapacityBytes() - pool.getUsedBytes());
sd.used = Long.toString(pool.getUsedBytes());
sd.committed = Long.toString(pool.getCapacityBytes());
sd.setAvailable(Long.toString(pool.getCapacityBytes() - pool.getUsedBytes()));
sd.setUsed(Long.toString(pool.getUsedBytes()));
sd.setCommitted(Long.toString(pool.getCapacityBytes()));
sd.type = "data";
sd.status = mapPoolStatus(pool); // "active"/"inactive"/"maintenance" (approx)
sd.master = "true"; // if you dont have a concept, choose stable default
sd.backup = "false";
sd.setType("data");
sd.setStatus(mapPoolStatus(pool)); // "active"/"inactive"/"maintenance" (approx)
sd.setMaster("true"); // if you dont have a concept, choose stable default
sd.setBackup("false");
sd.blockSize = "512"; // stable default unless you can compute it
sd.externalStatus = "ok";
sd.storageFormat = "v5";
sd.setBlockSize("512"); // stable default unless you can compute it
sd.setExternalStatus("ok");
sd.setStorageFormat("v5");
sd.discardAfterDelete = "false";
sd.wipeAfterDelete = "false";
sd.supportsDiscard = "false";
sd.supportsDiscardZeroesData = "false";
sd.setDiscardAfterDelete("false");
sd.setWipeAfterDelete("false");
sd.setSupportsDiscard("false");
sd.setSupportsDiscardZeroesData("false");
sd.warningLowSpaceIndicator = "10";
sd.criticalSpaceActionBlocker = "5";
sd.setWarningLowSpaceIndicator("10");
sd.setCriticalSpaceActionBlocker("5");
// Nested storage (try to extract if available)
sd.storage = buildPrimaryStorage(pool);
sd.setStorage(buildPrimaryStorage(pool));
// dc attachment
String dcId = pool.getZoneUuid();
DataCenter dc = new DataCenter();
dc.href = href(basePath, DataCentersRouteHandler.BASE_ROUTE + "/" + dcId);
dc.id = dcId;
sd.dataCenters = new DataCenters(List.of(dc));
dc.setHref(href(basePath, DataCentersRouteHandler.BASE_ROUTE + "/" + dcId));
dc.setId(dcId);
sd.setDataCenters(new DataCenters(List.of(dc)));
sd.link = defaultStorageDomainLinks(href, true, /*includeTemplates*/ true);
sd.setLink(defaultStorageDomainLinks(href, true, /*includeTemplates*/ true));
return sd;
}
@ -97,46 +95,44 @@ public class StoreVOToStorageDomainConverter {
final String id = store.getUuid();
StorageDomain sd = new StorageDomain();
sd.id = id;
sd.setId(id);
final String href = href(basePath, ApiService.BASE_ROUTE + "/storagedomains/" + id);
sd.href = href;
sd.setHref(href);
sd.name = store.getName();
sd.description = "";
sd.comment = "";
sd.setName(store.getName());
// Many image repos dont have these values readily; keep as "0" or omit (null)
sd.committed = "0";
sd.available = null; // oVirts glance example omitted available/used
sd.used = null;
sd.setCommitted("0");
sd.setAvailable(null); // oVirts glance example omitted available/used
sd.setUsed(null);
sd.type = "image";
sd.status = "unattached"; // matches your sample for glance-like repo
sd.master = "false";
sd.backup = "false";
sd.setType("image");
sd.setStatus("unattached"); // matches your sample for glance-like repo
sd.setMaster("false");
sd.setBackup("false");
sd.blockSize = "512";
sd.externalStatus = "ok";
sd.storageFormat = "v1";
sd.setBlockSize("512");
sd.setExternalStatus("ok");
sd.setStorageFormat("v1");
sd.discardAfterDelete = "false";
sd.wipeAfterDelete = "false";
sd.supportsDiscard = "false";
sd.supportsDiscardZeroesData = "false";
sd.setDiscardAfterDelete("false");
sd.setWipeAfterDelete("false");
sd.setSupportsDiscard("false");
sd.setSupportsDiscardZeroesData("false");
sd.warningLowSpaceIndicator = "0";
sd.criticalSpaceActionBlocker = "0";
sd.setWarningLowSpaceIndicator("0");
sd.setCriticalSpaceActionBlocker("0");
sd.storage = buildImageStoreStorage(store);
sd.setStorage(buildImageStoreStorage(store));
// Optionally include dc attachment (your first object had it; second didnt)
String dcId = store.getZoneUuid();
DataCenter dc = new DataCenter();
dc.href = href(basePath, DataCentersRouteHandler.BASE_ROUTE + "/" + dcId);
dc.id = dcId;
sd.dataCenters = new DataCenters(List.of(dc));
dc.setHref(href(basePath, DataCentersRouteHandler.BASE_ROUTE + "/" + dcId));
dc.setId(dcId);
sd.setDataCenters(new DataCenters(List.of(dc)));
sd.link = defaultStorageDomainLinks(href, false, /*includeTemplates*/ false);
sd.setLink(defaultStorageDomainLinks(href, false, /*includeTemplates*/ false));
return sd;
}
@ -149,7 +145,7 @@ public class StoreVOToStorageDomainConverter {
private static Storage buildPrimaryStorage(StoragePoolJoinVO pool) {
Storage st = new Storage();
st.type = mapPrimaryStorageType(pool);
st.setType(mapPrimaryStorageType(pool));
// If you can parse details/url, fill these. If not, keep empty strings like oVirt.
// For NFS pools in CloudStack, URL is often like: nfs://10.0.32.4/path or 10.0.32.4:/path
@ -158,12 +154,12 @@ public class StoreVOToStorageDomainConverter {
url = pool.getHostAddress(); // sometimes exists in VO; if not, ignore
} catch (Exception ignored) { }
if ("nfs".equals(st.type)) {
if ("nfs".equals(st.getType())) {
// best-effort placeholders
st.address = ""; // fill if you can parse
st.path = ""; // fill if you can parse
st.mountOptions = "";
st.nfsVersion = "auto";
st.setAddress(""); // fill if you can parse
st.setPath(""); // fill if you can parse
st.setMountOptions("");
st.setNfsVersion("auto");
}
return st;
}
@ -173,13 +169,13 @@ public class StoreVOToStorageDomainConverter {
// Match your sample: glance store => type=glance
// If you want "nfs" for secondary, map based on provider/protocol instead.
st.type = mapImageStorageType(store);
st.setType(mapImageStorageType(store));
if ("nfs".equals(st.type)) {
st.address = "";
st.path = "";
st.mountOptions = "";
st.nfsVersion = "auto";
if ("nfs".equals(st.getType())) {
st.setAddress("");
st.setPath("");
st.setMountOptions("");
st.setNfsVersion("auto");
}
return st;
}
@ -188,19 +184,19 @@ public class StoreVOToStorageDomainConverter {
// Mirrors the rels you pasted; keep stable order.
// You can add/remove based on what endpoints you actually implement.
List<Link> common = new java.util.ArrayList<>();
common.add(new Link("diskprofiles", href(basePath, "/diskprofiles")));
common.add(Link.of("diskprofiles", href(basePath, "/diskprofiles")));
if (includeDisks) {
common.add(new Link("disks", href(basePath, "/disks")));
common.add(new Link("storageconnections", href(basePath, "/storageconnections")));
common.add(Link.of("disks", href(basePath, "/disks")));
common.add(Link.of("storageconnections", href(basePath, "/storageconnections")));
}
common.add(new Link("permissions", href(basePath, "/permissions")));
common.add(Link.of("permissions", href(basePath, "/permissions")));
if (includeTemplates) {
common.add(new Link("templates", href(basePath, "/templates")));
common.add(new Link("vms", href(basePath, "/vms")));
common.add(Link.of("templates", href(basePath, "/templates")));
common.add(Link.of("vms", href(basePath, "/vms")));
} else {
common.add(new Link("images", href(basePath, "/images")));
common.add(Link.of("images", href(basePath, "/images")));
}
common.add(new Link("disksnapshots", href(basePath, "/disksnapshots")));
common.add(Link.of("disksnapshots", href(basePath, "/disksnapshots")));
return common;
}

View File

@ -65,18 +65,18 @@ public final class UserVmJoinVOToVmConverter {
final String basePath = VeeamControlService.ContextPath.value();
final Vm dst = new Vm();
dst.id = src.getUuid();
dst.name = StringUtils.firstNonBlank(src.getName(), src.getInstanceName());
dst.setId(src.getUuid());
dst.setName(StringUtils.firstNonBlank(src.getName(), src.getInstanceName()));
// CloudStack doesn't really have "description" for VM; displayName is closest
dst.description = src.getDisplayName();
dst.href = basePath + VmsRouteHandler.BASE_ROUTE + "/" + src.getUuid();
dst.status = mapStatus(src.getState());
dst.setDescription(src.getDisplayName());
dst.setHref(basePath + VmsRouteHandler.BASE_ROUTE + "/" + src.getUuid());
dst.setStatus(mapStatus(src.getState()));
dst.setCreationTime(src.getCreated().getTime());
final Date lastUpdated = src.getLastUpdated() != null ? src.getLastUpdated() : src.getCreated();
if ("down".equals(dst.status)) {
dst.stopTime = lastUpdated.getTime();
if ("down".equals(dst.getStatus())) {
dst.setStopTime(lastUpdated.getTime());
}
if ("up".equals(dst.status)) {
if ("up".equals(dst.getStatus())) {
dst.setStartTime(lastUpdated.getTime());
}
final Ref template = buildRef(
@ -84,40 +84,45 @@ public final class UserVmJoinVOToVmConverter {
"templates",
src.getTemplateUuid()
);
dst.template = template;
dst.originalTemplate = template;
dst.setTemplate(template);
dst.setOriginalTemplate(template);
if (StringUtils.isNotBlank(src.getHostUuid())) {
dst.host = buildRef(
dst.setHost(buildRef(
basePath + ApiService.BASE_ROUTE,
"hosts",
src.getHostUuid());
src.getHostUuid()));
}
if (hostResolver != null) {
HostJoinVO hostVo = hostResolver.apply(src.getHostId() == null ? src.getLastHostId() : src.getHostId());
if (hostVo != null) {
dst.host = buildRef(
dst.setHost(buildRef(
basePath + ApiService.BASE_ROUTE,
"hosts",
hostVo.getUuid());
dst.cluster = buildRef(
hostVo.getUuid()));
dst.setCluster(buildRef(
basePath + ApiService.BASE_ROUTE,
"clusters",
hostVo.getClusterUuid());
hostVo.getClusterUuid()));
}
}
dst.memory = String.valueOf(src.getRamSize() * 1024L * 1024L);
dst.cpu = new Cpu(src.getArch(), new Topology(src.getCpu(), 1, 1));
dst.os = new Os();
dst.os.type = src.getGuestOsId() % 2 == 0
dst.setMemory(String.valueOf(src.getRamSize() * 1024L * 1024L));
Cpu cpu = new Cpu();
cpu.setArchitecture(src.getArch());
cpu.setTopology(new Topology(src.getCpu(), 1, 1));
dst.setCpu(cpu);
Os os = new Os();
os.setType(src.getGuestOsId() % 2 == 0
? "windows"
: "linux";
dst.bios = new Bios();
dst.bios.type = "q35_secure_boot";
dst.type = "desktop";
dst.origin = "ovirt";
: "linux");
dst.setOs(os);
Bios bios = new Bios();
bios.setType("q35_secure_boot");
dst.setBios(bios);
dst.setType("desktop");
dst.setOrigin("ovirt");
dst.setStateless("false");
if (disksResolver != null) {
List<DiskAttachment> diskAttachments = disksResolver.apply(src.getId());
@ -129,18 +134,18 @@ public final class UserVmJoinVOToVmConverter {
dst.setNics(new Nics(nics));
}
dst.actions = new Actions(List.of(
BaseDto.getActionLink("start", dst.href),
BaseDto.getActionLink("stop", dst.href),
BaseDto.getActionLink("shutdown", dst.href)
dst.setActions(new Actions(List.of(
BaseDto.getActionLink("start", dst.getHref()),
BaseDto.getActionLink("stop", dst.getHref()),
BaseDto.getActionLink("shutdown", dst.getHref())
)));
dst.setLink(List.of(
BaseDto.getActionLink("diskattachments", dst.getHref()),
BaseDto.getActionLink("nics", dst.getHref()),
BaseDto.getActionLink("reporteddevices", dst.getHref()),
BaseDto.getActionLink("snapshots", dst.getHref())
));
dst.link = List.of(
BaseDto.getActionLink("diskattachments", dst.href),
BaseDto.getActionLink("nics", dst.href),
BaseDto.getActionLink("reporteddevices", dst.href),
BaseDto.getActionLink("snapshots", dst.href)
);
dst.tags = new EmptyElement();
dst.setTags(new EmptyElement());
return dst;
}
@ -173,9 +178,6 @@ public final class UserVmJoinVOToVmConverter {
if (StringUtils.isBlank(id)) {
return null;
}
final Ref r = new Ref();
r.id = id;
r.href = (baseHref != null) ? (baseHref + "/" + suffix + "/" + id) : null;
return r;
return Ref.of((baseHref != null) ? (baseHref + "/" + suffix + "/" + id) : null, id);
}
}

View File

@ -24,8 +24,8 @@ import org.apache.cloudstack.veeam.VeeamControlService;
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
import org.apache.cloudstack.veeam.api.dto.Actions;
import org.apache.cloudstack.veeam.api.dto.BaseDto;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.Snapshot;
import org.apache.cloudstack.veeam.api.dto.Vm;
import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.VMSnapshotVO;
@ -36,7 +36,7 @@ public class VmSnapshotVOToSnapshotConverter {
final Snapshot snapshot = new Snapshot();
snapshot.setId(vmSnapshotVO.getUuid());
snapshot.setHref(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid + "/snapshots/" + vmSnapshotVO.getUuid());
snapshot.setVm(Ref.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid, vmUuid));
snapshot.setVm(Vm.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid, vmUuid));
snapshot.setDescription(vmSnapshotVO.getDescription());
snapshot.setSnapshotType("active");
snapshot.setDate(vmSnapshotVO.getCreated().getTime());

View File

@ -30,6 +30,9 @@ import org.apache.cloudstack.veeam.api.dto.Disk;
import org.apache.cloudstack.veeam.api.dto.DiskAttachment;
import org.apache.cloudstack.veeam.api.dto.Link;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.StorageDomain;
import org.apache.cloudstack.veeam.api.dto.StorageDomains;
import org.apache.cloudstack.veeam.api.dto.Vm;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.VolumeJoinVO;
@ -45,22 +48,22 @@ public class VolumeJoinVOToDiskConverter {
final String diskId = vol.getUuid();
final String diskHref = basePath + DisksRouteHandler.BASE_ROUTE + "/" + diskId;
disk.id = diskId;
disk.href = diskHref;
disk.setId(diskId);
disk.setHref(diskHref);
disk.setBootable(String.valueOf(Volume.Type.ROOT.equals(vol.getVolumeType())));
// Names
disk.name = vol.getName();
disk.alias = vol.getName();
disk.description = vol.getName();
disk.setName(vol.getName());
disk.setAlias(vol.getName());
disk.setDescription(vol.getName());
// Sizes (bytes)
final long size = vol.getSize();
final long actualSize = vol.getVolumeStoreSize();
disk.provisionedSize = String.valueOf(size);
disk.actualSize = String.valueOf(actualSize);
disk.totalSize = String.valueOf(size);
disk.setProvisionedSize(String.valueOf(size));
disk.setActualSize(String.valueOf(actualSize));
disk.setTotalSize(String.valueOf(size));
VolumeStats vs = null;
if (List.of(Storage.ImageFormat.VHD, Storage.ImageFormat.QCOW2, Storage.ImageFormat.RAW).contains(vol.getFormat())) {
if (vol.getPath() != null) {
@ -72,56 +75,54 @@ public class VolumeJoinVOToDiskConverter {
}
}
if (vs != null) {
disk.totalSize = String.valueOf(vs.getVirtualSize());
disk.actualSize = String.valueOf(vs.getPhysicalSize());
disk.setTotalSize(String.valueOf(vs.getVirtualSize()));
disk.setActualSize(String.valueOf(vs.getPhysicalSize()));
}
// Disk format
disk.format = mapFormat(vol.getFormat());
disk.qcowVersion = "qcow2_v3";
disk.setFormat(mapFormat(vol.getFormat()));
disk.setQcowVersion("qcow2_v3");
// Content & storage
disk.contentType = "data";
disk.storageType = "image";
disk.sparse = "true";
disk.shareable = "false";
disk.setContentType("data");
disk.setStorageType("image");
disk.setSparse("true");
disk.setShareable("false");
// Status
disk.status = mapStatus(vol.getState());
disk.setStatus(mapStatus(vol.getState()));
// Backup-related flags (safe defaults)
disk.backup = "none";
disk.propagateErrors = "false";
disk.wipeAfterDelete = "false";
disk.setBackup("none");
disk.setPropagateErrors("false");
disk.setWipeAfterDelete("false");
// Image ID (best-effort)
disk.imageId = vol.getPath(); // acceptable placeholder
disk.setImageId(vol.getPath()); // acceptable placeholder
// Disk profile (optional)
disk.diskProfile = Ref.of(
disk.setDiskProfile(Ref.of(
apiBasePath + "/diskprofiles/" + vol.getDiskOfferingUuid(),
String.valueOf(vol.getDiskOfferingUuid())
);
));
// Storage domains
if (vol.getPoolUuid() != null) {
Disk.StorageDomains sds = new Disk.StorageDomains();
sds.storageDomain = List.of(
Ref.of(
apiBasePath + "/storagedomains/" + vol.getPoolUuid(),
vol.getPoolUuid()
)
);
disk.storageDomains = sds;
StorageDomains sds = new StorageDomains();
StorageDomain sd = new StorageDomain();
sd.setHref(apiBasePath + "/storagedomains/" + vol.getPoolUuid());
sd.setId(vol.getPoolUuid());
sds.setStorageDomain(List.of(sd));
disk.setStorageDomains(sds);
}
// Actions (Veeam checks presence, not behavior)
disk.actions = defaultDiskActions(diskHref);
disk.setActions(defaultDiskActions(diskHref));
// Links
disk.link = List.of(
new Link("disksnapshots", diskHref + "/disksnapshots")
);
disk.setLink(List.of(
Link.of("disksnapshots", diskHref + "/disksnapshots")
));
return disk;
}
@ -137,24 +138,21 @@ public class VolumeJoinVOToDiskConverter {
final String basePath = VeeamControlService.ContextPath.value();
final String diskAttachmentId = vol.getUuid();
da.vm = Ref.of(
basePath + VmsRouteHandler.BASE_ROUTE + "/" + vol.getVmUuid(),
vol.getVmUuid()
);
da.setVm(Vm.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vol.getVmUuid(), vol.getVmUuid()));
da.id = diskAttachmentId;
da.href = da.vm.href + "/diskattachments/" + diskAttachmentId;;
da.setId(diskAttachmentId);
da.setHref(da.getVm().getHref() + "/diskattachments/" + diskAttachmentId);;
// Links
da.disk = toDisk(vol);
da.setDisk(toDisk(vol));
// Properties
da.active = "true";
da.bootable = "false";
da.iface = "virtio_scsi";
da.logicalName = vol.getName();
da.readOnly = "false";
da.passDiscard = "false";
da.setActive("true");
da.setBootable(String.valueOf(Volume.Type.ROOT.equals(vol.getVolumeType())));
da.setIface("virtio_scsi");
da.setLogicalName(vol.getName());
da.setReadOnly("false");
da.setPassDiscard("false");
return da;
}

View File

@ -23,11 +23,19 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Actions {
public List<Link> link;
private List<Link> link;
public Actions() {}
public Actions(final List<Link> link) {
this.link = link;
}
public List<Link> getLink() {
return link;
}
public void setLink(List<Link> link) {
this.link = link;
}
}

View File

@ -21,42 +21,84 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
/**
* Root response for GET /ovirt-engine/api
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "api")
public final class Api {
// <link .../> repeated
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link;
private List<Link> link;
private EmptyElement engineBackup;
private ProductInfo productInfo;
private SpecialObjects specialObjects;
private ApiSummary summary;
private Long time;
private Ref authenticatedUser;
private Ref effectiveUser;
// <engine_backup/> (empty element)
@JacksonXmlProperty(localName = "engine_backup")
public EmptyElement engineBackup;
public List<Link> getLink() {
return link;
}
@JacksonXmlProperty(localName = "product_info")
public ProductInfo productInfo;
public void setLink(List<Link> link) {
this.link = link;
}
@JacksonXmlProperty(localName = "special_objects")
public SpecialObjects specialObjects;
public EmptyElement getEngineBackup() {
return engineBackup;
}
@JacksonXmlProperty(localName = "summary")
public ApiSummary summary;
public void setEngineBackup(EmptyElement engineBackup) {
this.engineBackup = engineBackup;
}
// Keep as String to avoid timezone/date parsing friction; you control formatting.
@JacksonXmlProperty(localName = "time")
public Long time;
public ProductInfo getProductInfo() {
return productInfo;
}
@JacksonXmlProperty(localName = "authenticated_user")
public Ref authenticatedUser;
public void setProductInfo(ProductInfo productInfo) {
this.productInfo = productInfo;
}
@JacksonXmlProperty(localName = "effective_user")
public Ref effectiveUser;
public SpecialObjects getSpecialObjects() {
return specialObjects;
}
public Api() {}
public void setSpecialObjects(SpecialObjects specialObjects) {
this.specialObjects = specialObjects;
}
public ApiSummary getSummary() {
return summary;
}
public void setSummary(ApiSummary summary) {
this.summary = summary;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
public Ref getAuthenticatedUser() {
return authenticatedUser;
}
public void setAuthenticatedUser(Ref authenticatedUser) {
this.authenticatedUser = authenticatedUser;
}
public Ref getEffectiveUser() {
return effectiveUser;
}
public void setEffectiveUser(Ref effectiveUser) {
this.effectiveUser = effectiveUser;
}
}

View File

@ -18,22 +18,44 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class ApiSummary {
@JacksonXmlProperty(localName = "hosts")
public SummaryCount hosts;
private SummaryCount hosts;
private SummaryCount storageDomains;
private SummaryCount users;
private SummaryCount vms;
@JacksonXmlProperty(localName = "storage_domains")
public SummaryCount storageDomains;
public SummaryCount getHosts() {
return hosts;
}
@JacksonXmlProperty(localName = "users")
public SummaryCount users;
public void setHosts(SummaryCount hosts) {
this.hosts = hosts;
}
@JacksonXmlProperty(localName = "vms")
public SummaryCount vms;
public SummaryCount getStorageDomains() {
return storageDomains;
}
public ApiSummary() {}
public void setStorageDomains(SummaryCount storageDomains) {
this.storageDomains = storageDomains;
}
public SummaryCount getUsers() {
return users;
}
public void setUsers(SummaryCount users) {
this.users = users;
}
public SummaryCount getVms() {
return vms;
}
public void setVms(SummaryCount vms) {
this.vms = vms;
}
}

View File

@ -17,20 +17,69 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
public class Backup extends BaseDto {
public class Backup {
private String name;
private String description;
private Long creationDate;
private Vm vm;
private String phase;
private String fromCheckpointId;
private String toCheckpointId;
@JsonProperty("creation_date")
@JacksonXmlProperty(localName = "creation_date")
private String creationDate;
public String getName() {
return name;
}
public String getCreationDate() {
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Long getCreationDate() {
return creationDate;
}
public void setCreationDate(String creationDate) {
public void setCreationDate(Long creationDate) {
this.creationDate = creationDate;
}
public Vm getVm() {
return vm;
}
public void setVm(Vm vm) {
this.vm = vm;
}
public String getPhase() {
return phase;
}
public void setPhase(String phase) {
this.phase = phase;
}
public String getFromCheckpointId() {
return fromCheckpointId;
}
public void setFromCheckpointId(String fromCheckpointId) {
this.fromCheckpointId = fromCheckpointId;
}
public String getToCheckpointId() {
return toCheckpointId;
}
public void setToCheckpointId(String toCheckpointId) {
this.toCheckpointId = toCheckpointId;
}
}

View File

@ -17,22 +17,16 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class SpecialObjectRef {
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@JacksonXmlProperty(isAttribute = true, localName = "href")
public String href;
public class Backups {
@JacksonXmlProperty(isAttribute = true, localName = "id")
public String id;
@JacksonXmlElementWrapper(useWrapping = false)
public List<Backup> backup;
public SpecialObjectRef() {}
public SpecialObjectRef(String href, String id) {
this.href = href;
this.id = id;
public Backups(final List<Backup> backup) {
this.backup = backup;
}
}

View File

@ -42,6 +42,6 @@ public class BaseDto {
}
public static Link getActionLink(final String action, final String baseHref) {
return new Link(action, baseHref + "/" + action);
return Link.of(action, baseHref + "/" + action);
}
}

View File

@ -21,13 +21,23 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Bios {
public String type; // "uefi" or "bios" or whatever mapping you choose
public BootMenu bootMenu = new BootMenu();
private String type; // "uefi" or "bios" or whatever mapping you choose
private BootMenu bootMenu = new BootMenu();
public Bios() {}
public String getType() {
return type;
}
public Bios(final String type) {
public void setType(String type) {
this.type = type;
}
public BootMenu getBootMenu() {
return bootMenu;
}
public void setBootMenu(BootMenu bootMenu) {
this.bootMenu = bootMenu;
}
}

View File

@ -22,5 +22,13 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BootMenu {
public String enabled = "false";
private String enabled = "false";
public String getEnabled() {
return enabled;
}
public void setEnabled(String enabled) {
this.enabled = enabled;
}
}

View File

@ -18,14 +18,10 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Certificate {
@JsonProperty("organization")
private String organization;
@JsonProperty("subject")
private String subject;
public String getOrganization() { return organization; }

View File

@ -0,0 +1,76 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.dto;
public class Checkpoint extends BaseDto {
private String name;
private String description;
private String creationDate;
private Vm vm;
private String state;
private String parentId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCreationDate() {
return creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
public Vm getVm() {
return vm;
}
public void setVm(Vm vm) {
this.vm = vm;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
}

View File

@ -17,24 +17,26 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OsVersion {
@JsonProperty("full_version")
private String fullVersion;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@JsonProperty("major")
private String major;
public class Checkpoints {
@JsonProperty("minor")
private String minor;
@JacksonXmlElementWrapper(useWrapping = false)
private List<Checkpoint> checkpoint;
public String getFullVersion() { return fullVersion; }
public void setFullVersion(String fullVersion) { this.fullVersion = fullVersion; }
public String getMajor() { return major; }
public void setMajor(String major) { this.major = major; }
public String getMinor() { return minor; }
public void setMinor(String minor) { this.minor = minor; }
public Checkpoints() {}
public Checkpoints(final List<Checkpoint> checkpoint) {
this.checkpoint = checkpoint;
}
public List<Checkpoint> getCheckpoint() {
return checkpoint;
}
public void setCheckpoint(List<Checkpoint> checkpoint) {
this.checkpoint = checkpoint;
}
}

View File

@ -20,148 +20,315 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "cluster")
public final class Cluster {
// --- common identity
public String href;
public String id;
public String name;
public String description;
public String comment;
// --- oVirt-ish knobs (strings in oVirt JSON)
@JsonProperty("ballooning_enabled")
@JacksonXmlProperty(localName = "ballooning_enabled")
public String ballooningEnabled; // "true"/"false"
@JsonProperty("bios_type")
@JacksonXmlProperty(localName = "bios_type")
public String biosType; // e.g. "q35_ovmf"
public ClusterCpu cpu;
@JsonProperty("custom_scheduling_policy_properties")
@JacksonXmlProperty(localName = "custom_scheduling_policy_properties")
public CustomSchedulingPolicyProperties customSchedulingPolicyProperties;
@JsonProperty("error_handling")
@JacksonXmlProperty(localName = "error_handling")
public ErrorHandling errorHandling;
@JsonProperty("fencing_policy")
@JacksonXmlProperty(localName = "fencing_policy")
public FencingPolicy fencingPolicy;
@JsonProperty("fips_mode")
@JacksonXmlProperty(localName = "fips_mode")
public String fipsMode; // "disabled"
@JsonProperty("firewall_type")
@JacksonXmlProperty(localName = "firewall_type")
public String firewallType; // "firewalld"
@JsonProperty("gluster_service")
@JacksonXmlProperty(localName = "gluster_service")
public String glusterService;
@JsonProperty("ha_reservation")
@JacksonXmlProperty(localName = "ha_reservation")
public String haReservation;
public Ksm ksm;
@JsonProperty("log_max_memory_used_threshold")
@JacksonXmlProperty(localName = "log_max_memory_used_threshold")
public String logMaxMemoryUsedThreshold;
@JsonProperty("log_max_memory_used_threshold_type")
@JacksonXmlProperty(localName = "log_max_memory_used_threshold_type")
public String logMaxMemoryUsedThresholdType;
@JsonProperty("memory_policy")
@JacksonXmlProperty(localName = "memory_policy")
public MemoryPolicy memoryPolicy;
public Migration migration;
@JsonProperty("required_rng_sources")
@JacksonXmlProperty(localName = "required_rng_sources")
public RequiredRngSources requiredRngSources;
@JsonProperty("switch_type")
@JacksonXmlProperty(localName = "switch_type")
public String switchType;
@JsonProperty("threads_as_cores")
@JacksonXmlProperty(localName = "threads_as_cores")
public String threadsAsCores;
@JsonProperty("trusted_service")
@JacksonXmlProperty(localName = "trusted_service")
public String trustedService;
@JsonProperty("tunnel_migration")
@JacksonXmlProperty(localName = "tunnel_migration")
public String tunnelMigration;
@JsonProperty("upgrade_in_progress")
@JacksonXmlProperty(localName = "upgrade_in_progress")
public String upgradeInProgress;
@JsonProperty("upgrade_percent_complete")
@JacksonXmlProperty(localName = "upgrade_percent_complete")
public String upgradePercentComplete;
public Version version;
@JsonProperty("virt_service")
@JacksonXmlProperty(localName = "virt_service")
public String virtService;
@JsonProperty("vnc_encryption")
@JacksonXmlProperty(localName = "vnc_encryption")
public String vncEncryption;
// --- references
@JsonProperty("data_center")
@JacksonXmlProperty(localName = "data_center")
public Ref dataCenter;
@JsonProperty("mac_pool")
@JacksonXmlProperty(localName = "mac_pool")
public Ref macPool;
@JsonProperty("scheduling_policy")
@JacksonXmlProperty(localName = "scheduling_policy")
public Ref schedulingPolicy;
// --- actions + links
public Actions actions;
public final class Cluster extends BaseDto {
private String name;
private String description;
private String comment;
private String ballooningEnabled;
private String biosType;
private Cpu cpu;
private CustomSchedulingPolicyProperties customSchedulingPolicyProperties;
private ErrorHandling errorHandling;
private FencingPolicy fencingPolicy;
private String fipsMode; // "disabled"
private String firewallType; // "firewalld"
private String glusterService;
private String haReservation;
private Ksm ksm;
private String logMaxMemoryUsedThreshold;
private String logMaxMemoryUsedThresholdType;
private MemoryPolicy memoryPolicy;
private Migration migration;
private RequiredRngSources requiredRngSources;
private String switchType;
private String threadsAsCores;
private String trustedService;
private String tunnelMigration;
private String upgradeInProgress;
private String upgradePercentComplete;
private Version version;
private String virtService;
private String vncEncryption;
private Ref dataCenter;
private Ref macPool;
private Ref schedulingPolicy;
private Actions actions;
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link;
private List<Link> link;
public Cluster() {}
public String getName() {
return name;
}
// ===== nested DTOs =====
public void setName(String name) {
this.name = name;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class ClusterCpu {
public String architecture;
public String type;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getBallooningEnabled() {
return ballooningEnabled;
}
public void setBallooningEnabled(String ballooningEnabled) {
this.ballooningEnabled = ballooningEnabled;
}
public String getBiosType() {
return biosType;
}
public void setBiosType(String biosType) {
this.biosType = biosType;
}
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
public CustomSchedulingPolicyProperties getCustomSchedulingPolicyProperties() {
return customSchedulingPolicyProperties;
}
public void setCustomSchedulingPolicyProperties(CustomSchedulingPolicyProperties customSchedulingPolicyProperties) {
this.customSchedulingPolicyProperties = customSchedulingPolicyProperties;
}
public ErrorHandling getErrorHandling() {
return errorHandling;
}
public void setErrorHandling(ErrorHandling errorHandling) {
this.errorHandling = errorHandling;
}
public FencingPolicy getFencingPolicy() {
return fencingPolicy;
}
public void setFencingPolicy(FencingPolicy fencingPolicy) {
this.fencingPolicy = fencingPolicy;
}
public String getFipsMode() {
return fipsMode;
}
public void setFipsMode(String fipsMode) {
this.fipsMode = fipsMode;
}
public String getFirewallType() {
return firewallType;
}
public void setFirewallType(String firewallType) {
this.firewallType = firewallType;
}
public String getGlusterService() {
return glusterService;
}
public void setGlusterService(String glusterService) {
this.glusterService = glusterService;
}
public String getHaReservation() {
return haReservation;
}
public void setHaReservation(String haReservation) {
this.haReservation = haReservation;
}
public Ksm getKsm() {
return ksm;
}
public void setKsm(Ksm ksm) {
this.ksm = ksm;
}
public String getLogMaxMemoryUsedThreshold() {
return logMaxMemoryUsedThreshold;
}
public void setLogMaxMemoryUsedThreshold(String logMaxMemoryUsedThreshold) {
this.logMaxMemoryUsedThreshold = logMaxMemoryUsedThreshold;
}
public String getLogMaxMemoryUsedThresholdType() {
return logMaxMemoryUsedThresholdType;
}
public void setLogMaxMemoryUsedThresholdType(String logMaxMemoryUsedThresholdType) {
this.logMaxMemoryUsedThresholdType = logMaxMemoryUsedThresholdType;
}
public MemoryPolicy getMemoryPolicy() {
return memoryPolicy;
}
public void setMemoryPolicy(MemoryPolicy memoryPolicy) {
this.memoryPolicy = memoryPolicy;
}
public Migration getMigration() {
return migration;
}
public void setMigration(Migration migration) {
this.migration = migration;
}
public RequiredRngSources getRequiredRngSources() {
return requiredRngSources;
}
public void setRequiredRngSources(RequiredRngSources requiredRngSources) {
this.requiredRngSources = requiredRngSources;
}
public String getSwitchType() {
return switchType;
}
public void setSwitchType(String switchType) {
this.switchType = switchType;
}
public String getThreadsAsCores() {
return threadsAsCores;
}
public void setThreadsAsCores(String threadsAsCores) {
this.threadsAsCores = threadsAsCores;
}
public String getTrustedService() {
return trustedService;
}
public void setTrustedService(String trustedService) {
this.trustedService = trustedService;
}
public String getTunnelMigration() {
return tunnelMigration;
}
public void setTunnelMigration(String tunnelMigration) {
this.tunnelMigration = tunnelMigration;
}
public String getUpgradeInProgress() {
return upgradeInProgress;
}
public void setUpgradeInProgress(String upgradeInProgress) {
this.upgradeInProgress = upgradeInProgress;
}
public String getUpgradePercentComplete() {
return upgradePercentComplete;
}
public void setUpgradePercentComplete(String upgradePercentComplete) {
this.upgradePercentComplete = upgradePercentComplete;
}
public Version getVersion() {
return version;
}
public void setVersion(Version version) {
this.version = version;
}
public String getVirtService() {
return virtService;
}
public void setVirtService(String virtService) {
this.virtService = virtService;
}
public String getVncEncryption() {
return vncEncryption;
}
public void setVncEncryption(String vncEncryption) {
this.vncEncryption = vncEncryption;
}
public Ref getDataCenter() {
return dataCenter;
}
public void setDataCenter(Ref dataCenter) {
this.dataCenter = dataCenter;
}
public Ref getMacPool() {
return macPool;
}
public void setMacPool(Ref macPool) {
this.macPool = macPool;
}
public Ref getSchedulingPolicy() {
return schedulingPolicy;
}
public void setSchedulingPolicy(Ref schedulingPolicy) {
this.schedulingPolicy = schedulingPolicy;
}
public Actions getActions() {
return actions;
}
public void setActions(Actions actions) {
this.actions = actions;
}
public List<Link> getLink() {
return link;
}
public void setLink(List<Link> link) {
this.link = link;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class CustomSchedulingPolicyProperties {
@JacksonXmlElementWrapper(useWrapping = false)
@JsonProperty("property")
public List<Property> property;
}
@ -173,29 +340,15 @@ public final class Cluster {
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class ErrorHandling {
@JsonProperty("on_error")
@JacksonXmlProperty(localName = "on_error")
public String onError; // "migrate"
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class FencingPolicy {
public String enabled;
@JsonProperty("skip_if_connectivity_broken")
@JacksonXmlProperty(localName = "skip_if_connectivity_broken")
public SkipIfConnectivityBroken skipIfConnectivityBroken;
@JsonProperty("skip_if_gluster_bricks_up")
@JacksonXmlProperty(localName = "skip_if_gluster_bricks_up")
public String skipIfGlusterBricksUp;
@JsonProperty("skip_if_gluster_quorum_not_met")
@JacksonXmlProperty(localName = "skip_if_gluster_quorum_not_met")
public String skipIfGlusterQuorumNotMet;
@JsonProperty("skip_if_sd_active")
@JacksonXmlProperty(localName = "skip_if_sd_active")
public SkipIfSdActive skipIfSdActive;
}
@ -213,20 +366,12 @@ public final class Cluster {
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class Ksm {
public String enabled;
@JsonProperty("merge_across_nodes")
@JacksonXmlProperty(localName = "merge_across_nodes")
public String mergeAcrossNodes;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class MemoryPolicy {
@JsonProperty("over_commit")
@JacksonXmlProperty(localName = "over_commit")
public OverCommit overCommit;
@JsonProperty("transparent_hugepages")
@JacksonXmlProperty(localName = "transparent_hugepages")
public TransparentHugepages transparentHugepages;
}
@ -242,39 +387,22 @@ public final class Cluster {
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class Migration {
@JsonProperty("auto_converge")
@JacksonXmlProperty(localName = "auto_converge")
public String autoConverge;
public Bandwidth bandwidth;
public String compressed;
public String encrypted;
@JsonProperty("parallel_migrations_policy")
@JacksonXmlProperty(localName = "parallel_migrations_policy")
public String parallelMigrationsPolicy;
public Ref policy;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class Bandwidth {
@JsonProperty("assignment_method")
@JacksonXmlProperty(localName = "assignment_method")
public String assignmentMethod;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class RequiredRngSources {
@JsonProperty("required_rng_source")
@JacksonXmlElementWrapper(useWrapping = false)
public List<String> requiredRngSource;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class Version {
public String major;
public String minor;
}
}

View File

@ -22,19 +22,25 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "clusters")
public final class Clusters {
@JsonProperty("cluster")
@JacksonXmlElementWrapper(useWrapping = false)
public List<Cluster> cluster;
private List<Cluster> cluster;
public Clusters() {}
public Clusters(final List<Cluster> cluster) {
this.cluster = cluster;
}
public List<Cluster> getCluster() {
return cluster;
}
public void setCluster(List<Cluster> cluster) {
this.cluster = cluster;
}
}

View File

@ -18,27 +18,23 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Cpu {
@JsonProperty("name")
private String name;
@JsonProperty("speed")
private Integer speed;
public String architecture;
public Topology topology;
public Cpu() {}
public Cpu(final String architecture, final Topology topology) {
this.architecture = architecture;
this.topology = topology;
}
private String architecture;
private String type;
private Topology topology;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getSpeed() { return speed; }
public void setSpeed(Integer speed) { this.speed = speed; }
public String getArchitecture() { return architecture; }
public void setArchitecture(String architecture) { this.architecture = architecture; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public Topology getTopology() { return topology; }
public void setTopology(Topology topology) { this.topology = topology; }
}

View File

@ -20,43 +20,110 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "data_center")
public final class DataCenter {
// keep strings to match oVirt JSON ("false", "disabled", "up", "v5", etc.)
public String local;
@JsonProperty("quota_mode")
public String quotaMode;
public String status;
@JsonProperty("storage_format")
public String storageFormat;
@JsonProperty("supported_versions")
public SupportedVersions supportedVersions;
public Version version;
@JsonProperty("mac_pool")
public Ref macPool;
public Actions actions;
public String name;
public String description;
public final class DataCenter extends BaseDto {
private String local;
private String quotaMode;
private String status;
private String storageFormat;
private SupportedVersions supportedVersions;
private Version version;
private Ref macPool;
private Actions actions;
private String name;
private String description;
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link;
public String href;
public String id;
public String getLocal() {
return local;
}
public DataCenter() {}
public void setLocal(String local) {
this.local = local;
}
public String getQuotaMode() {
return quotaMode;
}
public void setQuotaMode(String quotaMode) {
this.quotaMode = quotaMode;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getStorageFormat() {
return storageFormat;
}
public void setStorageFormat(String storageFormat) {
this.storageFormat = storageFormat;
}
public SupportedVersions getSupportedVersions() {
return supportedVersions;
}
public void setSupportedVersions(SupportedVersions supportedVersions) {
this.supportedVersions = supportedVersions;
}
public Version getVersion() {
return version;
}
public void setVersion(Version version) {
this.version = version;
}
public Ref getMacPool() {
return macPool;
}
public void setMacPool(Ref macPool) {
this.macPool = macPool;
}
public Actions getActions() {
return actions;
}
public void setActions(Actions actions) {
this.actions = actions;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Link> getLink() {
return link;
}
public void setLink(List<Link> link) {
this.link = link;
}
}

View File

@ -20,10 +20,7 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
/**
* Root collection wrapper:
@ -32,11 +29,8 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
* }
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "data_centers")
@JsonPropertyOrder({ "data_center" })
public final class DataCenters {
@JsonProperty("data_center")
@JacksonXmlElementWrapper(useWrapping = false)
public List<DataCenter> dataCenter;
@ -44,4 +38,12 @@ public final class DataCenters {
public DataCenters(final List<DataCenter> dataCenter) {
this.dataCenter = dataCenter;
}
public List<DataCenter> getDataCenter() {
return dataCenter;
}
public void setDataCenter(List<DataCenter> dataCenter) {
this.dataCenter = dataCenter;
}
}

View File

@ -17,78 +17,41 @@
package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "disk")
public final class Disk {
public final class Disk extends BaseDto {
private String bootable;
@JsonProperty("actual_size")
public String actualSize;
public String alias;
public String backup;
@JsonProperty("content_type")
public String contentType;
public String format;
@JsonProperty("image_id")
public String imageId;
@JsonProperty("propagate_errors")
public String propagateErrors;
@JsonProperty("initial_size")
public String initialSize;
@JsonProperty("provisioned_size")
public String provisionedSize;
@JsonProperty("qcow_version")
public String qcowVersion;
public String shareable;
public String sparse;
public String status;
@JsonProperty("storage_type")
public String storageType;
@JsonProperty("total_size")
public String totalSize;
@JsonProperty("wipe_after_delete")
public String wipeAfterDelete;
@JsonProperty("disk_profile")
public Ref diskProfile;
public Ref quota;
@JsonProperty("storage_domains")
public StorageDomains storageDomains;
public Actions actions;
public String name;
public String description;
private String actualSize;
private String alias;
private String backup;
private String contentType;
private String format;
private String imageId;
private String propagateErrors;
private String initialSize;
private String provisionedSize;
private String qcowVersion;
private String shareable;
private String sparse;
private String status;
private String storageType;
private String totalSize;
private String wipeAfterDelete;
private Ref diskProfile;
private Ref quota;
private StorageDomains storageDomains;
private Actions actions;
private String name;
private String description;
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link;
public String href;
public String id;
public Disk() {}
private List<Link> link;
public String getBootable() {
return bootable;
@ -98,12 +61,187 @@ public final class Disk {
this.bootable = bootable;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "storage_domains")
public static final class StorageDomains {
@JsonProperty("storage_domain")
@JacksonXmlElementWrapper(useWrapping = false)
public List<Ref> storageDomain;
public StorageDomains() {}
public String getActualSize() {
return actualSize;
}
public void setActualSize(String actualSize) {
this.actualSize = actualSize;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getBackup() {
return backup;
}
public void setBackup(String backup) {
this.backup = backup;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getImageId() {
return imageId;
}
public void setImageId(String imageId) {
this.imageId = imageId;
}
public String getPropagateErrors() {
return propagateErrors;
}
public void setPropagateErrors(String propagateErrors) {
this.propagateErrors = propagateErrors;
}
public String getInitialSize() {
return initialSize;
}
public void setInitialSize(String initialSize) {
this.initialSize = initialSize;
}
public String getProvisionedSize() {
return provisionedSize;
}
public void setProvisionedSize(String provisionedSize) {
this.provisionedSize = provisionedSize;
}
public String getQcowVersion() {
return qcowVersion;
}
public void setQcowVersion(String qcowVersion) {
this.qcowVersion = qcowVersion;
}
public String getShareable() {
return shareable;
}
public void setShareable(String shareable) {
this.shareable = shareable;
}
public String getSparse() {
return sparse;
}
public void setSparse(String sparse) {
this.sparse = sparse;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getStorageType() {
return storageType;
}
public void setStorageType(String storageType) {
this.storageType = storageType;
}
public String getTotalSize() {
return totalSize;
}
public void setTotalSize(String totalSize) {
this.totalSize = totalSize;
}
public String getWipeAfterDelete() {
return wipeAfterDelete;
}
public void setWipeAfterDelete(String wipeAfterDelete) {
this.wipeAfterDelete = wipeAfterDelete;
}
public Ref getDiskProfile() {
return diskProfile;
}
public void setDiskProfile(Ref diskProfile) {
this.diskProfile = diskProfile;
}
public Ref getQuota() {
return quota;
}
public void setQuota(Ref quota) {
this.quota = quota;
}
public StorageDomains getStorageDomains() {
return storageDomains;
}
public void setStorageDomains(StorageDomains storageDomains) {
this.storageDomains = storageDomains;
}
public Actions getActions() {
return actions;
}
public void setActions(Actions actions) {
this.actions = actions;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Link> getLink() {
return link;
}
public void setLink(List<Link> link) {
this.link = link;
}
}

View File

@ -19,35 +19,92 @@ package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "disk_attachment")
public final class DiskAttachment {
public String active;
public String bootable;
public final class DiskAttachment extends BaseDto {
private String active;
private String bootable;
@JsonProperty("interface")
public String iface; // virtio_scsi etc
@JsonProperty("logical_name")
public String logicalName;
@JsonProperty("pass_discard")
public String passDiscard;
@JsonProperty("read_only")
public String readOnly;
@JsonProperty("uses_scsi_reservation")
public String usesScsiReservation;
public Disk disk;
public Ref vm;
public String href;
public String id;
private String iface; // virtio_scsi etc
private String logicalName;
private String passDiscard;
private String readOnly;
private String usesScsiReservation;
private Disk disk;
private Vm vm;
public DiskAttachment() {}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getBootable() {
return bootable;
}
public void setBootable(String bootable) {
this.bootable = bootable;
}
public String getIface() {
return iface;
}
public void setIface(String iface) {
this.iface = iface;
}
public String getLogicalName() {
return logicalName;
}
public void setLogicalName(String logicalName) {
this.logicalName = logicalName;
}
public String getPassDiscard() {
return passDiscard;
}
public void setPassDiscard(String passDiscard) {
this.passDiscard = passDiscard;
}
public String getReadOnly() {
return readOnly;
}
public void setReadOnly(String readOnly) {
this.readOnly = readOnly;
}
public String getUsesScsiReservation() {
return usesScsiReservation;
}
public void setUsesScsiReservation(String usesScsiReservation) {
this.usesScsiReservation = usesScsiReservation;
}
public Disk getDisk() {
return disk;
}
public void setDisk(Disk disk) {
this.disk = disk;
}
public Vm getVm() {
return vm;
}
public void setVm(Vm vm) {
this.vm = vm;
}
}

View File

@ -17,24 +17,22 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "disk_attachments")
public final class DiskAttachments {
@JsonProperty("disk_attachment")
@JacksonXmlElementWrapper(useWrapping = false)
public List<DiskAttachment> diskAttachment;
public DiskAttachments() {}
private List<DiskAttachment> diskAttachment;
public DiskAttachments(final List<DiskAttachment> diskAttachment) {
this.diskAttachment = diskAttachment;
}
public List<DiskAttachment> getDiskAttachment() {
return diskAttachment;
}
}

View File

@ -20,21 +20,19 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "disks")
public final class Disks {
@JsonProperty("disk")
@JacksonXmlElementWrapper(useWrapping = false)
public List<Disk> disk;
public Disks() {}
private List<Disk> disk;
public Disks(final List<Disk> disk) {
this.disk = disk;
}
public List<Disk> getDisk() {
return disk;
}
}

View File

@ -18,18 +18,22 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "fault")
public final class Fault {
public String reason; // "Not Found", "Bad Request", "Unauthorized"
public String detail; // full message
public Fault() {}
private String reason; // "Not Found", "Bad Request", "Unauthorized"
private String detail; // full message
public Fault(final String reason, final String detail) {
this.reason = reason;
this.detail = detail;
}
public String getReason() {
return reason;
}
public String getDetail() {
return detail;
}
}

View File

@ -18,23 +18,13 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class HardwareInformation {
@JsonProperty("manufacturer")
private String manufacturer;
@JsonProperty("product_name")
private String productName;
@JsonProperty("serial_number")
private String serialNumber;
@JsonProperty("uuid")
private String uuid;
@JsonProperty("version")
private String version;
public String getManufacturer() { return manufacturer; }

View File

@ -17,98 +17,40 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Host {
public class Host extends BaseDto {
@JsonProperty("address")
private String address;
@JsonProperty("auto_numa_status")
private String autoNumaStatus;
@JsonProperty("certificate")
private Certificate certificate;
@JsonProperty("cpu")
private Cpu cpu;
@JsonProperty("external_status")
private String externalStatus;
@JsonProperty("hardware_information")
private HardwareInformation hardwareInformation;
@JsonProperty("kdump_status")
private String kdumpStatus;
@JsonProperty("libvirt_version")
private Version libvirtVersion;
@JsonProperty("max_scheduling_memory")
private String maxSchedulingMemory;
@JsonProperty("memory")
private String memory;
@JsonProperty("numa_supported")
private String numaSupported;
@JsonProperty("os")
private Os os;
@JsonProperty("port")
private String port;
@JsonProperty("protocol")
private String protocol;
@JsonProperty("reinstallation_required")
private String reinstallationRequired;
@JsonProperty("status")
private String status;
@JsonProperty("summary")
private ApiSummary summary;
@JsonProperty("type")
private String type;
@JsonProperty("update_available")
private String updateAvailable;
@JsonProperty("version")
private Version version;
@JsonProperty("vgpu_placement")
private String vgpuPlacement;
@JsonProperty("cluster")
private Ref cluster;
@JsonProperty("actions")
private Actions actions;
@JsonProperty("name")
private String name;
@JsonProperty("comment")
private String comment;
@JsonProperty("link")
private List<Link> link;
@JsonProperty("href")
private String href;
@JsonProperty("id")
private String id;
// getters/setters (generate via IDE)
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@ -162,8 +104,4 @@ public class Host {
public void setComment(String comment) { this.comment = comment; }
public List<Link> getLink() { return link; }
public void setLink(List<Link> link) { this.link = link; }
public String getHref() { return href; }
public void setHref(String href) { this.href = href; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
}

View File

@ -21,41 +21,22 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "image_transfer")
public class ImageTransfer {
private String id;
private String href;
public class ImageTransfer extends BaseDto {
private String active;
private String direction;
private String format;
@JsonProperty("inactivity_timeout")
private String inactivityTimeout;
private String phase;
@JsonProperty("proxy_url")
private String proxyUrl;
private String shallow;
@JsonProperty("timeout_policy")
private String timeoutPolicy;
@JsonProperty("transfer_url")
private String transferUrl;
private String transferred;
private Backup backup;
private Ref host;
private Ref image;
private Ref disk;
@ -64,22 +45,6 @@ public class ImageTransfer {
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public String getActive() {
return active;
}

View File

@ -22,7 +22,7 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Job {
public class Job extends BaseDto {
private String autoCleared;
private String external;
private Long lastUpdated;
@ -33,8 +33,6 @@ public class Job {
private Actions actions;
private String description;
private List<Link> link;
private String href;
private String id;
// getters and setters
public String getAutoCleared() { return autoCleared; }
@ -66,10 +64,4 @@ public class Job {
public List<Link> getLink() { return link; }
public void setLink(List<Link> link) { this.link = link; }
public String getHref() { return href; }
public void setHref(String href) { this.href = href; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
}

View File

@ -21,13 +21,29 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Link {
public String rel;
public String href;
private String rel;
private String href;
public Link() {}
public static Link of(final String rel, final String href) {
Link link = new Link();
link.setRel(rel);
link.setHref(href);
return link;
}
public Link(final String rel, final String href) {
public String getRel() {
return rel;
}
public void setRel(String rel) {
this.rel = rel;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}

View File

@ -0,0 +1,57 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.dto;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonCreator;
public class NamedList<T> {
private final String name;
private final List<T> items;
private NamedList(String name, List<T> items) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("name must be non-empty");
}
this.name = name;
this.items = items == null ? Collections.emptyList() : items;
}
public static <T> NamedList<T> of(String name, List<T> items) {
return new NamedList<>(name, items);
}
@JsonAnyGetter
public Map<String, List<T>> asMap() {
return Collections.singletonMap(name, items);
}
@JsonCreator
public static <T> NamedList<T> fromMap(Map<String, List<T>> map) {
if (map == null || map.size() != 1) {
throw new IllegalArgumentException("Expected single-property object for NamedList");
}
Entry<String, List<T>> e = map.entrySet().iterator().next();
return new NamedList<>(e.getKey(), e.getValue());
}
}

View File

@ -23,7 +23,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Network {
public class Network extends BaseDto {
private String mtu; // oVirt prints as string
private String portIsolation; // "false"
private String stp; // "false"
@ -39,9 +39,6 @@ public class Network {
@JsonProperty("link")
private List<Link> link;
private String href;
private String id;
public Network() {}
// ---- getters / setters ----
@ -75,10 +72,4 @@ public class Network {
public List<Link> getLink() { return link; }
public void setLink(final List<Link> link) { this.link = link; }
public String getHref() { return href; }
public void setHref(final String href) { this.href = href; }
public String getId() { return id; }
public void setId(final String id) { this.id = id; }
}

View File

@ -22,10 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Nic {
public class Nic extends BaseDto {
private String href;
private String id;
private String name;
private String description;
@JacksonXmlProperty(localName = "interface")
@ -36,28 +34,12 @@ public class Nic {
private String plugged;
public String synced;
private Ref vnicProfile;
private Ref vm;
private Vm vm;
private ReportedDevices reportedDevices;
public Nic() {
}
public String getHref() {
return href;
}
public void setHref(final String href) {
this.href = href;
}
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getName() {
return name;
}
@ -122,11 +104,11 @@ public class Nic {
this.vnicProfile = vnicProfile;
}
public Ref getVm() {
public Vm getVm() {
return vm;
}
public void setVm(Ref vm) {
public void setVm(Vm vm) {
this.vm = vm;
}

View File

@ -21,11 +21,13 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Os {
public String type; // "rhel_9", "windows_2022", etc.
private String type;
public Os() {}
public String getType() {
return type;
}
public Os(final String type) {
public void setType(String type) {
this.type = type;
}
}

View File

@ -18,19 +18,35 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class ProductInfo {
@JacksonXmlProperty(localName = "instance_id")
public String instanceId;
@JacksonXmlProperty(localName = "name")
private String instanceId;
public String name;
@JacksonXmlProperty(localName = "version")
public Version version;
public ProductInfo() {}
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Version getVersion() {
return version;
}
public void setVersion(Version version) {
this.version = version;
}
}

View File

@ -20,20 +20,12 @@ package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Ref {
public String href;
public String id;
public String name; // optional
public Ref() {}
public Ref(final String href, final String id, final String name) {
this.href = href;
this.id = id;
this.name = name;
}
public final class Ref extends BaseDto {
public static Ref of(final String href, final String id) {
return new Ref(href, id, null);
Ref ref = new Ref();
ref.setHref(href);
ref.setId(id);
return ref;
}
}

View File

@ -17,16 +17,14 @@
package org.apache.cloudstack.veeam.api.dto;
public class ReportedDevice {
public class ReportedDevice extends BaseDto {
private String comment;
private String description;
private Ips ips;
private String id;
private Mac Mac;
private String name;
private String type;
private String href;
private Ref vm;
private Vm vm;
public String getComment() {
return comment;
@ -52,14 +50,6 @@ public class ReportedDevice {
this.ips = ips;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Mac getMac() {
return Mac;
}
@ -84,19 +74,11 @@ public class ReportedDevice {
this.type = type;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public Ref getVm() {
public Vm getVm() {
return vm;
}
public void setVm(Ref vm) {
public void setVm(Vm vm) {
this.vm = vm;
}
}

View File

@ -34,7 +34,7 @@ public class Snapshot extends BaseDto {
private String description;
@JacksonXmlElementWrapper(useWrapping = false)
private List<Link> link;
private Ref vm;
private Vm vm;
public Snapshot() {}
@ -94,11 +94,11 @@ public class Snapshot extends BaseDto {
this.link = link;
}
public Ref getVm() {
public Vm getVm() {
return vm;
}
public void setVm(Ref vm) {
public void setVm(Vm vm) {
this.vm = vm;
}
}

View File

@ -18,16 +18,26 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class SpecialObjects {
@JacksonXmlProperty(localName = "blank_template")
public SpecialObjectRef blankTemplate;
private Ref blankTemplate;
private Ref rootTag;
@JacksonXmlProperty(localName = "root_tag")
public SpecialObjectRef rootTag;
public Ref getBlankTemplate() {
return blankTemplate;
}
public SpecialObjects() {}
public void setBlankTemplate(Ref blankTemplate) {
this.blankTemplate = blankTemplate;
}
public Ref getRootTag() {
return rootTag;
}
public void setRootTag(Ref rootTag) {
this.rootTag = rootTag;
}
}

View File

@ -18,25 +18,53 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Storage {
public String type; // nfs / glance
private String type;
private String address;
private String path;
private String mountOptions;
private String nfsVersion;
// nfs-ish fields (optional)
public String address;
public String path;
public String getType() {
return type;
}
@JsonProperty("mount_options")
@JacksonXmlProperty(localName = "mount_options")
public String mountOptions;
public void setType(String type) {
this.type = type;
}
@JsonProperty("nfs_version")
@JacksonXmlProperty(localName = "nfs_version")
public String nfsVersion;
public String getAddress() {
return address;
}
public Storage() {}
public void setAddress(String address) {
this.address = address;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getMountOptions() {
return mountOptions;
}
public void setMountOptions(String mountOptions) {
this.mountOptions = mountOptions;
}
public String getNfsVersion() {
return nfsVersion;
}
public void setNfsVersion(String nfsVersion) {
this.nfsVersion = nfsVersion;
}
}

View File

@ -20,81 +20,217 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "storage_domain")
public final class StorageDomain {
// Identifiers
public String id;
public String href;
public String name;
public String description;
public String comment;
// oVirt returns these as strings in your sample
public String available;
public String used;
public String committed;
@JsonProperty("block_size")
@JacksonXmlProperty(localName = "block_size")
public String blockSize;
@JsonProperty("warning_low_space_indicator")
@JacksonXmlProperty(localName = "warning_low_space_indicator")
public String warningLowSpaceIndicator;
@JsonProperty("critical_space_action_blocker")
@JacksonXmlProperty(localName = "critical_space_action_blocker")
public String criticalSpaceActionBlocker;
public String status; // e.g. "unattached" (optional in your first object)
public String type; // data / image / iso / export
public String master; // "true"/"false"
public String backup; // "true"/"false"
@JsonProperty("external_status")
@JacksonXmlProperty(localName = "external_status")
public String externalStatus; // "ok"
@JsonProperty("storage_format")
@JacksonXmlProperty(localName = "storage_format")
public String storageFormat; // v5 / v1
@JsonProperty("discard_after_delete")
@JacksonXmlProperty(localName = "discard_after_delete")
public String discardAfterDelete;
@JsonProperty("wipe_after_delete")
@JacksonXmlProperty(localName = "wipe_after_delete")
public String wipeAfterDelete;
@JsonProperty("supports_discard")
@JacksonXmlProperty(localName = "supports_discard")
public String supportsDiscard;
@JsonProperty("supports_discard_zeroes_data")
@JacksonXmlProperty(localName = "supports_discard_zeroes_data")
public String supportsDiscardZeroesData;
// Nested
public Storage storage;
@JsonProperty("data_centers")
@JacksonXmlProperty(localName = "data_centers")
public DataCenters dataCenters;
public Actions actions;
public final class StorageDomain extends BaseDto {
private String name;
private String description;
private String comment;
private String available;
private String used;
private String committed;
private String blockSize;
private String warningLowSpaceIndicator;
private String criticalSpaceActionBlocker;
private String status; // e.g. "unattached" (optional in your first object)
private String type; // data / image / iso / export
private String master; // "true"/"false"
private String backup; // "true"/"false"
private String externalStatus; // "ok"
private String storageFormat; // v5 / v1
private String discardAfterDelete;
private String wipeAfterDelete;
private String supportsDiscard;
private String supportsDiscardZeroesData;
private Storage storage;
private DataCenters dataCenters;
private Actions actions;
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link;
private List<Link> link;
public StorageDomain() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getAvailable() {
return available;
}
public void setAvailable(String available) {
this.available = available;
}
public String getUsed() {
return used;
}
public void setUsed(String used) {
this.used = used;
}
public String getCommitted() {
return committed;
}
public void setCommitted(String committed) {
this.committed = committed;
}
public String getBlockSize() {
return blockSize;
}
public void setBlockSize(String blockSize) {
this.blockSize = blockSize;
}
public String getWarningLowSpaceIndicator() {
return warningLowSpaceIndicator;
}
public void setWarningLowSpaceIndicator(String warningLowSpaceIndicator) {
this.warningLowSpaceIndicator = warningLowSpaceIndicator;
}
public String getCriticalSpaceActionBlocker() {
return criticalSpaceActionBlocker;
}
public void setCriticalSpaceActionBlocker(String criticalSpaceActionBlocker) {
this.criticalSpaceActionBlocker = criticalSpaceActionBlocker;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMaster() {
return master;
}
public void setMaster(String master) {
this.master = master;
}
public String getBackup() {
return backup;
}
public void setBackup(String backup) {
this.backup = backup;
}
public String getExternalStatus() {
return externalStatus;
}
public void setExternalStatus(String externalStatus) {
this.externalStatus = externalStatus;
}
public String getStorageFormat() {
return storageFormat;
}
public void setStorageFormat(String storageFormat) {
this.storageFormat = storageFormat;
}
public String getDiscardAfterDelete() {
return discardAfterDelete;
}
public void setDiscardAfterDelete(String discardAfterDelete) {
this.discardAfterDelete = discardAfterDelete;
}
public String getWipeAfterDelete() {
return wipeAfterDelete;
}
public void setWipeAfterDelete(String wipeAfterDelete) {
this.wipeAfterDelete = wipeAfterDelete;
}
public String getSupportsDiscard() {
return supportsDiscard;
}
public void setSupportsDiscard(String supportsDiscard) {
this.supportsDiscard = supportsDiscard;
}
public String getSupportsDiscardZeroesData() {
return supportsDiscardZeroesData;
}
public void setSupportsDiscardZeroesData(String supportsDiscardZeroesData) {
this.supportsDiscardZeroesData = supportsDiscardZeroesData;
}
public Storage getStorage() {
return storage;
}
public void setStorage(Storage storage) {
this.storage = storage;
}
public DataCenters getDataCenters() {
return dataCenters;
}
public void setDataCenters(DataCenters dataCenters) {
this.dataCenters = dataCenters;
}
public Actions getActions() {
return actions;
}
public void setActions(Actions actions) {
this.actions = actions;
}
public List<Link> getLink() {
return link;
}
public void setLink(List<Link> link) {
this.link = link;
}
}

View File

@ -30,10 +30,13 @@ public final class StorageDomains {
@JsonProperty("storage_domain")
@JacksonXmlElementWrapper(useWrapping = false)
public List<StorageDomain> storageDomain;
private List<StorageDomain> storageDomain;
public StorageDomains() {}
public StorageDomains(List<StorageDomain> storageDomain) {
public List<StorageDomain> getStorageDomain() {
return storageDomain;
}
public void setStorageDomain(List<StorageDomain> storageDomain) {
this.storageDomain = storageDomain;
}
}

View File

@ -18,21 +18,23 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class SummaryCount {
@JacksonXmlProperty(localName = "active")
public Integer active;
@JacksonXmlProperty(localName = "total")
public Integer total;
public SummaryCount() {}
private Integer active;
private Integer total;
public SummaryCount(Integer active, Integer total) {
this.active = active;
this.total = total;
}
public Integer getActive() {
return active;
}
public Integer getTotal() {
return total;
}
}

View File

@ -20,18 +20,19 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class SupportedVersions {
@JsonProperty("version")
@JacksonXmlElementWrapper(useWrapping = false)
public List<Version> version;
private List<Version> version;
public SupportedVersions() {}
public SupportedVersions(final List<Version> version) {
this.version = version;
}
public List<Version> getVersion() {
return version;
}
}

View File

@ -25,11 +25,36 @@ public final class Topology {
public Integer cores;
public Integer threads;
public Topology() {}
public Topology() {
}
public Topology(final Integer sockets, final Integer cores, final Integer threads) {
this.sockets = sockets;
this.cores = cores;
this.threads = threads;
}
public Integer getSockets() {
return sockets;
}
public void setSockets(Integer sockets) {
this.sockets = sockets;
}
public Integer getCores() {
return cores;
}
public void setCores(Integer cores) {
this.cores = cores;
}
public Integer getThreads() {
return threads;
}
public void setThreads(Integer threads) {
this.threads = threads;
}
}

View File

@ -18,25 +18,55 @@
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Version {
@JacksonXmlProperty(localName = "build")
public String build;
@JacksonXmlProperty(localName = "full_version")
public String fullVersion;
@JacksonXmlProperty(localName = "major")
public Integer major;
@JacksonXmlProperty(localName = "minor")
public Integer minor;
@JacksonXmlProperty(localName = "revision")
public Integer revision;
private String build;
private String fullVersion;
private Integer major;
private Integer minor;
private Integer revision;
public Version() {}
public String getBuild() {
return build;
}
public void setBuild(String build) {
this.build = build;
}
public String getFullVersion() {
return fullVersion;
}
public void setFullVersion(String fullVersion) {
this.fullVersion = fullVersion;
}
public Integer getMajor() {
return major;
}
public void setMajor(Integer major) {
this.major = major;
}
public Integer getMinor() {
return minor;
}
public void setMinor(Integer minor) {
this.minor = minor;
}
public Integer getRevision() {
return revision;
}
public void setRevision(Integer revision) {
this.revision = revision;
}
}

View File

@ -20,9 +20,7 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
/**
@ -31,53 +29,64 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "vm")
public final class Vm {
public String href;
public String id;
public String name;
public String description;
public String status; // "up", "down", ...
@JsonProperty("stop_reason")
@JacksonXmlProperty(localName = "stop_reason")
public String stopReason; // empty string allowed
public final class Vm extends BaseDto {
private String name;
private String description;
private String status; // "up", "down", ...
private String stopReason; // empty string allowed
private Long creationTime;
@JsonProperty("stop_time")
@JacksonXmlProperty(localName = "stop_time")
public Long stopTime; // epoch millis
private Long stopTime; // epoch millis
private Long startTime; // epoch millis
public Ref template;
@JsonProperty("original_template")
@JacksonXmlProperty(localName = "original_template")
public Ref originalTemplate;
public Ref cluster;
public Ref host;
public String memory; // bytes
public Cpu cpu;
public Os os;
public Bios bios;
public String stateless = "false"; // true|false
public String type; // "server"
public String origin; // "ovirt"
public Actions actions; // actions.link[]
private Ref template;
private Ref originalTemplate;
private Ref cluster;
private Ref host;
private String memory; // bytes
private Cpu cpu;
private Os os;
private Bios bios;
private String stateless; // true|false
private String type; // "server"
private String origin; // "ovirt"
private Actions actions; // actions.link[]
@JacksonXmlElementWrapper(useWrapping = false)
public List<Link> link; // related resources
public EmptyElement tags; // empty <tags/>
private List<Link> link; // related resources
private EmptyElement tags; // empty <tags/>
private DiskAttachments diskAttachments;
private Nics nics;
private VmInitialization initialization;
public Vm() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getStopReason() {
return stopReason;
}
public void setStopReason(String stopReason) {
this.stopReason = stopReason;
}
public Long getCreationTime() {
return creationTime;
@ -87,6 +96,14 @@ public final class Vm {
this.creationTime = creationTime;
}
public Long getStopTime() {
return stopTime;
}
public void setStopTime(Long stopTime) {
this.stopTime = stopTime;
}
public Long getStartTime() {
return startTime;
}
@ -95,6 +112,118 @@ public final class Vm {
this.startTime = startTime;
}
public Ref getTemplate() {
return template;
}
public void setTemplate(Ref template) {
this.template = template;
}
public Ref getOriginalTemplate() {
return originalTemplate;
}
public void setOriginalTemplate(Ref originalTemplate) {
this.originalTemplate = originalTemplate;
}
public Ref getCluster() {
return cluster;
}
public void setCluster(Ref cluster) {
this.cluster = cluster;
}
public Ref getHost() {
return host;
}
public void setHost(Ref host) {
this.host = host;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
public Os getOs() {
return os;
}
public void setOs(Os os) {
this.os = os;
}
public Bios getBios() {
return bios;
}
public void setBios(Bios bios) {
this.bios = bios;
}
public String getStateless() {
return stateless;
}
public void setStateless(String stateless) {
this.stateless = stateless;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public Actions getActions() {
return actions;
}
public void setActions(Actions actions) {
this.actions = actions;
}
public List<Link> getLink() {
return link;
}
public void setLink(List<Link> link) {
this.link = link;
}
public EmptyElement getTags() {
return tags;
}
public void setTags(EmptyElement tags) {
this.tags = tags;
}
public DiskAttachments getDiskAttachments() {
return diskAttachments;
}
@ -118,4 +247,11 @@ public final class Vm {
public void setInitialization(VmInitialization initialization) {
this.initialization = initialization;
}
public static Vm of(String href, String id) {
Vm vm = new Vm();
vm.setHref(href);
vm.setId(id);
return vm;
}
}

View File

@ -26,10 +26,8 @@ import com.fasterxml.jackson.annotation.JsonInclude;
* Every vNIC profile MUST reference exactly one network.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class VnicProfile {
public class VnicProfile extends BaseDto {
private String href;
private String id;
private String name;
private String description;
@ -41,22 +39,6 @@ public class VnicProfile {
public VnicProfile() {
}
public String getHref() {
return href;
}
public void setHref(final String href) {
this.href = href;
}
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getName() {
return name;
}