CLOUDSTACK-5873: [Automation] Failed to attach volume to VM, if the vm is created with option startvm=false

This commit is contained in:
Mike Tutkowski 2014-01-15 14:33:15 -07:00
parent 151c239812
commit e2364cfca6
4 changed files with 86 additions and 20 deletions

View File

@ -1123,15 +1123,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
Map<String, String> details = disk.getDetails();
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
if (isManaged && disk.getPath() == null) {
if (isManaged) {
Long volumeId = disk.getData().getId();
VolumeVO volume = _volsDao.findById(volumeId);
String iScsiName = volume.get_iScsiName();
String path = iqnToPath.get(iScsiName);
volume.setPath(path);
if (path != null) {
volume.setPath(path);
_volsDao.update(volumeId, volume);
_volsDao.update(volumeId, volume);
}
}
}
}

View File

@ -438,6 +438,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
@DB
public VolumeInfo createVolume(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering,
DiskOffering diskOffering, List<StoragePool> avoids, long size, HypervisorType hyperType) {
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
volume = updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType);
StoragePool pool = null;
@ -1156,6 +1157,14 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
// retry one more time in case of template reload is required for Vmware case
AsyncCallFuture<VolumeApiResult> future = null;
if (templateId == null) {
DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType);
volume = volFactory.getVolume(newVol.getId(), destPool);
future = volService.createVolumeAsync(volume, destPool);
} else {
TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image);
@ -1174,6 +1183,16 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
throw new StorageUnavailableException("Unable to create " + newVol + ":" + result.getResult(), destPool.getId());
}
}
StoragePoolVO storagePool = _storagePoolDao.findById(destPool.getId());
if (newVol.getVolumeType() == Type.DATADISK && storagePool.isManaged()) {
long hostId = vm.getVirtualMachine().getHostId();
Host host = _hostDao.findById(hostId);
volService.connectVolumeToHost(volFactory.getVolume(newVol.getId()), host, destPool);
}
newVol = _volsDao.findById(newVol.getId());
break; //break out of template-redeploy retry loop
} catch (InterruptedException e) {

View File

@ -1192,10 +1192,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
}
protected VBD createVbd(Connection conn, DiskTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException {
protected VBD createVbd(Connection conn, DiskTO volume, String vmName, VM vm, BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException {
Volume.Type type = volume.getType();
VDI vdi = mount(conn, vmName, volume);
if (vdi == null) {
vdi = mount(conn, vmName, volume);
}
if ( vdi != null ) {
if ("detached".equals(vdi.getNameLabel(conn))) {
@ -1686,7 +1688,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
vm = createVmFromTemplate(conn, vmSpec, host);
for (DiskTO disk : vmSpec.getDisks()) {
createVbd(conn, disk, vmName, vm, vmSpec.getBootloader());
VDI newVdi = prepareManagedDisk(conn, disk, vmName);
if (newVdi != null) {
String path = newVdi.getUuid(conn);
iqnToPath.put(disk.getDetails().get(DiskTO.IQN), path);
}
createVbd(conn, disk, vmName, vm, vmSpec.getBootloader(), newVdi);
}
if (vmSpec.getType() != VirtualMachine.Type.User) {
@ -1796,6 +1806,53 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
}
// the idea here is to see if the DiskTO in question is from managed storage and
// does not yet have an SR
// if no SR, create it and create a VDI in it
private VDI prepareManagedDisk(Connection conn, DiskTO disk, String vmName) throws Exception {
Map<String, String> details = disk.getDetails();
if (details == null) {
return null;
}
boolean isManaged = new Boolean(details.get(DiskTO.MANAGED)).booleanValue();
if (!isManaged) {
return null;
}
String iqn = details.get(DiskTO.IQN);
Set<SR> srNameLabels = SR.getByNameLabel(conn, iqn);
if (srNameLabels.size() != 0) {
return null;
}
String vdiNameLabel = vmName + "-DATA";
return prepareManagedStorage(conn, details, null, vdiNameLabel);
}
protected VDI prepareManagedStorage(Connection conn, Map<String, String> details, String path, String vdiNameLabel) throws Exception {
String iScsiName = details.get(DiskTO.IQN);
String storageHost = details.get(DiskTO.STORAGE_HOST);
String chapInitiatorUsername = details.get(DiskTO.CHAP_INITIATOR_USERNAME);
String chapInitiatorSecret = details.get(DiskTO.CHAP_INITIATOR_SECRET);
Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE));
SR sr = getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true);
VDI vdi = getVDIbyUuid(conn, path, false);
if (vdi == null) {
vdi = createVdi(sr, vdiNameLabel, volumeSize);
}
return vdi;
}
protected Answer execute(ModifySshKeysCommand cmd) {
return new Answer(cmd);
}

View File

@ -185,7 +185,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
catch (CloudRuntimeException ex) {
}
Map<String, String> details = cmd.getDisk().getDetails();
Map<String, String> details = disk.getDetails();
boolean isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
// if the VM is not running and we're not dealing with managed storage, just return success (nothing to do here)
@ -197,19 +197,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
VDI vdi = null;
if (isManaged) {
String iScsiName = details.get(DiskTO.IQN);
String storageHost = details.get(DiskTO.STORAGE_HOST);
String chapInitiatorUsername = disk.getDetails().get(DiskTO.CHAP_INITIATOR_USERNAME);
String chapInitiatorSecret = disk.getDetails().get(DiskTO.CHAP_INITIATOR_SECRET);
Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE));
SR sr = this.hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true);
vdi = hypervisorResource.getVDIbyUuid(conn, data.getPath(), false);
if (vdi == null) {
vdi = hypervisorResource.createVdi(sr, vdiNameLabel, volumeSize);
}
vdi = hypervisorResource.prepareManagedStorage(conn, details, data.getPath(), vdiNameLabel);
if (vmNotRunning) {
DiskTO newDisk = new DiskTO(disk.getData(), disk.getDiskSeq(), vdi.getUuid(conn), disk.getType());