Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
522838f
Add VMware CBT migration entry points
codex May 14, 2026
23c2435
Add VMware CBT migration session model
codex May 14, 2026
5761067
Add VMware CBT agent command contracts
codex May 14, 2026
272af7f
Wire VMware CBT migration orchestration skeleton
codex May 14, 2026
0a5f28b
Add VMware CBT migration UI actions
codex May 14, 2026
1ece73f
Start VMware CBT sessions from import UI
codex May 14, 2026
27b2329
Discover VMware CBT source disks
codex May 14, 2026
47a4e18
Track VMware CBT source metadata
codex May 14, 2026
bf313bc
Add VMware CBT changed block query contract
codex May 14, 2026
b8b9700
Add VMware CBT snapshot service hooks
codex May 14, 2026
533a56f
Wire VMware CBT delta snapshot cycle
codex May 14, 2026
b5afd8d
Handle empty VMware CBT delta cycles
codex May 14, 2026
7319aa0
Move VMware CBT schema to 4.23 upgrade file
codex May 14, 2026
9e2b111
Propagate VMware CBT source credentials
codex May 14, 2026
43ecca6
Validate VMware CBT delta sync plans
codex May 14, 2026
60ec473
Apply VMware CBT cutover policy
codex May 14, 2026
987424b
Pass VMware CBT source credentials from UI
codex May 14, 2026
a9ce2da
Require VMware CBT initial sync targets
codex May 14, 2026
7a6b8e2
Register VMware CBT initial sync targets
andrijapanicsb May 14, 2026
8e088c7
Expose VMware CBT disk target registration in UI
andrijapanicsb May 14, 2026
3a826cf
Coalesce VMware CBT copy ranges
andrijapanicsb May 14, 2026
2e31093
Honor VDDK overrides for VMware CBT checks
andrijapanicsb May 14, 2026
324e081
Persist VMware CBT VDDK options
andrijapanicsb May 14, 2026
c5d6db4
Harden VMware CBT migration states
andrijapanicsb May 14, 2026
8209e54
Expose VMware CBT cycle history
andrijapanicsb May 14, 2026
5251401
Add Windows-safe CloudStack build helper
andrijapanicsb May 14, 2026
c4dd6e6
Allow targeted tests in build helper reactors
andrijapanicsb May 14, 2026
a1fab53
Fix VMware CBT migration UI lint
andrijapanicsb May 14, 2026
c14e9d8
Ignore local settings TOML
andrijapanicsb May 14, 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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.github/workflows/*.lock.yml linguist-generated=true merge=ours
*.sh text eol=lf
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ plugins/network-elements/juniper-contrail/logs/
replace.properties.override
replace.properties.tmp
scripts/.pydevproject
settings.toml
scripts/vm/hypervisor/xenserver/vhd-util
systemvm/.pydevproject
target/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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 com.cloud.agent.api.to;

import java.io.Serializable;

public class VmwareCbtChangedBlockRangeTO implements Serializable {

private String diskId;
private long startOffset;
private long length;

public VmwareCbtChangedBlockRangeTO() {
}

public VmwareCbtChangedBlockRangeTO(String diskId, long startOffset, long length) {
this.diskId = diskId;
this.startOffset = startOffset;
this.length = length;
}

public String getDiskId() {
return diskId;
}

public long getStartOffset() {
return startOffset;
}

public long getLength() {
return length;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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 com.cloud.agent.api.to;

import java.io.Serializable;

public class VmwareCbtDiskSyncResultTO implements Serializable {

private String diskId;
private String targetPath;
private String changeId;
private String snapshotMor;
private long changedBytes;
private long durationSeconds;
private boolean result;
private String details;

public VmwareCbtDiskSyncResultTO() {
}

public VmwareCbtDiskSyncResultTO(String diskId, String targetPath, String changeId, String snapshotMor,
long changedBytes, long durationSeconds, boolean result, String details) {
this.diskId = diskId;
this.targetPath = targetPath;
this.changeId = changeId;
this.snapshotMor = snapshotMor;
this.changedBytes = changedBytes;
this.durationSeconds = durationSeconds;
this.result = result;
this.details = details;
}

public String getDiskId() {
return diskId;
}

public String getTargetPath() {
return targetPath;
}

public String getChangeId() {
return changeId;
}

public String getSnapshotMor() {
return snapshotMor;
}

public long getChangedBytes() {
return changedBytes;
}

public long getDurationSeconds() {
return durationSeconds;
}

public boolean getResult() {
return result;
}

public String getDetails() {
return details;
}
}
85 changes: 85 additions & 0 deletions api/src/main/java/com/cloud/agent/api/to/VmwareCbtDiskTO.java
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
// 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 com.cloud.agent.api.to;

import java.io.Serializable;

public class VmwareCbtDiskTO implements Serializable {

private String diskId;
private Integer diskDeviceKey;
private String sourceDiskPath;
private String datastoreName;
private String targetPath;
private String targetFormat;
private String changeId;
private String snapshotMor;
private long capacityBytes;

public VmwareCbtDiskTO() {
}

public VmwareCbtDiskTO(String diskId, Integer diskDeviceKey, String sourceDiskPath, String datastoreName,
String targetPath, String targetFormat, String changeId, String snapshotMor,
long capacityBytes) {
this.diskId = diskId;
this.diskDeviceKey = diskDeviceKey;
this.sourceDiskPath = sourceDiskPath;
this.datastoreName = datastoreName;
this.targetPath = targetPath;
this.targetFormat = targetFormat;
this.changeId = changeId;
this.snapshotMor = snapshotMor;
this.capacityBytes = capacityBytes;
}

public String getDiskId() {
return diskId;
}

public Integer getDiskDeviceKey() {
return diskDeviceKey;
}

public String getSourceDiskPath() {
return sourceDiskPath;
}

public String getDatastoreName() {
return datastoreName;
}

public String getTargetPath() {
return targetPath;
}

public String getTargetFormat() {
return targetFormat;
}

public String getChangeId() {
return changeId;
}

public String getSnapshotMor() {
return snapshotMor;
}

public long getCapacityBytes() {
return capacityBytes;
}
}
3 changes: 3 additions & 0 deletions api/src/main/java/com/cloud/host/Host.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public static String[] toStrings(Host.Type... types) {
String HOST_VDDK_SUPPORT = "host.vddk.support";
String HOST_VDDK_LIB_DIR = "vddk.lib.dir";
String HOST_VDDK_VERSION = "host.vddk.version";
String HOST_VMWARE_CBT_SUPPORT = "host.vmware.cbt.support";
String HOST_QEMU_IMG_VERSION = "host.qemu.img.version";
String HOST_QEMU_NBD_VERSION = "host.qemu.nbd.version";
String HOST_OVFTOOL_VERSION = "host.ovftool.version";
String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
String HOST_SSH_PORT = "host.ssh.port";
Expand Down
24 changes: 24 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 @@ -635,6 +635,30 @@ public class ApiConstants {
public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist";
public static final String USER_SECRET_KEY = "usersecretkey";
public static final String USE_VDDK = "usevddk";
public static final String VMWARE_MIGRATION_MODE = "vmwaremigrationmode";
public static final String VMWARE_CBT_MIGRATION_ID = "vmwarecbtmigrationid";
public static final String SOURCE_HOST = "sourcehost";
public static final String SOURCE_CLUSTER = "sourcecluster";
public static final String SOURCE_VM_NAME = "sourcevmname";
public static final String SOURCE_DISK_ID = "sourcediskid";
public static final String SOURCE_DISK_DEVICE_KEY = "sourcediskdevicekey";
public static final String SOURCE_DISK_PATH = "sourcediskpath";
public static final String TARGET_DISK_LIST = "targetdisklist";
public static final String TARGET_PATH = "targetpath";
public static final String TARGET_FORMAT = "targetformat";
public static final String CHANGE_ID = "changeid";
public static final String SNAPSHOT_MOR = "snapshotmor";
public static final String CURRENT_STEP = "currentstep";
public static final String LAST_ERROR = "lasterror";
public static final String COMPLETED_CYCLES = "completedcycles";
public static final String QUIET_CYCLES = "quietcycles";
public static final String LAST_CHANGED_BYTES = "lastchangedbytes";
public static final String LAST_DIRTY_RATE = "lastdirtyrate";
public static final String TOTAL_CHANGED_BYTES = "totalchangedbytes";
public static final String CYCLE = "cycle";
public static final String CYCLE_NUMBER = "cyclenumber";
public static final String CHANGED_BYTES = "changedbytes";
public static final String DIRTY_RATE = "dirtyrate";
public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork";
public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver";
public static final String UPDATE_IN_SEQUENCE = "updateinsequence";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// 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.api.command.admin.vm;

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.ResponseObject;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.VmwareCbtMigrationResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.vm.VmwareCbtMigrationManager;

import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;

@APICommand(name = "cancelVmwareCbtMigration",
description = "Cancel a VMware CBT migration session",
responseObject = VmwareCbtMigrationResponse.class,
responseView = ResponseObject.ResponseView.Full,
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
authorized = {RoleType.Admin},
since = "4.22.1")
public class CancelVmwareCbtMigrationCmd extends BaseCmd {

@Inject
public VmwareCbtMigrationManager vmwareCbtMigrationManager;

@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VmwareCbtMigrationResponse.class,
required = true, description = "the VMware CBT migration ID")
private Long id;

public Long getId() {
return id;
}

@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
VmwareCbtMigrationResponse response = vmwareCbtMigrationManager.cancelVmwareCbtMigration(this);
response.setResponseName(getCommandName());
setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
Account account = CallContext.current().getCallingAccount();
return account == null ? Account.ACCOUNT_ID_SYSTEM : account.getId();
}
}
Loading
Loading