VMTemplateVO rootDiskTmplt = _templateDao.findById(vm
.getTemplateId());
DataCenterVO dcVO = _dcDao.findById(vm
.getDataCenterId());
HostPodVO pod = _podDao.findById(vm.getPodIdToDeployIn());
StoragePoolVO rootDiskPool = _storagePoolDao
.findById(rootVolumeOfVm.getPoolId());
ServiceOfferingVO svo = _serviceOfferingDao.findById(vm
.getServiceOfferingId());
DiskOfferingVO diskVO = _diskOfferingDao.findById(volume
.getDiskOfferingId());
Long clusterId = (rootDiskPool == null ? null : rootDiskPool
.getClusterId());
if (!isVolumeOnSec) {
volume = _storageMgr.createVolume(volume, vm,
rootDiskTmplt, dcVO, pod, clusterId, svo, diskVO,
new ArrayList<StoragePoolVO>(), volume.getSize(),
rootDiskHyperType);
} else {
try {
// Format of data disk should be the same as root disk
if (!volHostVO
.getFormat()
.getFileExtension()
.equals(_storageMgr
.getSupportedImageFormatForCluster(rootDiskPool
.getClusterId()))) {
throw new InvalidParameterValueException(
"Failed to attach volume to VM since volumes format "
+ volHostVO.getFormat()
.getFileExtension()
+ " is not compatible with the vm hypervisor type");
}
// Check that there is some shared storage.
StoragePoolVO vmRootVolumePool = _storagePoolDao
.findById(rootVolumeOfVm.getPoolId());
List<StoragePoolVO> sharedVMPools = _storagePoolDao
.findPoolsByTags(
vmRootVolumePool.getDataCenterId(),
vmRootVolumePool.getPodId(),
vmRootVolumePool.getClusterId(), null,
true);
if (sharedVMPools.size() == 0) {
throw new CloudRuntimeException(
"Cannot attach volume since there are no shared storage pools in the VM's cluster to copy the uploaded volume to.");
}
volume = _storageMgr.copyVolumeFromSecToPrimary(volume,
vm, rootDiskTmplt, dcVO, pod,
rootDiskPool.getClusterId(), svo, diskVO,
new ArrayList<StoragePoolVO>(),
volume.getSize(), rootDiskHyperType);
} catch (NoTransitionException e) {
throw new CloudRuntimeException(
"Unable to transition the volume ", e);
}
}
if (volume == null) {
throw new CloudRuntimeException(
"Failed to create volume when attaching it to VM: "
+ vm.getHostName());
}
}
StoragePoolVO vmRootVolumePool = _storagePoolDao
.findById(rootVolumeOfVm.getPoolId());
DiskOfferingVO volumeDiskOffering = _diskOfferingDao
.findById(volume.getDiskOfferingId());
String[] volumeTags = volumeDiskOffering.getTagsArray();
boolean isVolumeOnSharedPool = !volumeDiskOffering
.getUseLocalStorage();
StoragePoolVO sourcePool = _storagePoolDao.findById(volume
.getPoolId());
List<StoragePoolVO> matchingVMPools = _storagePoolDao
.findPoolsByTags(vmRootVolumePool.getDataCenterId(),
vmRootVolumePool.getPodId(),
vmRootVolumePool.getClusterId(), volumeTags,
isVolumeOnSharedPool);
boolean moveVolumeNeeded = true;
if (matchingVMPools.size() == 0) {
String poolType;
if (vmRootVolumePool.getClusterId() != null) {
poolType = "cluster";
} else if (vmRootVolumePool.getPodId() != null) {
poolType = "pod";
} else {
poolType = "zone";
}
throw new CloudRuntimeException(
"There are no storage pools in the VM's " + poolType
+ " with all of the volume's tags ("
+ volumeDiskOffering.getTags() + ").");
} else {
long sourcePoolId = sourcePool.getId();
Long sourcePoolDcId = sourcePool.getDataCenterId();
Long sourcePoolPodId = sourcePool.getPodId();
Long sourcePoolClusterId = sourcePool.getClusterId();
for (StoragePoolVO vmPool : matchingVMPools) {
long vmPoolId = vmPool.getId();
Long vmPoolDcId = vmPool.getDataCenterId();
Long vmPoolPodId = vmPool.getPodId();
Long vmPoolClusterId = vmPool.getClusterId();
// Moving a volume is not required if storage pools belongs
// to same cluster in case of shared volume or
// identical storage pool in case of local
if (sourcePoolDcId == vmPoolDcId
&& sourcePoolPodId == vmPoolPodId
&& sourcePoolClusterId == vmPoolClusterId
&& (isVolumeOnSharedPool || sourcePoolId == vmPoolId)) {
moveVolumeNeeded = false;
break;
}
}
}
if (moveVolumeNeeded) {
if (isVolumeOnSharedPool) {
// Move the volume to a storage pool in the VM's zone, pod,
// or cluster
try {
volume = _storageMgr.moveVolume(volume,
vmRootVolumePool.getDataCenterId(),
vmRootVolumePool.getPodId(),
vmRootVolumePool.getClusterId(),
dataDiskHyperType);
} catch (ConcurrentOperationException e) {
throw new CloudRuntimeException(e.toString());
}
} else {
throw new CloudRuntimeException(
"Failed to attach local data volume "
+ volume.getName()
+ " to VM "
+ vm.getDisplayName()
+ " as migration of local data volume is not allowed");
}
}
}
AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor
.getCurrentExecutor();
if (asyncExecutor != null) {
AsyncJobVO job = asyncExecutor.getJob();
if (s_logger.isInfoEnabled()) {
s_logger.info("Trying to attaching volume " + volumeId
+ " to vm instance:" + vm.getId()
+ ", update async job-" + job.getId()
+ " progress status");
}
_asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volumeId);
_asyncMgr.updateAsyncJobStatus(job.getId(),
BaseCmd.PROGRESS_INSTANCE_CREATED, volumeId);
}
String errorMsg = "Failed to attach volume: " + volume.getName()
+ " to VM: " + vm.getHostName();
boolean sendCommand = (vm.getState() == State.Running);
AttachVolumeAnswer answer = null;
Long hostId = vm.getHostId();
if (hostId == null) {
hostId = vm.getLastHostId();
HostVO host = _hostDao.findById(hostId);
if (host != null
&& host.getHypervisorType() == HypervisorType.VMware) {
sendCommand = true;
}
}
if (sendCommand) {
StoragePoolVO volumePool = _storagePoolDao.findById(volume
.getPoolId());
AttachVolumeCommand cmd = new AttachVolumeCommand(true,
vm.getInstanceName(), volume.getPoolType(),
volume.getFolder(), volume.getPath(), volume.getName(),
deviceId, volume.getChainInfo());
cmd.setPoolUuid(volumePool.getUuid());
try {
answer = (AttachVolumeAnswer) _agentMgr.send(hostId, cmd);
} catch (Exception e) {
throw new CloudRuntimeException(errorMsg + " due to: "