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:
prachi 2011-04-13 13:46:42 -07:00
parent 8abda2fdd0
commit b1700af146
4 changed files with 91 additions and 91 deletions

View File

@ -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();

View File

@ -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");
}
}
}

View File

@ -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) {

View File

@ -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);