133133import com .cloud .dc .DataCenter ;
134134import com .cloud .dc .DataCenterVO ;
135135import com .cloud .dc .Pod ;
136- import com .cloud .dc .dao .ClusterDao ;
137136import com .cloud .dc .dao .DataCenterDao ;
138- import com .cloud .dc .dao .HostPodDao ;
139137import com .cloud .domain .Domain ;
140138import com .cloud .domain .dao .DomainDao ;
141139import com .cloud .event .ActionEvent ;
155153import com .cloud .hypervisor .HypervisorCapabilitiesVO ;
156154import com .cloud .hypervisor .dao .HypervisorCapabilitiesDao ;
157155import com .cloud .offering .DiskOffering ;
158- import com .cloud .org .Cluster ;
159156import com .cloud .org .Grouping ;
160157import com .cloud .projects .Project ;
161158import com .cloud .projects .ProjectManager ;
@@ -326,8 +323,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
326323 @ Inject
327324 private VmWorkJobDao _workJobDao ;
328325 @ Inject
329- ClusterDao clusterDao ;
330- @ Inject
331326 private ClusterDetailsDao _clusterDetailsDao ;
332327 @ Inject
333328 private StorageManager storageMgr ;
@@ -351,8 +346,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
351346 protected ProjectManager projectManager ;
352347 @ Inject
353348 protected StoragePoolDetailsDao storagePoolDetailsDao ;
354- @ Inject
355- HostPodDao podDao ;
356349
357350
358351 protected Gson _gson ;
@@ -2387,18 +2380,25 @@ public Volume attachVolumeToVM(AttachVolumeCmd command) {
23872380 return attachVolumeToVM (command .getVirtualMachineId (), command .getId (), command .getDeviceId ());
23882381 }
23892382
2390- protected VolumeVO getVmExistingVolumeForVolumeAttach (UserVmVO vm , VolumeInfo volumeToAttach ) {
2383+ private Volume orchestrateAttachVolumeToVM (Long vmId , Long volumeId , Long deviceId ) {
2384+ VolumeInfo volumeToAttach = volFactory .getVolume (volumeId );
2385+
2386+ if (volumeToAttach .isAttachedVM ()) {
2387+ throw new CloudRuntimeException ("This volume is already attached to a VM." );
2388+ }
2389+
2390+ UserVmVO vm = _userVmDao .findById (vmId );
23912391 VolumeVO existingVolumeOfVm = null ;
23922392 VMTemplateVO template = _templateDao .findById (vm .getTemplateId ());
2393- List <VolumeVO > rootVolumesOfVm = _volsDao .findByInstanceAndType (vm . getId () , Volume .Type .ROOT );
2393+ List <VolumeVO > rootVolumesOfVm = _volsDao .findByInstanceAndType (vmId , Volume .Type .ROOT );
23942394 if (rootVolumesOfVm .size () > 1 && template != null && !template .isDeployAsIs ()) {
23952395 throw new CloudRuntimeException ("The VM " + vm .getHostName () + " has more than one ROOT volume and is in an invalid state." );
23962396 } else {
23972397 if (!rootVolumesOfVm .isEmpty ()) {
23982398 existingVolumeOfVm = rootVolumesOfVm .get (0 );
23992399 } else {
24002400 // locate data volume of the vm
2401- List <VolumeVO > diskVolumesOfVm = _volsDao .findByInstanceAndType (vm . getId () , Volume .Type .DATADISK );
2401+ List <VolumeVO > diskVolumesOfVm = _volsDao .findByInstanceAndType (vmId , Volume .Type .DATADISK );
24022402 for (VolumeVO diskVolume : diskVolumesOfVm ) {
24032403 if (diskVolume .getState () != Volume .State .Allocated ) {
24042404 existingVolumeOfVm = diskVolume ;
@@ -2407,89 +2407,45 @@ protected VolumeVO getVmExistingVolumeForVolumeAttach(UserVmVO vm, VolumeInfo vo
24072407 }
24082408 }
24092409 }
2410- if (existingVolumeOfVm == null ) {
2411- if (s_logger .isTraceEnabled ()) {
2412- s_logger .trace (String .format ("No existing volume found for VM (%s/%s) to attach volume %s/%s" ,
2410+ if (s_logger .isTraceEnabled ()) {
2411+ String msg = "attaching volume %s/%s to a VM (%s/%s) with an existing volume %s/%s on primary storage %s" ;
2412+ if (existingVolumeOfVm != null ) {
2413+ s_logger .trace (String .format (msg ,
2414+ volumeToAttach .getName (), volumeToAttach .getUuid (),
24132415 vm .getName (), vm .getUuid (),
2414- volumeToAttach .getName (), volumeToAttach .getUuid ()));
2416+ existingVolumeOfVm .getName (), existingVolumeOfVm .getUuid (),
2417+ existingVolumeOfVm .getPoolId ()));
24152418 }
2416- return null ;
24172419 }
2418- if (s_logger .isTraceEnabled ()) {
2419- String msg = "attaching volume %s/%s to a VM (%s/%s) with an existing volume %s/%s on primary storage %s" ;
2420- s_logger .trace (String .format (msg ,
2421- volumeToAttach .getName (), volumeToAttach .getUuid (),
2422- vm .getName (), vm .getUuid (),
2423- existingVolumeOfVm .getName (), existingVolumeOfVm .getUuid (),
2424- existingVolumeOfVm .getPoolId ()));
2425- }
2426- return existingVolumeOfVm ;
2427- }
2428-
2429- protected StoragePool getPoolForAllocatedOrUploadedVolumeForAttach (final VolumeInfo volumeToAttach , final UserVmVO vm ) {
2430- DataCenter zone = _dcDao .findById (vm .getDataCenterId ());
2431- Pair <Long , Long > clusterHostId = virtualMachineManager .findClusterAndHostIdForVm (vm , false );
2432- long podId = vm .getPodIdToDeployIn ();
2433- if (clusterHostId .first () != null ) {
2434- Cluster cluster = clusterDao .findById (clusterHostId .first ());
2435- podId = cluster .getPodId ();
2436- }
2437- Pod pod = podDao .findById (podId );
2438- DiskOfferingVO offering = _diskOfferingDao .findById (volumeToAttach .getDiskOfferingId ());
2439- DiskProfile diskProfile = new DiskProfile (volumeToAttach .getId (), volumeToAttach .getVolumeType (),
2440- volumeToAttach .getName (), volumeToAttach .getId (), volumeToAttach .getSize (), offering .getTagsArray (),
2441- offering .isUseLocalStorage (), offering .isRecreatable (),
2442- volumeToAttach .getTemplateId ());
2443- diskProfile .setHyperType (vm .getHypervisorType ());
2444- StoragePool pool = _volumeMgr .findStoragePool (diskProfile , zone , pod , clusterHostId .first (),
2445- clusterHostId .second (), vm , Collections .emptySet ());
2446- if (pool == null ) {
2447- throw new CloudRuntimeException (String .format ("Failed to find a primary storage for volume in state: %s" , volumeToAttach .getState ()));
2448- }
2449- return pool ;
2450- }
2451-
2452- protected VolumeInfo createVolumeOnPrimaryForAttachIfNeeded (final VolumeInfo volumeToAttach , final UserVmVO vm , VolumeVO existingVolumeOfVm ) {
2420+
2421+ HypervisorType rootDiskHyperType = vm .getHypervisorType ();
2422+ HypervisorType volumeToAttachHyperType = _volsDao .getHypervisorType (volumeToAttach .getId ());
2423+
24532424 VolumeInfo newVolumeOnPrimaryStorage = volumeToAttach ;
2454- boolean volumeOnSecondary = volumeToAttach .getState () == Volume .State .Uploaded ;
2455- if (!Arrays .asList (Volume .State .Allocated , Volume .State .Uploaded ).contains (volumeToAttach .getState ())) {
2456- return newVolumeOnPrimaryStorage ;
2457- }
2425+
24582426 //don't create volume on primary storage if its being attached to the vm which Root's volume hasn't been created yet
2459- StoragePool destPrimaryStorage = null ;
2427+ StoragePoolVO destPrimaryStorage = null ;
24602428 if (existingVolumeOfVm != null && !existingVolumeOfVm .getState ().equals (Volume .State .Allocated )) {
24612429 destPrimaryStorage = _storagePoolDao .findById (existingVolumeOfVm .getPoolId ());
24622430 if (s_logger .isTraceEnabled () && destPrimaryStorage != null ) {
24632431 s_logger .trace (String .format ("decided on target storage: %s/%s" , destPrimaryStorage .getName (), destPrimaryStorage .getUuid ()));
24642432 }
24652433 }
2466- if (destPrimaryStorage == null ) {
2467- destPrimaryStorage = getPoolForAllocatedOrUploadedVolumeForAttach (volumeToAttach , vm );
2468- }
2469- try {
2470- if (volumeOnSecondary && Storage .StoragePoolType .PowerFlex .equals (destPrimaryStorage .getPoolType ())) {
2471- throw new InvalidParameterValueException ("Cannot attach uploaded volume, this operation is unsupported on storage pool type " + destPrimaryStorage .getPoolType ());
2472- }
2473- newVolumeOnPrimaryStorage = _volumeMgr .createVolumeOnPrimaryStorage (vm , volumeToAttach ,
2474- vm .getHypervisorType (), destPrimaryStorage );
2475- } catch (NoTransitionException e ) {
2476- s_logger .debug ("Failed to create volume on primary storage" , e );
2477- throw new CloudRuntimeException ("Failed to create volume on primary storage" , e );
2478- }
2479- return newVolumeOnPrimaryStorage ;
2480- }
24812434
2482- private Volume orchestrateAttachVolumeToVM (Long vmId , Long volumeId , Long deviceId ) {
2483- VolumeInfo volumeToAttach = volFactory .getVolume (volumeId );
2435+ boolean volumeOnSecondary = volumeToAttach .getState () == Volume .State .Uploaded ;
24842436
2485- if (volumeToAttach .isAttachedVM ()) {
2486- throw new CloudRuntimeException ("This volume is already attached to a VM." );
2437+ if (destPrimaryStorage != null && (volumeToAttach .getState () == Volume .State .Allocated || volumeOnSecondary )) {
2438+ try {
2439+ if (volumeOnSecondary && destPrimaryStorage .getPoolType () == Storage .StoragePoolType .PowerFlex ) {
2440+ throw new InvalidParameterValueException ("Cannot attach uploaded volume, this operation is unsupported on storage pool type " + destPrimaryStorage .getPoolType ());
2441+ }
2442+ newVolumeOnPrimaryStorage = _volumeMgr .createVolumeOnPrimaryStorage (vm , volumeToAttach , rootDiskHyperType , destPrimaryStorage );
2443+ } catch (NoTransitionException e ) {
2444+ s_logger .debug ("Failed to create volume on primary storage" , e );
2445+ throw new CloudRuntimeException ("Failed to create volume on primary storage" , e );
2446+ }
24872447 }
24882448
2489- UserVmVO vm = _userVmDao .findById (vmId );
2490- VolumeVO existingVolumeOfVm = getVmExistingVolumeForVolumeAttach (vm , volumeToAttach );
2491- VolumeInfo newVolumeOnPrimaryStorage = createVolumeOnPrimaryForAttachIfNeeded (volumeToAttach , vm , existingVolumeOfVm );
2492-
24932449 // reload the volume from db
24942450 newVolumeOnPrimaryStorage = volFactory .getVolume (newVolumeOnPrimaryStorage .getId ());
24952451 boolean moveVolumeNeeded = needMoveVolume (existingVolumeOfVm , newVolumeOnPrimaryStorage );
@@ -2507,17 +2463,19 @@ private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long device
25072463 StoragePoolVO vmRootVolumePool = _storagePoolDao .findById (existingVolumeOfVm .getPoolId ());
25082464
25092465 try {
2510- HypervisorType volumeToAttachHyperType = _volsDao .getHypervisorType (volumeToAttach .getId ());
25112466 newVolumeOnPrimaryStorage = _volumeMgr .moveVolume (newVolumeOnPrimaryStorage , vmRootVolumePool .getDataCenterId (), vmRootVolumePool .getPodId (), vmRootVolumePool .getClusterId (),
25122467 volumeToAttachHyperType );
2513- } catch (ConcurrentOperationException | StorageUnavailableException e ) {
2468+ } catch (ConcurrentOperationException e ) {
2469+ s_logger .debug ("move volume failed" , e );
2470+ throw new CloudRuntimeException ("move volume failed" , e );
2471+ } catch (StorageUnavailableException e ) {
25142472 s_logger .debug ("move volume failed" , e );
25152473 throw new CloudRuntimeException ("move volume failed" , e );
25162474 }
25172475 }
25182476 VolumeVO newVol = _volsDao .findById (newVolumeOnPrimaryStorage .getId ());
25192477 // Getting the fresh vm object in case of volume migration to check the current state of VM
2520- if (moveVolumeNeeded ) {
2478+ if (moveVolumeNeeded || volumeOnSecondary ) {
25212479 vm = _userVmDao .findById (vmId );
25222480 if (vm == null ) {
25232481 throw new InvalidParameterValueException ("VM not found." );
@@ -2701,6 +2659,9 @@ private void checkDeviceId(Long deviceId, VolumeInfo volumeToAttach, UserVmVO vm
27012659 if (!_volsDao .findByInstanceAndDeviceId (vm .getId (), 0 ).isEmpty ()) {
27022660 throw new InvalidParameterValueException ("Vm already has root volume attached to it" );
27032661 }
2662+ if (volumeToAttach .getState () == Volume .State .Uploaded ) {
2663+ throw new InvalidParameterValueException ("No support for Root volume attach in state " + Volume .State .Uploaded );
2664+ }
27042665 }
27052666 }
27062667
0 commit comments