Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
d3b8e74
API command initialization
cron-ns Jun 7, 2021
e2f7228
first step to create the clone api execution
cron-ns Jun 10, 2021
6a2237c
Merge branch 'main' of https://github.com/atrocitytheme/cloudstack in…
cron-ns Jun 16, 2021
6b2604d
add findISO and findVO steps
cron-ns Jun 18, 2021
8c815ab
add creation of root-disk -> template -> vm step
cron-ns Jun 21, 2021
fb6cb0a
prepare the template impl
cron-ns Jun 23, 2021
77c39c2
clear the dot record for later test
cron-ns Jun 23, 2021
1971a39
checks for VM are implemented
cron-ns Jun 25, 2021
3687110
fix checkstyle
cron-ns Jun 25, 2021
fbb886c
compilation fixed
cron-ns Jun 25, 2021
16d75da
checkClone debug
cron-ns Jun 25, 2021
779681c
server state update
cron-ns Jun 25, 2021
5a81d2b
add and statement
cron-ns Jun 25, 2021
6f4fca9
fix null error
cron-ns Jun 25, 2021
896b033
test hit the current vm information
cron-ns Jun 28, 2021
cfd131c
fix typo of star import
cron-ns Jun 28, 2021
9677858
fix the null pt except
cron-ns Jun 28, 2021
85129ee
add vm record creation code
cron-ns Jun 28, 2021
b6607f4
add the user vm db creation code
cron-ns Jun 28, 2021
afae560
add vm creation typo fix
cron-ns Jun 28, 2021
0a1405d
change ip to available
cron-ns Jun 28, 2021
64c0fd5
fix ip issue
cron-ns Jun 28, 2021
e04dc22
fix the vm creation detail
cron-ns Jun 28, 2021
7bef87f
template zone addition code
cron-ns Jul 2, 2021
d15f620
trail-issue-1
cron-ns Jul 2, 2021
fee4a95
change test ip address
cron-ns Jul 2, 2021
eecacc0
add template download record
cron-ns Jul 2, 2021
31824f2
get the template created and prepare for the vm start
cron-ns Jul 4, 2021
e3bf894
fix unknown symbol
cron-ns Jul 4, 2021
99e5043
finish the final private creation
cron-ns Jul 4, 2021
40abfac
add logger information
cron-ns Jul 4, 2021
d235477
add autobox statement
cron-ns Jul 4, 2021
a48d7fa
add template Id setting
cron-ns Jul 5, 2021
7fb0994
use uuid as replacement of template
cron-ns Jul 5, 2021
ed9ac4e
fix the template recording bug
cron-ns Jul 5, 2021
23a53cb
fix instance creation null
cron-ns Jul 5, 2021
53785ed
fix the template creation sequence
cron-ns Jul 5, 2021
306a7f4
finish the start vm coding
cron-ns Jul 5, 2021
8ecb6a5
fix start virtual machine null pointer bug
cron-ns Jul 5, 2021
a1bf574
add public ip address for kvm host test
cron-ns Jul 5, 2021
9639389
new clone ip added
cron-ns Jul 5, 2021
0871f74
change test ip to 98
cron-ns Jul 5, 2021
f5b896e
fixing the first password issue
cron-ns Jul 7, 2021
8bebd3b
fix the style code
cron-ns Jul 7, 2021
21ac7a7
audit the star
cron-ns Jul 7, 2021
385df67
location type changed
cron-ns Jul 7, 2021
cec1ee9
fix the snapshot policy
cron-ns Jul 7, 2021
d4d7570
add automatic ip assignment-
cron-ns Jul 8, 2021
52f2810
add ip allocation
cron-ns Jul 8, 2021
1a475b3
fix the check-style typo
cron-ns Jul 8, 2021
b64c48b
try null address for vm creation
cron-ns Jul 8, 2021
6b145d1
ignore unused ip
cron-ns Jul 8, 2021
fbf3753
finish the network allocation
cron-ns Jul 8, 2021
63c7c5e
datadisk code added
cron-ns Jul 9, 2021
fcb8152
fix the import typos
cron-ns Jul 9, 2021
78d5295
fix the service api impl
cron-ns Jul 11, 2021
1414e3a
clear unused import
cron-ns Jul 11, 2021
8771728
ake the data disk shown
cron-ns Jul 11, 2021
c6279ce
data disk snapshot clearance and exception handler
cron-ns Jul 12, 2021
8fd5eb5
resolve main branch conflict
cron-ns Jul 14, 2021
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 1 api/src/main/java/com/cloud/event/EventTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public class EventTypes {
public static final String EVENT_VM_IMPORT = "VM.IMPORT";
public static final String EVENT_VM_UNMANAGE = "VM.UNMANAGE";
public static final String EVENT_VM_RECOVER = "VM.RECOVER";
public static final String EVENT_VM_CLONE = "VM.CLONE";

// Domain Router
public static final String EVENT_ROUTER_CREATE = "ROUTER.CREATE";
Expand Down
4 changes: 4 additions & 0 deletions 4 api/src/main/java/com/cloud/network/NetworkModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ public interface NetworkModel {

List<? extends Network> listNetworksUsedByVm(long vmId, boolean isSystem);

default List<Long> listNetworksUsedByVm(long vmId) {
throw new UnsupportedOperationException();
}

Nic getNicInNetwork(long vmId, long networkId);

List<? extends Nic> getNicsForTraffic(long vmId, TrafficType type);
Expand Down
6 changes: 6 additions & 0 deletions 6 api/src/main/java/com/cloud/storage/VolumeApiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.net.MalformedURLException;
import java.util.Map;

import com.cloud.exception.StorageUnavailableException;
import org.apache.cloudstack.api.command.user.vm.CloneVMCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
Expand Down Expand Up @@ -92,6 +94,8 @@ public interface VolumeApiService {

Volume detachVolumeViaDestroyVM(long vmId, long volumeId);

Volume cloneDataVolume(CloneVMCmd cmd, long snapshotId, Volume volume) throws StorageUnavailableException;

Volume detachVolumeFromVM(DetachVolumeCmd cmd);

Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map<String, String> tags)
Expand All @@ -101,6 +105,8 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc

Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume, String customId, long owner, String chainInfo);

Volume attachVolumeToVm(CloneVMCmd cmd, Long volumeId, Long deviceId);

/**
* Extracts the volume to a particular location.
*
Expand Down
9 changes: 9 additions & 0 deletions 9 api/src/main/java/com/cloud/template/TemplateApiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.net.URISyntaxException;
import java.util.List;

import com.cloud.storage.VolumeApiService;
import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd;
import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd;
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
Expand All @@ -40,6 +41,7 @@
import com.cloud.exception.StorageUnavailableException;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.user.vm.CloneVMCmd;
import org.apache.cloudstack.api.response.GetUploadParamsResponse;

public interface TemplateApiService {
Expand Down Expand Up @@ -99,6 +101,13 @@ public interface TemplateApiService {

boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissionsCmd cmd);

/**
* create a template record for later usage of creating a real template by createPrivateTemplate
* */
VirtualMachineTemplate createPrivateTemplateRecord(CloneVMCmd cmd, Account templateOwner, VolumeApiService serviceObj) throws ResourceAllocationException;

VirtualMachineTemplate createPrivateTemplate(CloneVMCmd cmd) throws CloudRuntimeException;

VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException;

VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) throws CloudRuntimeException;
Expand Down
18 changes: 18 additions & 0 deletions 18 api/src/main/java/com/cloud/vm/UserVmService.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.cloud.storage.VolumeApiService;
import com.cloud.storage.snapshot.SnapshotApiService;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd;
import org.apache.cloudstack.api.command.user.vm.CloneVMCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
Expand Down Expand Up @@ -85,6 +89,17 @@ public interface UserVmService {
*/
UserVm destroyVm(long vmId, boolean expunge) throws ResourceUnavailableException, ConcurrentOperationException;

/**
* Clone a specific VM (full clone)
*
* @param cmd
* - the command specifying vmId to be cloned
* @return the VM if cloneVM operation is successful
* */
Optional<UserVm> cloneVirtualMachine(CloneVMCmd cmd, VolumeApiService volumeService, SnapshotApiService snapshotService) throws ResourceUnavailableException, ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;

void checkCloneCondition(CloneVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ResourceAllocationException;

/**
* Resets the password of a virtual machine.
*
Expand Down Expand Up @@ -429,6 +444,9 @@ UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffe
UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
StorageUnavailableException, ResourceAllocationException;

UserVm recordVirtualMachineToDB(CloneVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
StorageUnavailableException, ResourceAllocationException;

UserVm getUserVm(long vmId);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,4 @@ public String getCreateEventType() {
public String getCreateEventDescription() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package org.apache.cloudstack.api.command.user.vm;

import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCreateCustomIdCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
//import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;

import java.util.Optional;

@APICommand(name = "cloneVirtualMachine", responseObject = UserVmResponse.class, description = "clone a virtual VM in full clone mode",
responseView = ResponseObject.ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = {VirtualMachine.class})
public class CloneVMCmd extends BaseAsyncCreateCustomIdCmd implements UserCmd {
public static final Logger s_logger = Logger.getLogger(CloneVMCmd.class.getName());
private static final String s_name = "clonevirtualmachineresponse";

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL(accessType = AccessType.OperateEntry)
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType=UserVmResponse.class,
required = true, description = "The ID of the virtual machine")
private Long id;

//Owner information
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the virtual machine. Must be used with domainId.")
private String accountName;

@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used.")
private Long domainId;

private Long temporaryTemlateId;

private Long temporarySnapShotId;

public String getAccountName() {
return accountName;
}

public Long getDomainId() {
return domainId;
}

public Long getId() {
return this.id;
}
@Override
public String getEventType() {
return EventTypes.EVENT_VM_CLONE;
}

@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.VirtualMachine;
}

@Override
public String getEventDescription() {
return "Cloning user VM: " + this._uuidMgr.getUuid(VirtualMachine.class, getId());
}

public Long getTemporaryTemlateId() {
return this.temporaryTemlateId;
}

public void setTemporarySnapShotId(Long snapshotId) {
this.temporarySnapShotId = snapshotId;
}

public Long getTemporarySnapShotId() {
return temporarySnapShotId;
}


public void setTemporaryTemlateId(long tempId) {
this.temporaryTemlateId = tempId;
}

@Override
public void create() throws ResourceAllocationException {
try {
_userVmService.checkCloneCondition(this);
VirtualMachineTemplate template = _templateService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId()), _volumeService);
if (template == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "failed to create a template to db");
}
s_logger.info("The template id recorded is: " + template.getId());
setTemporaryTemlateId(template.getId());
_templateService.createPrivateTemplate(this);
_snapshotService.deleteSnapshot(getTemporarySnapShotId());
UserVm vmRecord = _userVmService.recordVirtualMachineToDB(this);
if (vmRecord == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "unable to record a new VM to db!");
}
setEntityId(vmRecord.getId());
setEntityUuid(vmRecord.getUuid());
} catch (ResourceUnavailableException | InsufficientCapacityException e) {
s_logger.warn("Exception: ", e);
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, e.getMessage());
} catch (InvalidParameterValueException e) {
s_logger.warn("Exception: ", e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
} finally {
if (getTemporaryTemlateId() != null) {
// TODO: delete template in the service
s_logger.warn("clearing the temporary template: " + getTemporaryTemlateId());
}
}
}

public boolean isPublic() {
return false;
}

public String getVMName() {
return getTargetVM().getInstanceName();
}

public String getTemplateName() {
return getVMName() + "-QA";
}

@Override
public void execute() {
Optional<UserVm> result;
try {
CallContext.current().setEventDetails("Vm Id for full clone: " + getEntityId());
s_logger.info("starting actual VM id: " + getEntityId());
result = _userVmService.cloneVirtualMachine(this, _volumeService, _snapshotService);
} catch (ResourceUnavailableException ex) {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
} catch (ConcurrentOperationException ex) {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
}
catch (ResourceAllocationException | InsufficientCapacityException ex) {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
}
result.ifPresentOrElse((userVm)-> {
UserVmResponse response = _responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine", result.get()).get(0);
response.setResponseName("full_clone");
setResponseObject(response);
}, ()-> {
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, "failed to clone VM: " + getId());
});
}

@Override
public String getCommandName() {
return s_name;
}

@Override
public long getEntityOwnerId() {
UserVm vm = this._responseGenerator.findUserVmById(getId());
if (vm != null) {
return vm.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM;
}

public UserVm getTargetVM() {
return this._userVmService.getUserVm(getId());
}
}
10 changes: 10 additions & 0 deletions 10 server/src/main/java/com/cloud/network/NetworkModelImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.naming.ConfigurationException;
Expand Down Expand Up @@ -831,6 +832,15 @@ public List<NetworkVO> listNetworksUsedByVm(long vmId, boolean isSystem) {
return networks;
}

@Override
public List<Long> listNetworksUsedByVm(long vmId) {
return listNetworksUsedByVm(vmId, false).
stream().
mapToLong(NetworkVO::getId).
boxed().
collect(Collectors.toList());
}

@Override
public Nic getNicInNetwork(long vmId, long networkId) {
return _nicDao.findByNtwkIdAndInstanceId(networkId, vmId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@
import org.apache.cloudstack.api.command.user.template.UpdateTemplatePermissionsCmd;
import org.apache.cloudstack.api.command.user.vm.AddIpToVmNicCmd;
import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd;
import org.apache.cloudstack.api.command.user.vm.CloneVMCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
Expand Down Expand Up @@ -3236,6 +3237,7 @@ public List<Class<?>> getCommands() {
cmdList.add(ExpungeVMCmd.class);
cmdList.add(GetVMPasswordCmd.class);
cmdList.add(ListVMsCmd.class);
cmdList.add(CloneVMCmd.class);
cmdList.add(ScaleVMCmd.class);
cmdList.add(RebootVMCmd.class);
cmdList.add(RemoveNicFromVMCmd.class);
Expand Down
12 changes: 12 additions & 0 deletions 12 server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import javax.inject.Inject;

import org.apache.cloudstack.api.command.user.vm.CloneVMCmd;
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
Expand Down Expand Up @@ -908,6 +909,12 @@ public VolumeVO createVolume(CreateVolumeCmd cmd) {
}
}

@Override
public Volume cloneDataVolume(CloneVMCmd cmd, long snapshotId, Volume volume) throws StorageUnavailableException {
long vmId = cmd.getEntityId();
return createVolumeFromSnapshot((VolumeVO) volume, snapshotId, vmId);
}

protected VolumeVO createVolumeFromSnapshot(VolumeVO volume, long snapshotId, Long vmId) throws StorageUnavailableException {
VolumeInfo createdVolume = null;
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
Expand Down Expand Up @@ -1698,6 +1705,11 @@ private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long device
return newVol;
}

@Override
public Volume attachVolumeToVm(CloneVMCmd cmd, Long volumeId, Long deviceId) {
return attachVolumeToVM(cmd.getEntityId(), volumeId, deviceId);
}

public Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
Account caller = CallContext.current().getCallingAccount();

Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.