mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Bug 9387: Recreate system vms if template id changed....
Changes: While starting a System VM: - We check, incase the ROOT volume is READY, if the templateID of the volume matches the SystemVM's template. - If it does not match, we update the volumes' templateId and ask deployment planner to reassign a pool to this volume even if it is READY. In general: - If a root volume is READY, we remove its entry from the deploydestination before calling storagemanager :: prepare() - StorageManager creates a volume if a pool is assigned to it in deploydestination passed to it. - If a volume has no pool assigned to it in deploydestination, it means the volume is ready and has a pool already allocated to it.
This commit is contained in:
parent
8abda2fdd0
commit
b1700af146
@ -151,7 +151,16 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject
|
||||
* UserBareMetal is only used for selecting VirtualMachineGuru, there is no
|
||||
* VM with this type. UserBareMetal should treat exactly as User.
|
||||
*/
|
||||
UserBareMetal,
|
||||
UserBareMetal;
|
||||
|
||||
public static boolean isSystemVM(VirtualMachine.Type vmtype) {
|
||||
if(DomainRouter.equals(vmtype)
|
||||
|| ConsoleProxy.equals(vmtype)
|
||||
|| SecondaryStorageVm.equals(vmtype)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getInstanceName();
|
||||
|
||||
@ -515,14 +515,17 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
|
||||
//skip the volume if its already in READY state and has pool allocated
|
||||
if(plan.getPoolId() != null){
|
||||
if (toBeCreated.getPoolId() != null && toBeCreated.getPoolId().longValue() == plan.getPoolId().longValue()) {
|
||||
s_logger.debug("Volume is in READY state and has pool already allocated.");
|
||||
if (toBeCreated.getVolumeType() == Volume.Type.ROOT && toBeCreated.getPoolId() != null && toBeCreated.getPoolId().longValue() == plan.getPoolId().longValue()) {
|
||||
s_logger.debug("ROOT Volume is in READY state and has pool already allocated.");
|
||||
List<StoragePool> suitablePools = new ArrayList<StoragePool>();
|
||||
StoragePoolVO pool = _storagePoolDao.findById(toBeCreated.getPoolId());
|
||||
if(!avoid.shouldAvoid(pool)){
|
||||
s_logger.debug("Planner need not allocate a pool for this volume since its READY");
|
||||
suitablePools.add(pool);
|
||||
suitableVolumeStoragePools.put(toBeCreated, suitablePools);
|
||||
continue;
|
||||
}else{
|
||||
s_logger.debug("Pool of the ROOT volume is in avoid set, need to allocate a pool for this volume");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2480,12 +2480,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("DeployDestination cannot be null, cannot prepare Volumes for the vm: "+ vm);
|
||||
}
|
||||
throw new CloudRuntimeException("Unable to prepare Volume for vm because DeployDestination is null");
|
||||
}else if(dest.getStorageForDisks() == null){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("DeployDestination has no storage pools specified, cannot prepare Volumes for the vm: "+ vm);
|
||||
}
|
||||
throw new CloudRuntimeException("Unable to prepare Volume for vm because DeployDestination DeployDestination has no storage pools specified");
|
||||
throw new CloudRuntimeException("Unable to prepare Volume for vm because DeployDestination is null, vm:"+vm);
|
||||
}
|
||||
List<VolumeVO> vols = _volsDao.findUsableVolumesForInstance(vm.getId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
@ -2495,34 +2490,35 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
List<VolumeVO> recreateVols = new ArrayList<VolumeVO>(vols.size());
|
||||
|
||||
for (VolumeVO vol : vols) {
|
||||
if(vol.getPoolId() == null){
|
||||
recreateVols.add(vol);
|
||||
}else{
|
||||
StoragePool assignedPool = dest.getStorageForDisks().get(vol);
|
||||
if(assignedPool == null){
|
||||
throw new StorageUnavailableException("No storage pool assigned in DeployDestination, Unable to create " + vol, -1L);
|
||||
}
|
||||
if(vol.getPoolId() != assignedPool.getId()){
|
||||
if (vol.isRecreatable()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " has to be recreated since a different storage pool " + assignedPool + " is assigned by deploymentPlanner");
|
||||
}
|
||||
recreateVols.add(vol);
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " is not recreatable! Cannot create storagepool...");
|
||||
}
|
||||
throw new StorageUnavailableException("Unable to create " + vol, assignedPool.getId());
|
||||
//copy volume usecase - not yet developed.
|
||||
}
|
||||
}else{
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " already has the poolId set to the assigned pool: " + assignedPool);
|
||||
}
|
||||
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
|
||||
vm.addDisk(new VolumeTO(vol, pool));
|
||||
}
|
||||
}
|
||||
StoragePool assignedPool = null;
|
||||
if(dest.getStorageForDisks() != null){
|
||||
assignedPool = dest.getStorageForDisks().get(vol);
|
||||
}
|
||||
if(assignedPool != null){
|
||||
Volume.State state = vol.getState();
|
||||
if(state == Volume.State.Allocated){
|
||||
recreateVols.add(vol);
|
||||
}else{
|
||||
if (vol.isRecreatable()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " will be recreated on storage pool " + assignedPool + " assigned by deploymentPlanner");
|
||||
}
|
||||
recreateVols.add(vol);
|
||||
}else{
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " is not recreatable! Cannot recreate on storagepool: "+assignedPool);
|
||||
}
|
||||
throw new StorageUnavailableException("Volume is not recreatable, Unable to create " + vol, Volume.class, vol.getId());
|
||||
//copy volume usecase - not yet developed.
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(vol.getPoolId() == null){
|
||||
throw new StorageUnavailableException("Volume has no pool associate and also no storage pool assigned in DeployDestination, Unable to create " + vol, Volume.class, vol.getId());
|
||||
}
|
||||
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
|
||||
vm.addDisk(new VolumeTO(vol, pool));
|
||||
}
|
||||
}
|
||||
|
||||
for (VolumeVO vol : recreateVols) {
|
||||
|
||||
@ -556,21 +556,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
|
||||
T startedVm = null;
|
||||
ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId());
|
||||
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
|
||||
//if System VM template has been changed, update vm templateId if this is a System VM
|
||||
if(VirtualMachine.Type.DomainRouter.equals(vm.getType())
|
||||
|| VirtualMachine.Type.ConsoleProxy.equals(vm.getType())
|
||||
|| VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())){
|
||||
VMTemplateVO systemVMTemplate = _templateDao.findSystemVMTemplate(vm.getDataCenterId(), vm.getHypervisorType());
|
||||
if(template != null && systemVMTemplate != null){
|
||||
if(template.getId() != systemVMTemplate.getId()){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("System VM's templateId does not match the current System VM Template, updating templateId of the VM: "+ vm);
|
||||
}
|
||||
vm.setTemplateId(systemVMTemplate.getId());
|
||||
_vmDao.update(vm.getId(), vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Long clusterSpecified = null;
|
||||
if(hostIdSpecified != null){
|
||||
@ -582,50 +567,48 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
|
||||
|
||||
try {
|
||||
Journal journal = start.second().getJournal();
|
||||
|
||||
//edit plan if this vm's ROOT volume is in READY state already
|
||||
VolumeVO readyRootVolume = null;
|
||||
List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
|
||||
|
||||
for (VolumeVO vol : vols) {
|
||||
Volume.State state = vol.getState();
|
||||
if (state == Volume.State.Ready) {
|
||||
//make sure if this is a System VM, templateId is unchanged. If it is changed, let planner
|
||||
//reassign pool for the volume
|
||||
if(VirtualMachine.Type.isSystemVM(vm.getType())){
|
||||
Long volTemplateId = vol.getTemplateId();
|
||||
if(volTemplateId != null && template != null){
|
||||
if(volTemplateId.longValue() != template.getId()){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Root Volume " + vol + " of "+vm.getType().toString() +" System VM is ready, but volume's templateId does not match the System VM Template, updating templateId and reassigning a new pool");
|
||||
}
|
||||
vol.setTemplateId(template.getId());
|
||||
_volsDao.update(vol.getId(), vol);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
|
||||
if (!pool.isInMaintenance()) {
|
||||
long rootVolDcId = pool.getDataCenterId();
|
||||
Long rootVolPodId = pool.getPodId();
|
||||
Long rootVolClusterId = pool.getClusterId();
|
||||
plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId());
|
||||
readyRootVolume = vol;
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Root Volume " + vol + " is ready, changing deployment plan to use this pool's datacenterId: "+rootVolDcId +" , podId: "+rootVolPodId +" , and clusterId: "+rootVolClusterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExcludeList avoids = new ExcludeList();
|
||||
int retry = _retry;
|
||||
while (retry-- != 0) { // It's != so that it can match -1.
|
||||
|
||||
//edit plan if this vm's ROOT volume is in READY state already
|
||||
List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
|
||||
|
||||
for (VolumeVO vol : vols) {
|
||||
Volume.State state = vol.getState();
|
||||
if (state == Volume.State.Ready) {
|
||||
//make sure if this is a System VM, templateId is unchanged. If it is changed, let planner
|
||||
//reassign pool for the volume
|
||||
if(VirtualMachine.Type.DomainRouter.equals(vm.getType())
|
||||
|| VirtualMachine.Type.ConsoleProxy.equals(vm.getType())
|
||||
|| VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())){
|
||||
|
||||
Long volTemplateId = vol.getTemplateId();
|
||||
VMTemplateVO systemVMTemplate = _templateDao.findSystemVMTemplate(vm.getDataCenterId(), vm.getHypervisorType());
|
||||
if(volTemplateId != null && systemVMTemplate != null){
|
||||
if(volTemplateId.longValue() != systemVMTemplate.getId()){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Root Volume " + vol + " of "+vm.getType().toString() +" System VM is ready, but volume's templateId does not match the System VM Template, updating templateId and reassigning a new pool");
|
||||
}
|
||||
vol.setTemplateId(systemVMTemplate.getId());
|
||||
_volsDao.update(vol.getId(), vol);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
|
||||
if (!pool.isInMaintenance()) {
|
||||
long rootVolDcId = pool.getDataCenterId();
|
||||
Long rootVolPodId = pool.getPodId();
|
||||
Long rootVolClusterId = pool.getClusterId();
|
||||
plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Root Volume " + vol + " is ready, changing deployment plan to use this pool's datacenterId: "+rootVolDcId +" , podId: "+rootVolPodId +" , and clusterId: "+rootVolClusterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, account, params);
|
||||
DeployDestination dest = null;
|
||||
for (DeploymentPlanner planner : _planners) {
|
||||
@ -653,6 +636,15 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
|
||||
|
||||
try {
|
||||
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
|
||||
if(readyRootVolume != null){
|
||||
//remove the vol<->pool from destination, since we don't have to prepare this volume.
|
||||
if(dest.getStorageForDisks() != null){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No need to prepare the READY Root Volume " + readyRootVolume + ", removing it from deploydestination");
|
||||
}
|
||||
dest.getStorageForDisks().remove(readyRootVolume);
|
||||
}
|
||||
}
|
||||
_storageMgr.prepare(vmProfile, dest);
|
||||
}
|
||||
_networkMgr.prepare(vmProfile, dest, ctx);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user