Enhanced updateVirtualMachine API with optional parameter "name" - to allow update hostName for the virtual machine

This commit is contained in:
Alena Prokharchyk 2014-02-28 14:25:32 -08:00
parent c93b2fa605
commit d9a4e038a0
6 changed files with 72 additions and 34 deletions

View File

@ -77,6 +77,9 @@ public class UpdateVMCmd extends BaseCustomIdCmd {
description = "true if VM contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory")
protected Boolean isDynamicallyScalable;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "new host name of the vm. The VM has to be stopped/started for this update to take affect", since = "4.4")
private String name;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -109,6 +112,10 @@ public class UpdateVMCmd extends BaseCustomIdCmd {
return isDynamicallyScalable;
}
public String getHostName() {
return name;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -53,7 +53,7 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi
@Column(name = "id", updatable = false, nullable = false)
protected long id;
@Column(name = "name", updatable = false, nullable = false, length = 255)
@Column(name = "name", nullable = false, length = 255)
protected String hostName = null;
@Encrypt
@ -272,6 +272,10 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
@Override
public String getInstanceName() {
return instanceName;

View File

@ -43,8 +43,9 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> {
* @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
* @param hostName TODO
*/
void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable, String customId);
void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable, String customId, String hostName);
List<UserVmVO> findDestroyedVms(Date date);

View File

@ -216,7 +216,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, String customId) {
public void updateVM(long id, String displayName, boolean enable, Long osTypeId, String userData, boolean displayVm, boolean isDynamicallyScalable, String customId, String hostName) {
UserVmVO vo = createForUpdate();
vo.setDisplayName(displayName);
vo.setHaEnabled(enable);
@ -224,6 +224,9 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
vo.setUserData(userData);
vo.setDisplayVm(displayVm);
vo.setDynamicallyScalable(isDynamicallyScalable);
if (hostName != null) {
vo.setHostName(hostName);
}
if (customId != null) {
vo.setUuid(customId);
}

View File

@ -22,6 +22,7 @@ import java.util.Map;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -119,7 +120,7 @@ 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, String customId) throws ResourceUnavailableException, InsufficientCapacityException;
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName) throws ResourceUnavailableException, InsufficientCapacityException;
//the validateCustomParameters, save and remove CustomOfferingDetils functions can be removed from the interface once we can
//find a common place for all the scaling and upgrading code of both user and systemvms.

View File

@ -1831,7 +1831,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
Long osTypeId = cmd.getOsTypeId();
String userData = cmd.getUserData();
Boolean isDynamicallyScalable = cmd.isDynamicallyScalable();
Account caller = CallContext.current().getCallingAccount();
String hostName = cmd.getHostName();
// Input validation and permission checks
UserVmVO vmInstance = _vmDao.findById(id.longValue());
@ -1849,12 +1849,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
_resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.memory, isDisplayVm, new Long(offering.getRamSize()));
}
return updateVirtualMachine(id, displayName, group, ha, isDisplayVm, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod(), cmd.getCustomId());
return updateVirtualMachine(id, displayName, group, ha, isDisplayVm, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod(), cmd.getCustomId(), hostName);
}
@Override
public UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId) throws ResourceUnavailableException, InsufficientCapacityException {
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName) throws ResourceUnavailableException, InsufficientCapacityException {
UserVmVO vm = _vmDao.findById(id);
if (vm == null) {
throw new CloudRuntimeException("Unable to find virual machine with id " + id);
@ -1909,7 +1909,25 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
isDynamicallyScalable = vm.isDynamicallyScalable();
}
_vmDao.updateVM(id, displayName, ha, osTypeId, userData, isDisplayVmEnabled, isDynamicallyScalable, customId);
if (hostName != null) {
// Check is hostName is RFC compliant
checkNameForRFCCompliance(hostName);
if (vm.getHostName().equalsIgnoreCase(hostName)) {
s_logger.debug("Vm " + vm + " is already set with the hostName specified: " + hostName);
hostName = null;
}
// Verify that vm's hostName is unique
List<NetworkVO> vmNtwks = new ArrayList<NetworkVO>();
List<? extends Nic> nics = _nicDao.listByVmId(vm.getId());
for (Nic nic : nics) {
vmNtwks.add(_networkDao.findById(nic.getNetworkId()));
}
checkIfHostNameUniqueInNtwkDomain(hostName, vmNtwks);
}
_vmDao.updateVM(id, displayName, ha, osTypeId, userData, isDisplayVmEnabled, isDynamicallyScalable, customId, hostName);
if (updateUserdata) {
boolean result = updateUserDataInternal(_vmDao.findById(id));
@ -2728,32 +2746,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("There already exists a VM by the display name supplied");
}
// Check that hostName is unique in the network domain
Map<String, List<Long>> ntwkDomains = new HashMap<String, List<Long>>();
for (NetworkVO network : networkList) {
String ntwkDomain = network.getNetworkDomain();
if (!ntwkDomains.containsKey(ntwkDomain)) {
List<Long> ntwkIds = new ArrayList<Long>();
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
} else {
List<Long> ntwkIds = ntwkDomains.get(ntwkDomain);
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
}
}
for (Entry<String, List<Long>> ntwkDomain : ntwkDomains.entrySet()) {
for (Long ntwkId : ntwkDomain.getValue()) {
// * get all vms hostNames in the network
List<String> hostNames = _vmInstanceDao.listDistinctHostNames(ntwkId);
// * verify that there are no duplicates
if (hostNames.contains(hostName)) {
throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + ntwkDomain.getKey() + "; network="
+ _networkModel.getNetwork(ntwkId));
}
}
}
checkIfHostNameUniqueInNtwkDomain(hostName, networkList);
HypervisorType hypervisorType = null;
if (template.getHypervisorType() == null || template.getHypervisorType() == HypervisorType.None) {
@ -2786,6 +2779,35 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return vm;
}
private void checkIfHostNameUniqueInNtwkDomain(String hostName, List<? extends Network> networkList) {
// Check that hostName is unique in the network domain
Map<String, List<Long>> ntwkDomains = new HashMap<String, List<Long>>();
for (Network network : networkList) {
String ntwkDomain = network.getNetworkDomain();
if (!ntwkDomains.containsKey(ntwkDomain)) {
List<Long> ntwkIds = new ArrayList<Long>();
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
} else {
List<Long> ntwkIds = ntwkDomains.get(ntwkDomain);
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
}
}
for (Entry<String, List<Long>> ntwkDomain : ntwkDomains.entrySet()) {
for (Long ntwkId : ntwkDomain.getValue()) {
// * get all vms hostNames in the network
List<String> hostNames = _vmInstanceDao.listDistinctHostNames(ntwkId);
// * verify that there are no duplicates
if (hostNames.contains(hostName)) {
throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + ntwkDomain.getKey() + "; network="
+ _networkModel.getNetwork(ntwkId));
}
}
}
}
private String generateHostName(String uuidName) {
return _instance + "-" + uuidName;
}