mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Allow template re-deployment once template is deleted from hypervisor and CloudStack still holds out-dated status
This commit is contained in:
parent
8d44058010
commit
65d4cc98be
@ -22,6 +22,7 @@ import com.cloud.agent.api.to.VolumeTO;
|
||||
|
||||
public class CreateAnswer extends Answer {
|
||||
VolumeTO volume;
|
||||
boolean requestTemplateReload = false;
|
||||
protected CreateAnswer() {
|
||||
}
|
||||
|
||||
@ -34,6 +35,11 @@ public class CreateAnswer extends Answer {
|
||||
super(cmd, false, details);
|
||||
}
|
||||
|
||||
public CreateAnswer(CreateCommand cmd, String details, boolean requestTemplateReload) {
|
||||
super(cmd, false, details);
|
||||
this.requestTemplateReload = requestTemplateReload;
|
||||
}
|
||||
|
||||
public CreateAnswer(CreateCommand cmd, Exception e) {
|
||||
super(cmd, e);
|
||||
}
|
||||
@ -41,4 +47,8 @@ public class CreateAnswer extends Answer {
|
||||
public VolumeTO getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public boolean templateReloadRequested() {
|
||||
return requestTemplateReload;
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExceptionUtil;
|
||||
import com.cloud.utils.mgmt.JmxUtil;
|
||||
import com.cloud.utils.net.MacAddress;
|
||||
import com.google.gson.Gson;
|
||||
@ -351,7 +352,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe
|
||||
try {
|
||||
JmxUtil.registerMBean("AsyncJobManager", "Active Job " + job.getId(), new AsyncJobMBeanImpl(job));
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unable to register active job " + job.getId() + " to JMX minotoring");
|
||||
s_logger.warn("Unable to register active job " + job.getId() + " to JMX minotoring due to exception " + ExceptionUtil.toString(e));
|
||||
}
|
||||
|
||||
BaseAsyncCmd cmdObj = null;
|
||||
|
||||
@ -49,6 +49,7 @@ import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.events.SubscriptionMgr;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExceptionUtil;
|
||||
import com.cloud.utils.mgmt.JmxUtil;
|
||||
import com.cloud.utils.net.MacAddress;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
@ -618,7 +619,7 @@ public class ClusterManagerImpl implements ClusterManager {
|
||||
try {
|
||||
JmxUtil.registerMBean("ClusterManager", "Node " + mshost.getId(), new ClusterManagerMBeanImpl(this, mshost));
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unable to regiester cluster node into JMX monitoring due to exception " + e.toString());
|
||||
s_logger.warn("Unable to regiester cluster node into JMX monitoring due to exception " + ExceptionUtil.toString(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.HypervisorGuruManager;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.router.VirtualNetworkApplianceManager;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.server.ManagementServer;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
@ -179,7 +178,6 @@ import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.VirtualMachineProfileImpl;
|
||||
import com.cloud.vm.dao.ConsoleProxyDao;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||
@ -649,25 +647,39 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
|
||||
CreateCommand cmd = null;
|
||||
VMTemplateStoragePoolVO tmpltStoredOn = null;
|
||||
if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
|
||||
tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool);
|
||||
if (tmpltStoredOn == null) {
|
||||
continue;
|
||||
}
|
||||
cmd = new CreateCommand(dskCh, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool));
|
||||
} else {
|
||||
cmd = new CreateCommand(dskCh, new StorageFilerTO(pool));
|
||||
}
|
||||
|
||||
try {
|
||||
Answer answer = sendToPool(pool, cmd);
|
||||
if (answer != null && answer.getResult()) {
|
||||
created = ((CreateAnswer) answer).getVolume();
|
||||
break;
|
||||
}
|
||||
} catch (StorageUnavailableException e) {
|
||||
s_logger.debug("Storage unavailable for " + pool.getId());
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
|
||||
tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool);
|
||||
if (tmpltStoredOn == null) {
|
||||
continue;
|
||||
}
|
||||
cmd = new CreateCommand(dskCh, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool));
|
||||
} else {
|
||||
cmd = new CreateCommand(dskCh, new StorageFilerTO(pool));
|
||||
}
|
||||
|
||||
try {
|
||||
Answer answer = sendToPool(pool, cmd);
|
||||
if (answer != null && answer.getResult()) {
|
||||
created = ((CreateAnswer) answer).getVolume();
|
||||
break;
|
||||
}
|
||||
|
||||
if(tmpltStoredOn != null && answer != null && (answer instanceof CreateAnswer) && ((CreateAnswer)answer).templateReloadRequested()) {
|
||||
if(!_tmpltMgr.resetTemplateDownloadStateOnPool(tmpltStoredOn.getId()))
|
||||
break; // break out of template-redeploy retry loop
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} catch (StorageUnavailableException e) {
|
||||
s_logger.debug("Storage unavailable for " + pool.getId());
|
||||
break; // break out of template-redeploy retry loop
|
||||
}
|
||||
}
|
||||
|
||||
if(created != null)
|
||||
break;
|
||||
|
||||
s_logger.debug("Retrying the create because it failed on pool " + pool);
|
||||
}
|
||||
@ -694,8 +706,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
volume.setPodId(pod.getId());
|
||||
volume.setState(Volume.State.Ready);
|
||||
_volsDao.persist(volume);
|
||||
|
||||
|
||||
}
|
||||
txn.commit();
|
||||
return volume;
|
||||
@ -2544,22 +2554,32 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
}
|
||||
|
||||
CreateCommand cmd = null;
|
||||
if (template != null && template.getFormat() != Storage.ImageFormat.ISO) {
|
||||
VMTemplateStoragePoolVO tmpltStoredOn = null;
|
||||
tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool);
|
||||
if (tmpltStoredOn == null) {
|
||||
s_logger.debug("Cannot use this pool " + pool + " because we can't propagate template " + template);
|
||||
return null;
|
||||
}
|
||||
cmd = new CreateCommand(diskProfile, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool));
|
||||
} else {
|
||||
cmd = new CreateCommand(diskProfile, new StorageFilerTO(pool));
|
||||
}
|
||||
long[] hostIdsToTryFirst = {dest.getHost().getId()};
|
||||
Answer answer = sendToPool(pool, hostIdsToTryFirst, cmd);
|
||||
if (answer.getResult()) {
|
||||
CreateAnswer createAnswer = (CreateAnswer) answer;
|
||||
return new Pair<VolumeTO, StoragePool>(createAnswer.getVolume(), pool);
|
||||
VMTemplateStoragePoolVO tmpltStoredOn = null;
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
if (template != null && template.getFormat() != Storage.ImageFormat.ISO) {
|
||||
tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool);
|
||||
if (tmpltStoredOn == null) {
|
||||
s_logger.debug("Cannot use this pool " + pool + " because we can't propagate template " + template);
|
||||
return null;
|
||||
}
|
||||
cmd = new CreateCommand(diskProfile, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool));
|
||||
} else {
|
||||
cmd = new CreateCommand(diskProfile, new StorageFilerTO(pool));
|
||||
}
|
||||
long[] hostIdsToTryFirst = {dest.getHost().getId()};
|
||||
Answer answer = sendToPool(pool, hostIdsToTryFirst, cmd);
|
||||
if (answer.getResult()) {
|
||||
CreateAnswer createAnswer = (CreateAnswer) answer;
|
||||
return new Pair<VolumeTO, StoragePool>(createAnswer.getVolume(), pool);
|
||||
} else {
|
||||
if(tmpltStoredOn != null && (answer instanceof CreateAnswer) && ((CreateAnswer)answer).templateReloadRequested()) {
|
||||
if(!_tmpltMgr.resetTemplateDownloadStateOnPool(tmpltStoredOn.getId()))
|
||||
break; // break out of template-redeploy retry loop
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -70,6 +70,8 @@ public interface TemplateManager {
|
||||
*/
|
||||
VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO template, StoragePool pool);
|
||||
|
||||
boolean resetTemplateDownloadStateOnPool(long templateStoragePoolRefId);
|
||||
|
||||
/**
|
||||
* Copies a template from its current secondary storage server to the secondary storage server in the specified zone.
|
||||
* @param templateId
|
||||
|
||||
@ -714,6 +714,27 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean resetTemplateDownloadStateOnPool(long templateStoragePoolRefId) {
|
||||
// have to use the same lock that prepareTemplateForCreate use to maintain state consistency
|
||||
VMTemplateStoragePoolVO templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200);
|
||||
|
||||
if (templateStoragePoolRef == null) {
|
||||
s_logger.warn("resetTemplateDownloadStateOnPool failed - unable to lock TemplateStorgePoolRef " + templateStoragePoolRefId);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
templateStoragePoolRef.setDownloadState(VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED);
|
||||
_tmpltPoolDao.update(templateStoragePoolRefId, templateStoragePoolRef);
|
||||
} finally {
|
||||
_tmpltPoolDao.releaseFromLockTable(templateStoragePoolRefId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean copy(long userId, long templateId, long sourceZoneId, long destZoneId) throws StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user