Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
7c23b26
[WIP] plugins: veeam control service
shwstppr Jan 13, 2026
065ec85
wip
shwstppr Jan 22, 2026
a30eb28
changes for discovery
shwstppr Jan 22, 2026
f52b114
changes
shwstppr Jan 22, 2026
2784468
changes
shwstppr Jan 23, 2026
81c3b5b
changes
shwstppr Jan 26, 2026
f396c5c
Basic working version-1
abh1sar Jan 15, 2026
73df3cb
Create volume on the given storage pool
abh1sar Jan 19, 2026
23ecb1f
Image server basic working version in SSVM.
abh1sar Jan 21, 2026
5389fe6
Image server with disk upload
abh1sar Jan 22, 2026
aae158b
upload fix-1
abh1sar Jan 23, 2026
10f65b6
image upload working
abh1sar Jan 25, 2026
7b45d2e
wip: changes for imagetransfer handling
shwstppr Jan 27, 2026
2350661
Added progress to upload Image Transfers
abh1sar Jan 28, 2026
9ee9748
get Options to return capabilities for upload
abh1sar Jan 29, 2026
f83fd00
add license to image_server.py
abh1sar Jan 29, 2026
2bc3114
fix precommit, license
shwstppr Jan 29, 2026
3460a5d
veeam control changes
shwstppr Jan 29, 2026
b926c74
server changes
shwstppr Jan 29, 2026
da62e9a
Support multiple disks and checkpoints
abh1sar Jan 29, 2026
4173947
extents(zero/dirty) and capabilities - working
abh1sar Jan 30, 2026
91a081b
Patch (zero, data) + Flush support in image_server.py
abh1sar Feb 2, 2026
c36cd2c
Backup of stopped VMs
abh1sar Feb 5, 2026
ca4112e
api/server: create dummy KVM VM without volume and network is optional
weizhouapache Jan 27, 2026
a366929
worker vm deployment wip
shwstppr Feb 6, 2026
586134d
Support file backend for cow format: api and server
abh1sar Feb 8, 2026
6ca1c9b
Image server support for file backend (qcow2 upload)
abh1sar Feb 8, 2026
fba7c63
ut failure in UserVmManagerImplTest
abh1sar Feb 8, 2026
a89f872
wip
shwstppr Feb 10, 2026
106fbdb
fixes to allow worker vm deployment
shwstppr Feb 11, 2026
b97f70c
userdata: defensive check for userdata validation
shwstppr Feb 11, 2026
047595d
fix snapshot delete
shwstppr Feb 11, 2026
2352c83
return job for async=false as well
shwstppr Feb 12, 2026
d9a7d2f
refactor, implement remaining endpoints
shwstppr Feb 16, 2026
4853453
kvm hosts and clusters only
shwstppr Feb 16, 2026
a9c0215
oauth fix
shwstppr Feb 16, 2026
894eef1
fix numbers in response
shwstppr Feb 16, 2026
aa7d4bc
changes for backup job fix
shwstppr Feb 17, 2026
0b4b02d
changes to backup and checkpoints api
shwstppr Feb 17, 2026
c0b8aa6
plugin changes, fixes
shwstppr Feb 17, 2026
3a02433
refactor
shwstppr Feb 18, 2026
30136c8
Image server on kvm host - with image_server.py http server
abh1sar Feb 15, 2026
0ff4dc5
remove image server from systmvm
abh1sar Feb 21, 2026
f907098
changes
shwstppr Feb 23, 2026
27a2eb0
fix
shwstppr Feb 25, 2026
18fbf76
fix
shwstppr Feb 26, 2026
11592b0
fix image_server.py
abh1sar Feb 27, 2026
8655f61
fix pre-commit
abh1sar Feb 27, 2026
196dd7f
fix ovf end tag
shwstppr Feb 27, 2026
0dadbad
fix start nbd server
shwstppr Feb 27, 2026
b68e541
remove hostIpaddress from startNbdCommand
abh1sar Feb 27, 2026
824b05f
image server : support for range puts and blocking writes
abh1sar Mar 2, 2026
eac6943
fix put disk
shwstppr Mar 2, 2026
a0be1fb
temp fix for orphan image transfer listing and backup removal
shwstppr Mar 2, 2026
05a5b03
changes for user assignement; refactor
shwstppr Mar 11, 2026
10ad796
bug fixes
abh1sar Mar 14, 2026
9974e48
changes for retrieving vm account from ovf
shwstppr Mar 16, 2026
f4a4c7a
fix for project owned resource
shwstppr Mar 16, 2026
29dbf69
fix same vm restore
shwstppr Mar 16, 2026
d527762
Fix backup of stopped VMs by allowing multiple connections.
abh1sar Mar 17, 2026
a6c7e55
fix export bitmap in start backup of running vm
abh1sar Mar 18, 2026
1f72a22
changes for restore with template; refactor
shwstppr Mar 17, 2026
3bce25d
fix check for blank instance
shwstppr Mar 18, 2026
90d87d0
restore with correct bios type
shwstppr Mar 18, 2026
1e9a116
fix naming issue
shwstppr Mar 18, 2026
cb2d736
changes for default bios boot type
shwstppr Mar 18, 2026
38c8b70
server,engine-schema: allow retrieving volume stats for stopped vms
shwstppr Mar 20, 2026
50403f7
changes for allowed cidrs; refactor
shwstppr Mar 20, 2026
5907d64
Use the upper ceiling (in gb) for the volume size during restore
abh1sar Mar 23, 2026
3e7268e
modularize image server
abh1sar Mar 23, 2026
81fc6d5
Agent communication with Image server via unix socket
abh1sar Mar 23, 2026
dad314a
Image server unittests
abh1sar Mar 23, 2026
bb213dc
extract constants used in image server
abh1sar Mar 23, 2026
5b71847
fix network listing
shwstppr Mar 26, 2026
8d42d5f
change name from IncrementalBackupService to KVMBackupExportService
abh1sar Mar 28, 2026
b6d480c
hide kvm backup export service apis behind a global config
abh1sar Mar 28, 2026
ca0ad93
Remove dependency on backup offering. Make backup export service excl…
abh1sar Mar 28, 2026
ce19b92
coalesce similar extents
abh1sar Mar 26, 2026
9a7008a
change image server default port from 54323 to 54322
abh1sar Mar 28, 2026
2bbbcae
Add tests for qcow2 file parallel range reads and puts
abh1sar Mar 29, 2026
ebdcf70
fix pre-commit failures
abh1sar Mar 29, 2026
e32a6ab
Make veeam-kvm exclusive with other providers
abh1sar Mar 31, 2026
19a8509
Image server TLS support
abh1sar Mar 31, 2026
260e6bc
storage pool type fix
shwstppr Apr 2, 2026
bad164c
fixes
shwstppr Apr 2, 2026
414d96e
remove unused classes
shwstppr Apr 2, 2026
bf856ab
fix serviceoffering custom offering
shwstppr Apr 2, 2026
5fd1b85
return internal CA certificate
shwstppr Apr 2, 2026
2d2f740
Support local storage and shared mount point
abh1sar Apr 1, 2026
cdf4684
use shared=0 for unittests
abh1sar Apr 2, 2026
6f4758d
expiry timeouts for idle image transfers
abh1sar Apr 1, 2026
5310f29
fix tests
abh1sar Apr 1, 2026
76793f0
enable TLS by default and add listen address to agent.properties
abh1sar Apr 3, 2026
ac25dc9
remove unused code
shwstppr Apr 6, 2026
b52daa2
changes for access checks
shwstppr Apr 6, 2026
d6055c9
create volume on storage refactor
abh1sar Apr 5, 2026
b84ff6b
move checkpoint to vm details
abh1sar Apr 6, 2026
dc480e0
Implement backend for delete vm checkpoint
abh1sar Apr 6, 2026
6e420fe
fix config export to test backup apis
abh1sar Apr 7, 2026
c588e67
changes for adding syncqueueitem for backup to block other operations on
shwstppr Apr 7, 2026
1669c0d
fix db list issue
shwstppr Apr 7, 2026
800faa4
add log
shwstppr Apr 7, 2026
e836bab
fix vm tags
shwstppr Apr 7, 2026
1078202
addressed with finalizing transfers before backup
shwstppr Apr 7, 2026
1ddccaa
fix storagedomain retrieval
shwstppr Apr 8, 2026
f118fc2
add logs for unimplemented endpoints
shwstppr Apr 8, 2026
b7f8fa3
handle PUT on disks/{id}; refactor
shwstppr Apr 8, 2026
259ba31
fix vms listing with tags, effectively tagged jobs
shwstppr Apr 9, 2026
d804b75
address orphan trnasfers
shwstppr Apr 9, 2026
2f67356
cleanup; return tags with specific key only
shwstppr Apr 9, 2026
40cadd0
merge fixes
shwstppr Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions agent/conf/agent.properties
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ zone=default
# Generated with "uuidgen".
local.storage.uuid=

