CLOUDSTACK-5206: Ability to control the external id of first

class objects. Putting in the generic methods and trying it
 for objects like vm, volume. This is the first cut
This commit is contained in:
Nitin Mehta 2013-11-26 09:52:17 -08:00
parent 8b237eb0a2
commit 6bea532efa
18 changed files with 300 additions and 64 deletions

View File

@ -87,7 +87,7 @@ public interface VolumeApiService {
Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException;
Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume);
Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume, String customId);
/**
* Extracts the volume to a particular location.

View File

@ -137,6 +137,7 @@ public interface UserVmService {
* caller.
*
*
*
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@ -182,15 +183,10 @@ public interface UserVmService {
* @param displayVm
* - Boolean flag whether to the display the vm to the end user or not
* @param affinityGroupIdList
* @param accountName
* - an optional account for the virtual machine. Must be used
* with domainId
* @param domainId
* - an optional domainId for the virtual machine. If the account
* parameter is used, domainId must also be used
* @param cpuSpeed
* @param memory
* @param cpuNumber
* @param customId
* @return UserVm object if successful.
*
* @throws InsufficientCapacityException
@ -204,9 +200,9 @@ public interface UserVmService {
* @throws InsufficientResourcesException
*/
UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdisksize) throws InsufficientCapacityException,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdisksize, String customId) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/**
@ -214,6 +210,7 @@ public interface UserVmService {
* the database and returns the VM to the caller.
*
*
*
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@ -261,15 +258,9 @@ public interface UserVmService {
* @param displayVm
* - Boolean flag whether to the display the vm to the end user or not
* @param affinityGroupIdList
* @param accountName
* - an optional account for the virtual machine. Must be used
* with domainId
* @param domainId
* - an optional domainId for the virtual machine. If the account
* parameter is used, domainId must also be used
* @param CpuSpeed
* @param memory
* @param cpuNumber
* @param customId
* @return UserVm object if successful.
*
* @throws InsufficientCapacityException
@ -283,9 +274,9 @@ public interface UserVmService {
* @throws InsufficientResourcesException
*/
UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdisksize) throws InsufficientCapacityException,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdisksize, String customId) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/**
@ -293,6 +284,7 @@ public interface UserVmService {
* in the database and returns the VM to the caller.
*
*
*
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@ -337,15 +329,10 @@ public interface UserVmService {
* @param displayVm
* - Boolean flag whether to the display the vm to the end user or not
* @param affinityGroupIdList
* @param accountName
* - an optional account for the virtual machine. Must be used
* with domainId
* @param domainId
* - an optional domainId for the virtual machine. If the account
* parameter is used, domainId must also be used
* @param cpuSpeed
* @param memory
* @param cpuNumber
* @param customId
* @return UserVm object if successful.
*
* @throws InsufficientCapacityException
@ -359,9 +346,9 @@ public interface UserVmService {
* @throws InsufficientResourcesException
*/
UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner,
String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List<Long> affinityGroupIdList,
Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdkisksize)
String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List<Long> affinityGroupIdList,
Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdkisksize, String customId)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;

View File

