[WIP] backup: veeam kvm integration#12991
Conversation
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
todo: patch (needed?)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
vm Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #12991 +/- ##
============================================
- Coverage 18.00% 17.76% -0.25%
- Complexity 16466 16502 +36
============================================
Files 5977 6101 +124
Lines 537777 546461 +8684
Branches 66037 66771 +734
============================================
+ Hits 96844 97061 +217
- Misses 430011 438446 +8435
- Partials 10922 10954 +32
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
|
@blueorangutan package |
|
@shwstppr a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 17429 |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Introduces initial Veeam UHAPI integration for CloudStack KVM by adding a new Veeam control-plane plugin and KVM image/data transfer components, plus schema/API extensions to support checkpointed/incremental backup workflows.
Changes:
- Added
veeam-control-serviceplugin with UHAPI-compatible DTOs, route handlers wiring, auth/CIDR filters, and serialization utilities. - Added KVM image server package (Python) and KVM agent/libvirt wrappers + new agent commands for checkpoints and image transfer lifecycle.
- Extended DB schema, DAOs, and API responses/commands to persist checkpoint/image-transfer state and support new workflows.
Reviewed changes
Copilot reviewed 183 out of 221 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/vm/hypervisor/kvm/imageserver/tests/init.py | Adds test package scaffold for the new KVM image server component. |
| scripts/vm/hypervisor/kvm/imageserver/constants.py | Introduces image server constants (ports, paths, tuning). |
| scripts/vm/hypervisor/kvm/imageserver/concurrency.py | Adds per-image concurrency controls for image transfers. |
| scripts/vm/hypervisor/kvm/imageserver/backends/init.py | Backend factory for file/NBD transfer backends. |
| scripts/vm/hypervisor/kvm/imageserver/main.py | Module entrypoint for starting the image server. |
| scripts/vm/hypervisor/kvm/imageserver/init.py | Package-level documentation for the image server. |
| plugins/pom.xml | Registers the new Veeam control service plugin module. |
| plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java | Updates mock to satisfy new/changed account-service API methods. |
| plugins/integrations/veeam-control-service/src/test/java/org/apache/cloudstack/veeam/api/dto/OvfXmlUtilTest.java | Adds test coverage for OVF XML parsing into DTOs. |
| plugins/integrations/veeam-control-service/src/test/java/org/apache/cloudstack/veeam/VeeamControlServiceImplTest.java | Adds basic JSON parsing test for ImageTransfer DTO. |
| plugins/integrations/veeam-control-service/src/main/resources/META-INF/cloudstack/veeam-control-service/spring-veeam-control-service-context.xml | Wires Spring beans for route handlers and adapters. |
| plugins/integrations/veeam-control-service/src/main/resources/META-INF/cloudstack/veeam-control-service/module.properties | Declares the new plugin module metadata. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/utils/ResponseWriter.java | Adds response serialization helper for XML/JSON. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/utils/PathUtil.java | Adds URL path parsing utility for route handlers. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/utils/Negotiation.java | Adds Accept-header negotiation for XML vs JSON output. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/utils/Mapper.java | Adds Jackson JSON/XML mappers configured for UHAPI-like payloads. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/utils/JwtUtil.java | Adds basic JWT issuing helper (HS256). |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/utils/DataUtil.java | Adds base64url, JSON escaping, constant-time equals helpers. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/filter/BasicAuthFilter.java | Adds Basic Auth enforcement for the Veeam API endpoint. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/filter/AllowedClientCidrsFilter.java | Adds CIDR allow-list filtering for inbound requests. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/VnicProfile.java | Adds UHAPI DTO for vNIC profiles. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/VmAction.java | Adds action DTO for VM-related async operations. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Version.java | Adds version DTO and derivation from CloudStack/package version. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Topology.java | Adds CPU topology DTO. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Tag.java | Adds tag DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/SupportedVersions.java | Adds supported-versions DTO wrapper. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/SummaryCount.java | Adds summary count DTO. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Storage.java | Adds storage DTO used by UHAPI payloads. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/SpecialObjects.java | Adds specialObjects DTO for root/blank template refs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Snapshot.java | Adds snapshot DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/ResourceAction.java | Adds base action DTO. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/ReportedDevice.java | Adds reported device info DTO for NICs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Ref.java | Adds lightweight href/id ref DTO helper. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/ProductInfo.java | Adds product info DTO returned by API root. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Os.java | Adds OS DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Nic.java | Adds NIC DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Network.java | Adds network DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/NamedList.java | Adds NamedList wrapper for oVirt-like list payload shape. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Mac.java | Adds MAC address DTO. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Link.java | Adds link DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Job.java | Adds async job DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Ip.java | Adds IP DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Fault.java | Adds fault DTO for error responses. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/EmptyElementSerializer.java | Adds serializer for empty XML element placeholders. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/EmptyElement.java | Adds empty element placeholder type. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/DiskAttachment.java | Adds disk-attachment DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/DataCenter.java | Adds datacenter DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Cpu.java | Adds CPU DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Checkpoint.java | Adds checkpoint DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Certificate.java | Adds certificate DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/BaseDto.java | Adds base DTO with href/id helpers. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Backup.java | Adds backup DTO representation. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/ApiSummary.java | Adds API root summary DTO. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Api.java | Adds API root payload DTO for /ovirt-engine/api. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/VmSnapshotVOToSnapshotConverter.java | Converts CloudStack VM snapshots to UHAPI snapshot DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/UserVmVOToCheckpointConverter.java | Converts VM details into checkpoint DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/ResourceTagVOToTagConverter.java | Converts resource tags to tag DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/NetworkVOToVnicProfileConverter.java | Converts networks to vNIC profile DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/NetworkVOToNetworkConverter.java | Converts networks to UHAPI network DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/ImageTransferVOToImageTransferConverter.java | Converts ImageTransfer VO to UHAPI transfer DTO. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/HostJoinVOToHostConverter.java | Converts hosts to UHAPI host DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/DataCenterJoinVOToDataCenterConverter.java | Converts zones to UHAPI datacenter DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/AsyncJobJoinVOToJobConverter.java | Converts async jobs to UHAPI job/action DTOs. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ApiAccessInterceptor.java | Adds AOP interceptor to enforce API permissions. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ApiAccess.java | Adds annotation to mark methods requiring API permission checks. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/VeeamControlService.java | Adds configurable service interface and config keys. |
| plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/RouteHandler.java | Adds route handler abstraction for servlet routing. |
| plugins/integrations/veeam-control-service/pom.xml | Adds Maven module definition for the new plugin. |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStopNBDServerCommandWrapper.java | Stops qemu-nbd systemd services used for transfers. |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStopBackupCommandWrapper.java | Adds backup-stop behavior via libvirt/virsh. |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetImageTransferProgressCommandWrapper.java | Adds progress reporting for image transfers on KVM. |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVmCheckpointCommandWrapper.java | Adds checkpoint deletion logic on KVM. |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java | Adds image server path/props + extra KVM helper method(s). |
| framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/AsyncJobDaoImpl.java | Adds DAO query for pending jobs by account. |
| framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/AsyncJobDao.java | Adds DAO method signature for pending jobs by account. |
| engine/userdata/src/main/java/org/apache/cloudstack/userdata/UserDataManagerImpl.java | Simplifies HTTP method selection for userdata decode limits. |
| engine/schema/src/main/resources/META-INF/db/views/cloud.user_vm_view.sql | Extends VM view to include guest OS display name. |
| engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql | Adds backup checkpoint fields + creates image_transfer table. |
| engine/schema/src/main/resources/META-INF/db/schema-42100to42200.sql | Minor schema formatting cleanup. |
| engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml | Registers imageTransferDaoImpl bean. |
| engine/schema/src/main/java/org/apache/cloudstack/backup/dao/ImageTransferDao.java | Adds DAO interface for ImageTransfer persistence. |
| engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java | Persists checkpoint, host tracking fields in backups. |
| engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java | Adds query for VM IDs by host/lastHost for volume stats. |
| engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java | Adds DAO method signature for VM IDs by host/lastHost. |
| engine/schema/src/main/java/com/cloud/tags/dao/ResourceTagsDaoImpl.java | Adds tag lookup helpers by owners/key/value. |
| engine/schema/src/main/java/com/cloud/tags/dao/ResourceTagDao.java | Adds new tag DAO APIs with filter support. |
| engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java | Adds template lookup by account+name. |
| engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java | Adds DAO method signature for account+name template lookup. |
| engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java | Adds filtering/owner-aware network list query. |
| engine/schema/src/main/java/com/cloud/network/dao/NetworkDao.java | Adds new network DAO signatures with filters/owners. |
| engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java | Adds filtered listing by hypervisor type. |
| engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java | Adds DAO method signature for filtered listing by hypervisor type. |
| engine/orchestration/src/main/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml | Registers KVM backup export service in adapter map. |
| engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java | Adds “blank instance” short-circuit during allocation. |
| core/src/main/java/org/apache/cloudstack/backup/StopNBDServerCommand.java | Adds agent command to stop NBD service for transfer. |
| core/src/main/java/org/apache/cloudstack/backup/StopBackupCommand.java | Adds agent command to abort backup job. |
| core/src/main/java/org/apache/cloudstack/backup/StopBackupAnswer.java | Adds answer type for StopBackupCommand. |
| core/src/main/java/org/apache/cloudstack/backup/StartNBDServerCommand.java | Adds agent command to start NBD server. |
| core/src/main/java/org/apache/cloudstack/backup/StartNBDServerAnswer.java | Adds answer type for StartNBDServerCommand. |
| core/src/main/java/org/apache/cloudstack/backup/StartBackupCommand.java | Adds agent command for starting checkpoint-based backup. |
| core/src/main/java/org/apache/cloudstack/backup/StartBackupAnswer.java | Adds answer type returning checkpoint create time. |
| core/src/main/java/org/apache/cloudstack/backup/GetImageTransferProgressCommand.java | Adds agent command to retrieve transfer progress. |
| core/src/main/java/org/apache/cloudstack/backup/GetImageTransferProgressAnswer.java | Adds answer type carrying progress map. |
| core/src/main/java/org/apache/cloudstack/backup/FinalizeImageTransferCommand.java | Adds agent command to finalize transfers. |
| core/src/main/java/org/apache/cloudstack/backup/DeleteVmCheckpointCommand.java | Adds agent command to delete VM checkpoints/bitmaps. |
| core/src/main/java/org/apache/cloudstack/backup/CreateImageTransferCommand.java | Adds agent command for registering image transfers. |
| core/src/main/java/org/apache/cloudstack/backup/CreateImageTransferAnswer.java | Adds answer type for CreateImageTransferCommand. |
| client/pom.xml | Adds dependency on the new Veeam control service plugin. |
| api/src/main/java/org/apache/cloudstack/backup/ImageTransfer.java | Adds ImageTransfer API model and enums. |
| api/src/main/java/org/apache/cloudstack/backup/BackupManager.java | Updates backup provider config description. |
| api/src/main/java/org/apache/cloudstack/backup/Backup.java | Adds checkpoint fields + new backup status states. |
| api/src/main/java/org/apache/cloudstack/api/response/ImageTransferResponse.java | Adds API response type for image transfer listing/creation. |
| api/src/main/java/org/apache/cloudstack/api/response/CheckpointResponse.java | Adds API response type for VM checkpoints. |
| api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java | Adds checkpoint/host fields to backup response. |
| api/src/main/java/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java | Adds storage pool selection parameter + validation. |
| api/src/main/java/org/apache/cloudstack/api/command/user/volume/AssignVolumeCmd.java | Adds setters to facilitate programmatic usage. |
| api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java | Adds setters to facilitate programmatic usage. |
| api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java | Adds setters to facilitate programmatic usage. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java | Adds setter for cluster ID. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java | Adds skipNetwork flag + setters for programmatic usage. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ListVmCheckpointsCmd.java | Adds admin-only checkpoint listing test API. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ListImageTransfersCmd.java | Adds admin-only image transfer listing test API. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/backup/FinalizeImageTransferCmd.java | Adds admin-only transfer finalization test API. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/backup/FinalizeBackupCmd.java | Adds admin-only backup finalization test API. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteVmCheckpointCmd.java | Adds admin-only checkpoint deletion test API. |
| api/src/main/java/org/apache/cloudstack/api/command/admin/backup/CreateImageTransferCmd.java | Adds admin-only image transfer creation test API. |
| api/src/main/java/org/apache/cloudstack/api/ApiServerService.java | Adds interface method for async command processing. |
| api/src/main/java/org/apache/cloudstack/api/ApiConstants.java | Adds constants for new API fields. |
| api/src/main/java/com/cloud/vm/VmDetailConstants.java | Adds VM detail keys for checkpoint tracking. |
| api/src/main/java/com/cloud/user/AccountService.java | Adds account lookup by UUID + user lookup convenience method. |
| api/src/main/java/com/cloud/storage/VolumeApiService.java | Adds overloads for programmatic volume alloc/create + helpers. |
| agent/src/main/java/com/cloud/agent/properties/AgentProperties.java | Adds agent config keys for image server TLS/listen address. |
| agent/conf/agent.properties | Documents and adds image-server-related agent properties. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public static DataCenter toDataCenter(final DataCenterJoinVO zone) { | ||
| final String id = zone.getUuid(); | ||
| final String basePath = VeeamControlService.ContextPath.value(); | ||
| final String href = basePath + DataCentersRouteHandler.BASE_ROUTE + DataCentersRouteHandler.BASE_ROUTE + "/" + id; |
There was a problem hiding this comment.
The href concatenation duplicates BASE_ROUTE, producing an incorrect URL. Also, Link.of(rel, href) is being called with parameters reversed (rel is being set to a URL and href to a literal like clusters). Build href as basePath + BASE_ROUTE + \"/\" + id, and construct links as Link.of(\"clusters\", href + \"/clusters\") (same for networks/storagedomains).
| dc.link = Arrays.asList( | ||
| Link.of(href + "/clusters", "clusters"), | ||
| Link.of(href + "/networks", "networks"), | ||
| Link.of(href + "/storagedomains", "storagedomains") | ||
| ); |
There was a problem hiding this comment.
The href concatenation duplicates BASE_ROUTE, producing an incorrect URL. Also, Link.of(rel, href) is being called with parameters reversed (rel is being set to a URL and href to a literal like clusters). Build href as basePath + BASE_ROUTE + \"/\" + id, and construct links as Link.of(\"clusters\", href + \"/clusters\") (same for networks/storagedomains).
| logger.debug("Template is a dummy template for hypervisor {}, skipping volume allocation", hyperType); | ||
| return; |
There was a problem hiding this comment.
Returning from allocate(...) when the template is a blank/dummy template likely aborts the rest of the VM allocation flow (beyond root volume allocation). If the intent is only to skip root volume allocation, avoid return here and instead conditionally skip allocateRootVolume(...) while letting the method continue.
| logger.debug("Template is a dummy template for hypervisor {}, skipping volume allocation", hyperType); | |
| return; | |
| logger.debug("Template is a dummy template for hypervisor {}, skipping root volume allocation", hyperType); |
|
|
||
| public CreateImageTransferCommand(String transferId, String direction, String socket, String file, int idleTimeoutSeconds) { | ||
| this(transferId, direction, socket, idleTimeoutSeconds); | ||
| if (direction == ImageTransfer.Direction.download.toString()) { |
There was a problem hiding this comment.
String comparison uses ==, so the download check can fail unexpectedly. Use .equals(...) (or parse direction into ImageTransfer.Direction and compare enums) to reliably reject the file backend for downloads.
| if (direction == ImageTransfer.Direction.download.toString()) { | |
| if (ImageTransfer.Direction.download.toString().equals(direction)) { |
| LOGGER.warn("Failed to inject VeeamControlService, allowing request by default"); | ||
| chain.doFilter(request, response); |
There was a problem hiding this comment.
Failing open when VeeamControlService injection is missing makes the allow-list enforcement ineffective and can unintentionally expose the endpoint. Prefer failing closed (e.g., return 503/500) or at least deny with 403 when CIDR enforcement cannot be evaluated.
| LOGGER.warn("Failed to inject VeeamControlService, allowing request by default"); | |
| chain.doFilter(request, response); | |
| LOGGER.error("Failed to inject VeeamControlService, rejecting request because allowed client CIDRs cannot be evaluated"); | |
| resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Service Unavailable"); |
| @SerializedName("from_checkpoint_id") | ||
| @Param(description = "Previous active checkpoint id for incremental backups", since = "4.22.0") | ||
| private String fromCheckpointId; | ||
|
|
||
| @SerializedName("to_checkpoint_id") |
There was a problem hiding this comment.
These new response field names use underscores (from_checkpoint_id, to_checkpoint_id), which is inconsistent with typical CloudStack API response naming (commonly lower-cased without underscores like backupid, vmid, etc.). Consider aligning the serialized names with existing conventions to minimize client surprises and maintain consistency.
| @SerializedName("from_checkpoint_id") | |
| @Param(description = "Previous active checkpoint id for incremental backups", since = "4.22.0") | |
| private String fromCheckpointId; | |
| @SerializedName("to_checkpoint_id") | |
| @SerializedName("fromcheckpointid") | |
| @Param(description = "Previous active checkpoint id for incremental backups", since = "4.22.0") | |
| private String fromCheckpointId; | |
| @SerializedName("tocheckpointid") |
| private NamedList<Ip> ips; | ||
| private Mac Mac; |
There was a problem hiding this comment.
Field name Mac is capitalized, which is inconsistent with Java conventions and makes the code harder to read/maintain. Rename the field to mac and update getters/setters accordingly (method names can remain getMac/setMac).
| public Mac getMac() { | ||
| return Mac; | ||
| } | ||
|
|
||
| public void setMac(Mac mac) { | ||
| Mac = mac; | ||
| } |
There was a problem hiding this comment.
Field name Mac is capitalized, which is inconsistent with Java conventions and makes the code harder to read/maintain. Rename the field to mac and update getters/setters accordingly (method names can remain getMac/setMac).
|
|
||
| if (StringUtils.isBlank(path)) { | ||
| return null; | ||
| } | ||
|
|
||
| // Remove base route (be tolerant of trailing slash in baseRoute) | ||
| String rest = path; | ||
| if (StringUtils.isNotBlank(baseRoute)) { | ||
| String normalizedBase = baseRoute.endsWith("/") && baseRoute.length() > 1 | ||
| ? baseRoute.substring(0, baseRoute.length() - 1) | ||
| : baseRoute; | ||
| if (rest.startsWith(normalizedBase)) { | ||
| rest = rest.substring(normalizedBase.length()); | ||
| } | ||
| } | ||
|
|
||
| // Expect "/{id}" or "/{id}/..." (no empty segments) | ||
| if (StringUtils.isBlank(rest) || !rest.startsWith("/")) { | ||
| return null; // /api/datacenters (no id) or invalid format | ||
| } | ||
|
|
||
| rest = rest.substring(1); // remove leading '/' | ||
|
|
||
| if (StringUtils.isBlank(rest)) { | ||
| return null; | ||
| } | ||
|
|
||
| final String[] parts = rest.split("/", -1); | ||
|
|
||
| // Collect non-blank segments | ||
| List<String> validParts = new ArrayList<>(); | ||
| for (String part : parts) { | ||
| if (StringUtils.isNotBlank(part)) { | ||
| validParts.add(part); | ||
| } | ||
| } | ||
|
|
||
| // Validate first segment is a UUID | ||
| if (validParts.isEmpty() || (CONSIDER_ONLY_UUID_AS_ID && !UuidUtils.isUuid(validParts.get(0)))) { | ||
| return null; | ||
| } | ||
|
|
||
| return validParts; |
There was a problem hiding this comment.
The indentation is inconsistent, and the UUID validation comment does not match behavior when CONSIDER_ONLY_UUID_AS_ID is false (no UUID validation occurs). Consider either enabling UUID validation (and enforcing it), or updating the comment/logic to reflect the intended contract; also prefer returning an empty list (or an Optional) instead of null to simplify callers.
| if (StringUtils.isBlank(path)) { | |
| return null; | |
| } | |
| // Remove base route (be tolerant of trailing slash in baseRoute) | |
| String rest = path; | |
| if (StringUtils.isNotBlank(baseRoute)) { | |
| String normalizedBase = baseRoute.endsWith("/") && baseRoute.length() > 1 | |
| ? baseRoute.substring(0, baseRoute.length() - 1) | |
| : baseRoute; | |
| if (rest.startsWith(normalizedBase)) { | |
| rest = rest.substring(normalizedBase.length()); | |
| } | |
| } | |
| // Expect "/{id}" or "/{id}/..." (no empty segments) | |
| if (StringUtils.isBlank(rest) || !rest.startsWith("/")) { | |
| return null; // /api/datacenters (no id) or invalid format | |
| } | |
| rest = rest.substring(1); // remove leading '/' | |
| if (StringUtils.isBlank(rest)) { | |
| return null; | |
| } | |
| final String[] parts = rest.split("/", -1); | |
| // Collect non-blank segments | |
| List<String> validParts = new ArrayList<>(); | |
| for (String part : parts) { | |
| if (StringUtils.isNotBlank(part)) { | |
| validParts.add(part); | |
| } | |
| } | |
| // Validate first segment is a UUID | |
| if (validParts.isEmpty() || (CONSIDER_ONLY_UUID_AS_ID && !UuidUtils.isUuid(validParts.get(0)))) { | |
| return null; | |
| } | |
| return validParts; | |
| if (StringUtils.isBlank(path)) { | |
| return new ArrayList<>(); | |
| } | |
| // Remove base route (be tolerant of trailing slash in baseRoute) | |
| String rest = path; | |
| if (StringUtils.isNotBlank(baseRoute)) { | |
| String normalizedBase = baseRoute.endsWith("/") && baseRoute.length() > 1 | |
| ? baseRoute.substring(0, baseRoute.length() - 1) | |
| : baseRoute; | |
| if (rest.startsWith(normalizedBase)) { | |
| rest = rest.substring(normalizedBase.length()); | |
| } | |
| } | |
| // Expect "/{id}" or "/{id}/..." (no empty segments) | |
| if (StringUtils.isBlank(rest) || !rest.startsWith("/")) { | |
| return new ArrayList<>(); // /api/datacenters (no id) or invalid format | |
| } | |
| rest = rest.substring(1); // remove leading '/' | |
| if (StringUtils.isBlank(rest)) { | |
| return new ArrayList<>(); | |
| } | |
| final String[] parts = rest.split("/", -1); | |
| // Collect non-blank segments | |
| List<String> validParts = new ArrayList<>(); | |
| for (String part : parts) { | |
| if (StringUtils.isNotBlank(part)) { | |
| validParts.add(part); | |
| } | |
| } | |
| // Ensure the first segment exists; validate it as a UUID only when configured to do so | |
| if (validParts.isEmpty() || (CONSIDER_ONLY_UUID_AS_ID && !UuidUtils.isUuid(validParts.get(0)))) { | |
| return new ArrayList<>(); | |
| } | |
| return validParts; |
| // Validate first segment is a UUID | ||
| if (validParts.isEmpty() || (CONSIDER_ONLY_UUID_AS_ID && !UuidUtils.isUuid(validParts.get(0)))) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
The indentation is inconsistent, and the UUID validation comment does not match behavior when CONSIDER_ONLY_UUID_AS_ID is false (no UUID validation occurs). Consider either enabling UUID validation (and enforcing it), or updating the comment/logic to reflect the intended contract; also prefer returning an empty list (or an Optional) instead of null to simplify callers.
Description
This PR introduces the initial implementation of Veeam integration support for KVM in CloudStack by adding a UHAPI-compatible server and image server components.
Veeam Backup & Replication interacts with virtualization platforms using its Universal Hypervisor API (UHAPI). To enable backup and restore workflows for CloudStack-managed KVM environments, this change introduces a UHAPI server that exposes CloudStack resources through a UHAPI-compatible interface.
In addition to the control plane APIs, an image server component is introduced to handle the data transfer operations required during backup and restore workflows.
Architecture
The integration consists of two main components:
A lightweight UHAPI server runs inside the CloudStack management server and exposes endpoints under:
This server provides inventory discovery APIs required by Veeam and translates CloudStack resources into the structures expected by UHAPI.
The server:
A separate image server component is introduced to handle backup and restore data transfer operations.
This component:
The separation between both these components server ensures that:
Co-authored by @abh1sar @weizhouapache
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
How did you try to break this feature and the system with this change?