# Enable TLS for image server transfers. The keys are read from:
# cert file = /etc/cloudstack/agent/cloud.crt
# key file = /etc/cloudstack/agent/cloud.key
image.server.tls.enabled=true

# The Address for the network interface that the image server listens on. If not specified, it will listen on the Management network.
#image.server.listen.address=

# Location for KVM virtual router scripts.
# The path defined in this property is relative to the directory "/usr/share/cloudstack-common/".
domr.scripts.dir=scripts/network/domr/kvm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,20 @@ public class AgentProperties{
*/
public static final Property<String> LOCAL_STORAGE_PATH = new Property<>("local.storage.path", "/var/lib/libvirt/images/");

/**
* Enables TLS on the KVM image server transfer endpoint.<br>
* Data type: Boolean.<br>
* Default value: <code>true</code>
*/
public static final Property<Boolean> IMAGE_SERVER_TLS_ENABLED = new Property<>("image.server.tls.enabled", true);

/**
* The IP address that the KVM image server listens on.<br>
* Data type: String.<br>
* Default value: <code>null</code>
*/
public static final Property<String> IMAGE_SERVER_LISTEN_ADDRESS = new Property<>("image.server.listen.address", null, String.class);

/**
* Directory where Qemu sockets are placed.<br>
* These sockets are for the Qemu Guest Agent and SSVM provisioning.<br>
Expand Down
9 changes: 9 additions & 0 deletions api/src/main/java/com/cloud/storage/VolumeApiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;
import java.util.Map;

import com.cloud.dc.DataCenter;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.offering.DiskOffering;
import com.cloud.user.Account;
Expand Down Expand Up @@ -70,6 +71,10 @@ public interface VolumeApiService {
*/
Volume allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationException;

Volume allocVolume(long ownerId, Long zoneId, Long diskOfferingId, Long vmId, Long snapshotId, String name,
Long cmdSize, Boolean displayVolume, Long cmdMinIops, Long cmdMaxIops, String customId)
throws ResourceAllocationException;

/**
* Creates the volume based on the given criteria
*
Expand All @@ -80,6 +85,8 @@ public interface VolumeApiService {
*/
Volume createVolume(CreateVolumeCmd cmd);

Volume createVolume(long volumeId, Long vmId, Long snapshotId, Long storageId, Boolean display);

/**
* Resizes the volume based on the given criteria
*
Expand Down Expand Up @@ -203,4 +210,6 @@ Volume updateVolume(long volumeId, String path, String state, Long storageId,
Pair<String, String> checkAndRepairVolume(CheckAndRepairVolumeCmd cmd) throws ResourceAllocationException;

Long getVolumePhysicalSize(Storage.ImageFormat format, String path, String chainInfo);

Long getCustomDiskOfferingIdForVolumeUpload(Account owner, DataCenter zone);
}
4 changes: 4 additions & 0 deletions api/src/main/java/com/cloud/user/AccountService.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,14 @@ User createUser(String userName, String password, String firstName, String lastN

Account getActiveAccountById(long accountId);

Account getActiveAccountByUuid(String accountUuid);

Account getAccount(long accountId);

User getActiveUser(long userId);

User getOneActiveUserForAccount(Account account);

User getUserIncludingRemoved(long userId);

boolean isRootAdmin(Long accountId);
Expand Down
6 changes: 6 additions & 0 deletions api/src/main/java/com/cloud/vm/VmDetailConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,10 @@ public interface VmDetailConstants {
String EXTERNAL_DETAIL_PREFIX = "External:";
String CLOUDSTACK_VM_DETAILS = "cloudstack.vm.details";
String CLOUDSTACK_VLAN = "cloudstack.vlan";

// KVM Checkpoints related
String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id";
String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time";
String LAST_CHECKPOINT_ID = "last.checkpoint.id";
String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time";
}
3 changes: 3 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class ApiConstants {
public static final String BOOTABLE = "bootable";
public static final String BIND_DN = "binddn";
public static final String BIND_PASSWORD = "bindpass";
public static final String BLANK_INSTANCE = "blankinstance";
public static final String BUS_ADDRESS = "busaddress";
public static final String BYTES_READ_RATE = "bytesreadrate";
public static final String BYTES_READ_RATE_MAX = "bytesreadratemax";
Expand Down Expand Up @@ -216,6 +217,7 @@ public class ApiConstants {
public static final String DOMAIN_PATH = "domainpath";
public static final String DOMAIN_ID = "domainid";
public static final String DOMAIN__ID = "domainId";
public static final String DUMMY = "dummy";
public static final String DURATION = "duration";
public static final String ELIGIBLE = "eligible";
public static final String EMAIL = "email";
Expand Down Expand Up @@ -331,6 +333,7 @@ public class ApiConstants {
public static final String IS_2FA_VERIFIED = "is2faverified";

public static final String IS_2FA_MANDATED = "is2famandated";
public static final String IS_ACTIVE = "isactive";
public static final String IS_ASYNC = "isasync";
public static final String IP_AVAILABLE = "ipavailable";
public static final String IP_LIMIT = "iplimit";
Expand Down
19 changes: 19 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiServerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@

import javax.servlet.http.HttpSession;

import org.apache.cloudstack.context.CallContext;

import com.cloud.domain.Domain;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.user.Account;
import com.cloud.user.UserAccount;

public interface ApiServerService {
Expand Down Expand Up @@ -52,4 +55,20 @@ public ResponseObject loginUser(HttpSession session, String username, String pas
String getDomainId(Map<String, Object[]> params);

boolean isPostRequestsAndTimestampsEnforced();

AsyncCmdResult processAsyncCmd(BaseAsyncCmd cmdObj, Map<String, String> params, CallContext ctx, Long callerUserId, Account caller) throws Exception;

class AsyncCmdResult {
public final Long objectId;
public final String objectUuid;
public final BaseAsyncCmd asyncCmd;
public final long jobId;

public AsyncCmdResult(Long objectId, String objectUuid, BaseAsyncCmd asyncCmd, long jobId) {
this.objectId = objectId;
this.objectUuid = objectUuid;
this.asyncCmd = asyncCmd;
this.jobId = jobId;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//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
//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.api.command.admin.backup;

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.command.admin.AdminCmd;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.api.response.ImageTransferResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.backup.ImageTransfer;
import org.apache.cloudstack.backup.KVMBackupExportService;
import org.apache.cloudstack.context.CallContext;

import com.cloud.utils.EnumUtils;

@APICommand(name = "createImageTransfer",
description = "Create image transfer for a disk in backup. This API is intended for testing only and is disabled by default.",
responseObject = ImageTransferResponse.class,
since = "4.23.0",
authorized = {RoleType.Admin})
public class CreateImageTransferCmd extends BaseCmd implements AdminCmd {

@Inject
private KVMBackupExportService kvmBackupExportService;

@Parameter(name = ApiConstants.BACKUP_ID,
type = CommandType.UUID,
entityType = BackupResponse.class,
description = "ID of the backup")
private Long backupId;

@Parameter(name = ApiConstants.VOLUME_ID,
type = CommandType.UUID,
entityType = VolumeResponse.class,
required = true,
description = "ID of the disk/volume")
private Long volumeId;

@Parameter(name = ApiConstants.DIRECTION,
type = CommandType.STRING,
required = true,
description = "Direction of the transfer: upload, download")
private String direction;

@Parameter(name = ApiConstants.FORMAT,
type = CommandType.STRING,
description = "Format of the image: cow/raw. Currently only raw is supported for download. Defaults to raw if not provided")
private String format;

public Long getBackupId() {
return backupId;
}

public Long getVolumeId() {
return volumeId;
}

public ImageTransfer.Direction getDirection() {
return ImageTransfer.Direction.valueOf(direction);
}

public ImageTransfer.Format getFormat() {
return EnumUtils.getEnum(ImageTransfer.Format.class, format);
}

@Override
public void execute() {
ImageTransferResponse response = kvmBackupExportService.createImageTransfer(this);
response.setResponseName(getCommandName());
setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccount().getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//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
//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.api.command.admin.backup;

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.command.admin.AdminCmd;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.backup.KVMBackupExportService;
import org.apache.cloudstack.context.CallContext;

@APICommand(name = "deleteVirtualMachineCheckpoint",
description = "Delete a VM checkpoint. This API is intended for testing only and is disabled by default.",
responseObject = SuccessResponse.class,
since = "4.23.0",
authorized = {RoleType.Admin})
public class DeleteVmCheckpointCmd extends BaseCmd implements AdminCmd {

@Inject
private KVMBackupExportService kvmBackupExportService;

@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
type = CommandType.UUID,
entityType = UserVmResponse.class,
required = true,
description = "ID of the VM")
private Long vmId;

@Parameter(name = "checkpointid",
type = CommandType.STRING,
required = true,
description = "Checkpoint ID")
private String checkpointId;

public Long getVmId() {
return vmId;
}

public String getCheckpointId() {
return checkpointId;
}

public void setVmId(Long vmId) {
this.vmId = vmId;
}

public void setCheckpointId(String checkpointId) {
this.checkpointId = checkpointId;
}

@Override
public void execute() {
boolean result = kvmBackupExportService.deleteVmCheckpoint(this);
SuccessResponse response = new SuccessResponse(getCommandName());
response.setSuccess(result);
response.setResponseName(getCommandName());
setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccount().getId();
}
}
Loading
Loading