@ -54,6 +54,7 @@ public class ApiConstants {
public static final String CREATED = "created";
public static final String CUSTOMIZED = "customized";
public static final String CUSTOMIZED_IOPS = "customizediops";
public static final String CUSTOM_ID = "customid";
public static final String MIN_IOPS = "miniops";
public static final String MAX_IOPS = "maxiops";
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";

View File

@ -0,0 +1,27 @@
// 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;
public abstract class BaseAsyncCreateCustomIdCmd extends BaseAsyncCreateCmd{
@Parameter(name=ApiConstants.CUSTOM_ID, type=CommandType.STRING, description="an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only")
private String customId;
public String getCustomId() {
return customId;
}
}

View File

@ -0,0 +1,27 @@
// 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;
public abstract class BaseAsyncCustomIdCmd extends BaseAsyncCmd {
@Parameter(name=ApiConstants.CUSTOM_ID, type=CommandType.STRING, description="an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only")
private String customId;
public String getCustomId() {
return customId;
}
}

View File

@ -0,0 +1,27 @@
// 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;
public abstract class BaseCustomIdCmd extends BaseCmd {
@Parameter(name=ApiConstants.CUSTOM_ID, type=CommandType.STRING, description="an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only")
private String customId;
public String getCustomId() {
return customId;
}
}

View File

@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.BaseAsyncCreateCustomIdCmd;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -69,7 +70,7 @@ import com.cloud.uservm.UserVm;
@APICommand(name = "deployVirtualMachine",
description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.",
responseObject = UserVmResponse.class)
public class DeployVMCmd extends BaseAsyncCreateCmd {
public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd {
public static final Logger s_logger = Logger.getLogger(DeployVMCmd.class.getName());
private static final String s_name = "deployvirtualmachineresponse";
@ -576,14 +577,14 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
vm =
_userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(), owner, name, displayName,
diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard,
getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize);
getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize, getCustomId());
}
} else {
if (zone.isSecurityGroupEnabled()) {
vm =
_userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, getNetworkIds(), getSecurityGroupIdList(), owner, name,
displayName, diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm,
keyboard, getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize);
keyboard, getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize, getCustomId());
} else {
if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) {
@ -592,7 +593,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
vm =
_userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, getNetworkIds(), owner, name, displayName, diskOfferingId, size,
group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList(),
cpuSpeed, memory, cpuNumber, rootdisksize);
cpuSpeed, memory, cpuNumber, rootdisksize, getCustomId());
}
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.api.command.user.vm;
import org.apache.cloudstack.api.BaseCustomIdCmd;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
@ -36,7 +37,7 @@ import com.cloud.uservm.UserVm;
@APICommand(name = "updateVirtualMachine", description = "Updates properties of a virtual machine. The VM has to be stopped and restarted for the "
+ "new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. "
+ "Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class)
public class UpdateVMCmd extends BaseCmd {
public class UpdateVMCmd extends BaseCustomIdCmd {
public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName());
private static final String s_name = "updatevirtualmachineresponse";

View File

@ -16,6 +16,8 @@
// under the License.
package org.apache.cloudstack.api.command.user.volume;
import org.apache.cloudstack.api.BaseAsyncCreateCustomIdCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
@ -41,7 +43,7 @@ import com.cloud.storage.Volume;
@APICommand(name = "createVolume",
responseObject = VolumeResponse.class,
description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.")
public class CreateVolumeCmd extends BaseAsyncCreateCmd {
public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd {
public static final Logger s_logger = Logger.getLogger(CreateVolumeCmd.class.getName());
private static final String s_name = "createvolumeresponse";
@ -50,7 +52,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd {
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNT,
type = CommandType.STRING,
type = BaseCmd.CommandType.STRING,
description = "the account associated with the disk volume. Must be used with the domainId parameter.")
private String accountName;

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.api.command.user.volume;
import org.apache.cloudstack.api.BaseAsyncCustomIdCmd;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
@ -34,7 +35,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.storage.Volume;
@APICommand(name = "updateVolume", description = "Updates the volume.", responseObject = VolumeResponse.class)
public class UpdateVolumeCmd extends BaseAsyncCmd {
public class UpdateVolumeCmd extends BaseAsyncCustomIdCmd {
public static final Logger s_logger = Logger.getLogger(UpdateVolumeCmd.class.getName());
private static final String s_name = "updatevolumeresponse";
@ -140,7 +141,7 @@ public class UpdateVolumeCmd extends BaseAsyncCmd {
@Override
public void execute() {
CallContext.current().setEventDetails("Volume Id: " + getId());
Volume result = _volumeService.updateVolume(getId(), getPath(), getState(), getStorageId(), getDisplayVolume());
Volume result = _volumeService.updateVolume(getId(), getPath(), getState(), getStorageId(), getDisplayVolume(), getCustomId());
if (result != null) {
VolumeResponse response = _responseGenerator.createVolumeResponse(result);
response.setResponseName(getCommandName());

View File

@ -40,11 +40,11 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> {
/**
* Updates display name and group for vm; enables/disables ha
* @param id vm id.
* @param displan name and enable for ha
* @param userData updates the userData of the vm
* @param displayVm updates the displayvm attribute signifying whether it has to be displayed to the end user or not.
* @param customId
*/
void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable);
void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable, String customId);
List<UserVmVO> findDestroyedVms(Date date);

View File

@ -215,7 +215,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
}
@Override
public void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable) {
public void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable, String customId) {
UserVmVO vo = createForUpdate();
vo.setDisplayName(displayName);
vo.setHaEnabled(enable);
@ -223,6 +223,10 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
vo.setUserData(userData);
vo.setDisplayVm(displayVm);
vo.setDynamicallyScalable(isDynamicallyScalable);
if (customId != null){
vo.setUuid(customId);
}
update(id, vo);
}

View File

@ -116,6 +116,8 @@
<bean id="identityServiceImpl" class="com.cloud.uuididentity.IdentityServiceImpl" />
<bean id="uUIDManagerImpl" class="com.cloud.uuididentity.UUIDManagerImpl" />
<bean id="keystoreManagerImpl" class="com.cloud.keystore.KeystoreManagerImpl" />
<bean id="loadBalancingRulesManagerImpl" class="com.cloud.network.lb.LoadBalancingRulesManagerImpl" >

View File

@ -26,6 +26,7 @@ import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import com.cloud.uuididentity.UUIDManager;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.BaseCmd;
@ -302,6 +303,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
UploadMonitor _uploadMonitor;
@Inject
UploadDao _uploadDao;
@Inject
UUIDManager _uuidMgr;
@Inject
protected HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
@ -604,18 +607,21 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
userSpecifiedName = getRandomVolumeName();
}
VolumeVO volume = commitVolume(cmd, caller, ownerId, displayVolumeEnabled, zoneId, diskOfferingId, size, minIops, maxIops, parentVolume, userSpecifiedName);
VolumeVO volume = commitVolume(cmd, caller, ownerId, displayVolumeEnabled, zoneId, diskOfferingId, size, minIops,
maxIops, parentVolume, userSpecifiedName, _uuidMgr.generateUuid(Volume.class, cmd.getCustomId()));
return volume;
}
private VolumeVO commitVolume(final CreateVolumeCmd cmd, final Account caller, final long ownerId, final Boolean displayVolumeEnabled, final Long zoneId,
final Long diskOfferingId, final Long size, final Long minIops, final Long maxIops, final VolumeVO parentVolume, final String userSpecifiedName) {
final Long diskOfferingId, final Long size, final Long minIops, final Long maxIops, final VolumeVO parentVolume,
final String userSpecifiedName, final String uuid) {
return Transaction.execute(new TransactionCallback<VolumeVO>() {
@Override
public VolumeVO doInTransaction(TransactionStatus status) {
VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK);
volume.setPoolId(null);
volume.setUuid(uuid);
volume.setDataCenterId(zoneId);
volume.setPodId(null);
volume.setAccountId(ownerId);
@ -1134,7 +1140,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_UPDATE, eventDescription = "updating volume", async = true)
public Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume) {
public Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume, String customId) {
VolumeVO volume = _volumeDao.findById(volumeId);
if (path != null) {
@ -1162,6 +1168,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
volume.setPoolId(pool.getId());
}
if (customId != null){
_uuidMgr.checkUuid(customId, Volume.class);
volume.setUuid(customId);
}
_volumeDao.update(volumeId, volume);
return volume;

View File

@ -0,0 +1,38 @@
// 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.uuididentity;
import org.apache.cloudstack.api.Identity;
public interface UUIDManager {
/**
* Generates a new uuid or uses the customId
* @param entityType the type of entity
* @param customId optional custom uuid of the object.
* @return newly created uuid.
*/
public <T> String generateUuid(Class<T> entityType, String customId);
/**
* Checks the uuid for correct format, uniqueness and permissions.
* @param uuid uuid to check
* @param entityType the type of entity
* .
*/
<T> void checkUuid(String uuid, Class<T> entityType);
}

View File

@ -0,0 +1,102 @@
// 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.uuididentity;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.storage.Volume;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.context.CallContext;
import javax.ejb.Local;
import javax.inject.Inject;
import java.util.UUID;
@Local(value = { UUIDManager.class })
public class UUIDManagerImpl implements UUIDManager {
@Inject
EntityManager _entityMgr;
@Inject
AccountManager _accountMgr;
//TODO - Make this configurable.
private final int UUID_RETRY = 3;
@Override
public <T> void checkUuid(String uuid, Class<T> entityType){
if(uuid == null) return;
Account caller = CallContext.current().getCallingAccount();
// Only admin and system allowed to do this
if ( !(caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) ) {
throw new PermissionDeniedException("Please check your permissions, you are not allowed to create/update custom id");
}
// check format
if(!IsUuidFormat(uuid))
throw new InvalidParameterValueException("UUID: " + uuid + " doesn't follow the UUID format");
// check unique
if(!IsUuidUnique(entityType, uuid))
throw new InvalidParameterValueException("UUID: " + uuid + " already exists so can't create/update with custom id");
}
public boolean IsUuidFormat(String uuid){
// Match against UUID regex to check if input is uuid string
boolean isUuid = uuid.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
return isUuid;
}
public <T> boolean IsUuidUnique(Class<T> entityType, String uuid){
T obj = _entityMgr.findByUuid(entityType, uuid);
if(obj != null)
return false;
else
return true;
}
@Override
public <T> String generateUuid(Class<T> entityType, String customId){
if(customId == null){ // if no customid is passed then generate it.
int retry = UUID_RETRY;
while (retry-- != 0) { // there might be collision so retry
String uuid = UUID.randomUUID().toString();
if(IsUuidUnique(entityType, uuid))
return uuid;
}
throw new CloudRuntimeException("Unable to generate a unique uuid, please try again");
}else {
checkUuid(customId, entityType);
return customId;
}
}
}

View File

@ -116,5 +116,5 @@ public interface UserVmManager extends UserVmService {
void collectVmDiskStatistics(UserVmVO userVm);
UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod) throws ResourceUnavailableException, InsufficientCapacityException;
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId) throws ResourceUnavailableException, InsufficientCapacityException;
}

View File

@ -34,6 +34,7 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.uuididentity.UUIDManager;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
@ -445,6 +446,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
VolumeDataFactory volFactory;
@Inject
UserVmDetailsDao _uservmDetailsDao;
@Inject
UUIDManager _uuidMgr;
protected ScheduledExecutorService _executor = null;
protected int _expungeInterval;
@ -1731,12 +1734,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
return updateVirtualMachine(id, displayName, group, ha, isDisplayVmEnabled, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod());
return updateVirtualMachine(id, displayName, group, ha, isDisplayVmEnabled, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod(), cmd.getCustomId());
}
@Override
public UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod) throws ResourceUnavailableException, InsufficientCapacityException {
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId) throws ResourceUnavailableException, InsufficientCapacityException {
UserVmVO vm = _vmDao.findById(id);
if (vm == null) {
throw new CloudRuntimeException("Unable to find virual machine with id " + id);
@ -1791,7 +1794,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
isDynamicallyScalable = vm.isDynamicallyScalable();
}
_vmDao.updateVM(id, displayName, ha, osTypeId, userData, isDisplayVmEnabled, isDynamicallyScalable);
_uuidMgr.checkUuid(customId, UserVm.class);
_vmDao.updateVM(id, displayName, ha, osTypeId, userData, isDisplayVmEnabled, isDynamicallyScalable, customId);
if (updateUserdata) {
boolean result = updateUserDataInternal(_vmDao.findById(id));
@ -2083,9 +2088,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true)
public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize, String customId) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
@ -2131,16 +2136,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, securityGroupIdList, group,
httpmethod, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, displayVm, keyboard, affinityGroupIdList, cpuSpeed, memory, cpuNumber,
rootDiskSize);
rootDiskSize, customId);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true)
public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize, String customId) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
@ -2240,15 +2245,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, securityGroupIdList, group,
httpmethod, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, displayVm, keyboard, affinityGroupIdList, cpuSpeed, memory, cpuNumber,
rootDiskSize);
rootDiskSize, customId);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true)
public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayvm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayvm, String keyboard,
List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize, String customId) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
@ -2337,7 +2342,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, null, group, httpmethod,
userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, displayvm, keyboard, affinityGroupIdList, cpuSpeed, memory, cpuNumber, rootDiskSize);
userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, displayvm, keyboard, affinityGroupIdList, cpuSpeed, memory, cpuNumber, rootDiskSize, customId);
}
public void checkNameForRFCCompliance(String name) {
@ -2349,9 +2354,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@DB
protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate tmplt, String hostName, String displayName,
Account owner, Long diskOfferingId, Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, HTTPMethod httpmethod,
String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps,
Boolean isDisplayVmEnabled, String keyboard, List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize)
Account owner, Long diskOfferingId, Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, HTTPMethod httpmethod,
String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps,
Boolean isDisplayVmEnabled, String keyboard, List<Long> affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize, String customId)
throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException {
_accountMgr.checkAccess(caller, null, true, owner);
@ -2601,7 +2606,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
String instanceName = null;
String uuidName = UUID.randomUUID().toString();
String uuidName = _uuidMgr.generateUuid(UserVm.class, customId);
if (_instanceNameFlag && hypervisor.equals(HypervisorType.VMware)) {
if (hostName == null) {
if (displayName != null) {