You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by nv...@apache.org on 2021/06/16 18:39:40 UTC

[cloudstack] branch main updated (07cabbe -> d2ab350)

This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git.


    from 07cabbe  scaleio: Updated PowerFlex/ScaleIO gateway client with some improvements. (#5037)
     add 12b2e80  vmware: Fix fetching chain_info of the volumes. It is used to assume datastore names are in the form of UUIDs but it can be any name. So fetch chain_info based on the datastore name. (#5097)
     add 9dd0acf  ui: add action syncStoragePool (#5098)
     add bc12833  server: Failed to scale between Service Offerings with the same root disk size (#5095)
     add b6e4329  ui: Greek (Hellenic) translation (#5109)
     add 006d0fe  ui: show read from ova only for ova format (#5108)
     add 67182dc  vxlan: arp does not work between hosts as multicast group is communicated over physical nic instead of linux bridge (#5078)
     add 2e32c2f  travis: allow big contents from error output in marvin tests (#5113)
     add 326e03b  ui: Fix typo in error message on login page (#5118)
     add 46a3032  server: set correct gateway when update vm nic on shared networks (#5105)
     new d2ab350  Merge branch '4.15' into main

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |    3 +
 .../hypervisor/kvm/resource/BridgeVifDriver.java   |    4 +-
 .../hypervisor/kvm/resource/IvsVifDriver.java      |    2 +-
 .../hypervisor/vmware/resource/VmwareResource.java |    7 +-
 .../java/com/cloud/storage/StorageManagerImpl.java |    2 +-
 .../com/cloud/storage/VolumeApiServiceImpl.java    |   45 +-
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  |    2 +-
 .../cloud/storage/VolumeApiServiceImplTest.java    |   56 +-
 .../test/java/com/cloud/vm/UserVmManagerTest.java  |    5 +-
 tools/travis/xunit-reader.py                       |    2 +-
 ui/public/locales/el_GR.json                       | 3332 ++++++++++++++++++++
 ui/public/locales/en.json                          |    4 +-
 ui/src/components/header/TranslationMenu.vue       |    1 +
 ui/src/config/section/infra/primaryStorages.js     |    8 +
 ui/src/views/image/RegisterOrUploadTemplate.vue    |    6 +-
 15 files changed, 3450 insertions(+), 29 deletions(-)
 create mode 100644 ui/public/locales/el_GR.json

[cloudstack] 01/01: Merge branch '4.15' into main

Posted by nv...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit d2ab350a40cffe4eacf625e1648db7c12341f2cb
Merge: 07cabbe 46a3032
Author: nicolas <ni...@gmail.com>
AuthorDate: Wed Jun 16 15:38:18 2021 -0300

    Merge branch '4.15' into main

 .../com/cloud/vm/VirtualMachineManagerImpl.java    |    3 +
 .../hypervisor/kvm/resource/BridgeVifDriver.java   |    4 +-
 .../hypervisor/kvm/resource/IvsVifDriver.java      |    2 +-
 .../hypervisor/vmware/resource/VmwareResource.java |    7 +-
 .../java/com/cloud/storage/StorageManagerImpl.java |    2 +-
 .../com/cloud/storage/VolumeApiServiceImpl.java    |   45 +-
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  |    2 +-
 .../cloud/storage/VolumeApiServiceImplTest.java    |   56 +-
 .../test/java/com/cloud/vm/UserVmManagerTest.java  |    5 +-
 tools/travis/xunit-reader.py                       |    2 +-
 ui/public/locales/el_GR.json                       | 3332 ++++++++++++++++++++
 ui/public/locales/en.json                          |    4 +-
 ui/src/components/header/TranslationMenu.vue       |    1 +
 ui/src/config/section/infra/primaryStorages.js     |    8 +
 ui/src/views/image/RegisterOrUploadTemplate.vue    |    6 +-
 15 files changed, 3450 insertions(+), 29 deletions(-)

diff --cc engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index e378842,3f435e9..0cb766e
--- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@@ -2395,20 -2297,19 +2395,23 @@@ public class VirtualMachineManagerImpl 
          }
          List<VolumeVO> volumes = _volsDao.findUsableVolumesForInstance(vm.getId());
          if(s_logger.isDebugEnabled()) {
 -            String msg = String.format("found %d volumes for VM %s(uuid:%s, id:%d)", volumes.size(), vm.getInstanceName(), vm.getUuid(), vm.getId());
 +            String msg = String.format("Found %d volumes for VM %s(uuid:%s, id:%d)", results.size(), vm.getInstanceName(), vm.getUuid(), vm.getId());
              s_logger.debug(msg);
          }
 -        for (VolumeObjectTO result : relevantAnswer.getVolumeTos() ) {
 +        for (VolumeObjectTO result : results ) {
              if(s_logger.isDebugEnabled()) {
 -                s_logger.debug(String.format("updating volume (%d) with path '%s' on pool '%d'", result.getId(), result.getPath(), destPool.getId()));
 +                s_logger.debug(String.format("Updating volume (%d) with path '%s' on pool '%s'", result.getId(), result.getPath(), result.getDataStoreUuid()));
              }
              VolumeVO volume = _volsDao.findById(result.getId());
 +            StoragePool pool = _storagePoolDao.findPoolByUUID(result.getDataStoreUuid());
 +            if (volume == null || pool == null) {
 +                continue;
 +            }
              volume.setPath(result.getPath());
 -            volume.setPoolId(destPool.getId());
 +            volume.setPoolId(pool.getId());
+             if (result.getChainInfo() != null) {
+                 volume.setChainInfo(result.getChainInfo());
+             }
              _volsDao.update(volume.getId(), volume);
          }
      }
diff --cc plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index a9a953a,f8fe2d6..f19f7cc
--- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@@ -7302,281 -7539,6 +7302,282 @@@ public class VmwareResource implements 
          return new PrepareUnmanageVMInstanceAnswer(cmd, true, "OK");
      }
  
 +    /*
 +     * Method to relocate a virtual machine. This migrates VM and its volumes to given host, datastores.
 +     * It is used for MigrateVolumeCommand (detached volume case), MigrateVmToPoolCommand and MigrateVmWithStorageCommand.
 +     */
 +
 +    private List<VolumeObjectTO> relocateVirtualMachine(final VmwareHypervisorHost hypervisorHost,
 +                                                        final String name, final VirtualMachineTO vmTo,
 +                                                        final String targetHost, final VmwareHypervisorHost hostInTargetCluster,
 +                                                        final String poolUuid, final List<Pair<VolumeTO, StorageFilerTO>> volToFiler) throws Exception {
 +        String vmName = name;
 +        if (vmName == null && vmTo != null) {
 +            vmName = vmTo.getName();
 +        }
 +        VmwareHypervisorHost sourceHyperHost = hypervisorHost;
 +        VmwareHypervisorHost targetHyperHost = hostInTargetCluster;
 +        VirtualMachineMO vmMo = null;
 +        ManagedObjectReference morSourceHostDc = null;
 +        VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec();
 +        List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
 +        Set<String> mountedDatastoresAtSource = new HashSet<String>();
 +        List<VolumeObjectTO> volumeToList =  new ArrayList<>();
 +        Map<Long, Integer> volumeDeviceKey = new HashMap<Long, Integer>();
 +
 +        try {
 +            if (sourceHyperHost == null) {
 +                sourceHyperHost = getHyperHost(getServiceContext());
 +            }
 +            if (targetHyperHost == null && StringUtils.isNotBlank(targetHost)) {
 +                targetHyperHost = VmwareHelper.getHostMOFromHostName(getServiceContext(), targetHost);
 +            }
 +            morSourceHostDc = sourceHyperHost.getHyperHostDatacenter();
 +            DatacenterMO dcMo = new DatacenterMO(sourceHyperHost.getContext(), morSourceHostDc);
 +            if (targetHyperHost != null) {
 +                ManagedObjectReference morTargetHostDc = targetHyperHost.getHyperHostDatacenter();
 +                if (!morSourceHostDc.getValue().equalsIgnoreCase(morTargetHostDc.getValue())) {
 +                    String msg = "VM " + vmName + " cannot be migrated between different datacenter";
 +                    throw new CloudRuntimeException(msg);
 +                }
 +            }
 +
 +            // find VM through source host (VM is not at the target host yet)
 +            vmMo = sourceHyperHost.findVmOnHyperHost(vmName);
 +            if (vmMo == null) {
 +                String msg = "VM " + vmName + " does not exist on host: " + sourceHyperHost.getHyperHostName();
 +                s_logger.warn(msg);
 +                // find VM through source host (VM is not at the target host yet)
 +                vmMo = dcMo.findVm(vmName);
 +                if (vmMo == null) {
 +                    msg = "VM " + vmName + " does not exist on datacenter: " + dcMo.getName();
 +                    s_logger.error(msg);
 +                    throw new Exception(msg);
 +                }
 +                // VM host has changed
 +                sourceHyperHost = vmMo.getRunningHost();
 +            }
 +
 +            vmName = vmMo.getName();
 +            String srcHostApiVersion = ((HostMO)sourceHyperHost).getHostAboutInfo().getApiVersion();
 +
 +            if (StringUtils.isNotBlank(poolUuid)) {
 +                VmwareHypervisorHost dsHost = targetHyperHost == null ? sourceHyperHost : targetHyperHost;
 +                ManagedObjectReference morDatastore = null;
 +                String msg;
 +                morDatastore = getTargetDatastoreMOReference(poolUuid, dsHost);
 +                if (morDatastore == null) {
 +                    msg = "Unable to find the target datastore: " + poolUuid + " on host: " + dsHost.getHyperHostName() +
 +                            " to execute migration";
 +                    s_logger.error(msg);
 +                    throw new CloudRuntimeException(msg);
 +                }
 +                relocateSpec.setDatastore(morDatastore);
 +            } else if (CollectionUtils.isNotEmpty(volToFiler)) {
 +                // Specify destination datastore location for each volume
 +                VmwareHypervisorHost dsHost = targetHyperHost == null ? sourceHyperHost : targetHyperHost;
 +                for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
 +                    VolumeTO volume = entry.first();
 +                    StorageFilerTO filerTo = entry.second();
 +                    if (s_logger.isDebugEnabled()) {
 +                        s_logger.debug(String.format("Preparing spec for volume: %s to migrate it to datastore: %s", volume.getName(), filerTo.getUuid()));
 +                    }
 +                    ManagedObjectReference morVolumeDatastore = getTargetDatastoreMOReference(filerTo.getUuid(), dsHost);
 +                    if (morVolumeDatastore == null) {
 +                        String msg = "Unable to find the target datastore: " + filerTo.getUuid() + " in datacenter: " + dcMo.getName() + " to execute migration";
 +                        s_logger.error(msg);
 +                        throw new CloudRuntimeException(msg);
 +                    }
 +
 +                    String mountedDs = getMountedDatastoreName(sourceHyperHost, srcHostApiVersion, filerTo);
 +                    if (mountedDs != null) {
 +                        mountedDatastoresAtSource.add(mountedDs);
 +                    }
 +
 +                    if (volume.getType() == Volume.Type.ROOT) {
 +                        relocateSpec.setDatastore(morVolumeDatastore);
 +                    }
 +                    VirtualMachineRelocateSpecDiskLocator diskLocator = new VirtualMachineRelocateSpecDiskLocator();
 +                    diskLocator.setDatastore(morVolumeDatastore);
 +                    Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, volume.getPath() + VMDK_EXTENSION);
 +                    String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
 +                    if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
 +                        vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
 +                    }
 +                    int diskId = diskInfo.first().getKey();
 +                    diskLocator.setDiskId(diskId);
 +
 +                    diskLocators.add(diskLocator);
 +                    volumeDeviceKey.put(volume.getId(), diskId);
 +                }
 +                // If a target datastore is provided for the VM, then by default all volumes associated with the VM will be migrated to that target datastore.
 +                // Hence set the existing datastore as target datastore for volumes that are not to be migrated.
 +                List<Pair<Integer, ManagedObjectReference>> diskDatastores = vmMo.getAllDiskDatastores();
 +                for (Pair<Integer, ManagedObjectReference> diskDatastore : diskDatastores) {
 +                    if (!volumeDeviceKey.containsValue(diskDatastore.first().intValue())) {
 +                        VirtualMachineRelocateSpecDiskLocator diskLocator = new VirtualMachineRelocateSpecDiskLocator();
 +                        diskLocator.setDiskId(diskDatastore.first().intValue());
 +                        diskLocator.setDatastore(diskDatastore.second());
 +                        diskLocators.add(diskLocator);
 +                    }
 +                }
 +
 +                relocateSpec.getDisk().addAll(diskLocators);
 +            }
 +
 +            // Specific section for MigrateVmWithStorageCommand
 +            if (vmTo != null) {
 +                // Prepare network at target before migration
 +                NicTO[] nics = vmTo.getNics();
 +                for (NicTO nic : nics) {
 +                    // prepare network on the host
 +                    prepareNetworkFromNicInfo((HostMO)targetHyperHost, nic, false, vmTo.getType());
 +                }
 +                // Ensure secondary storage mounted on target host
 +                VmwareManager mgr = targetHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
 +                Pair<String, Long> secStoreUrlAndId = mgr.getSecondaryStorageStoreUrlAndId(Long.parseLong(_dcId));
 +                String secStoreUrl = secStoreUrlAndId.first();
 +                Long secStoreId = secStoreUrlAndId.second();
 +                if (secStoreUrl == null) {
 +                    String msg = "secondary storage for dc " + _dcId + " is not ready yet?";
 +                    throw new Exception(msg);
 +                }
 +                mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId);
 +                ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnSpecificHost(secStoreUrl, targetHyperHost);
 +                if (morSecDs == null) {
 +                    String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl;
 +                    throw new Exception(msg);
 +                }
 +            }
 +
 +            if (srcHostApiVersion.compareTo("5.1") < 0) {
 +                // Migrate VM's volumes to target datastore(s).
 +                if (!vmMo.changeDatastore(relocateSpec)) {
 +                    throw new Exception("Change datastore operation failed during storage migration");
 +                } else {
 +                    s_logger.debug("Successfully migrated storage of VM " + vmName + " to target datastore(s)");
 +                }
 +                // Migrate VM to target host.
 +                if (targetHyperHost != null) {
 +                    ManagedObjectReference morPool = targetHyperHost.getHyperHostOwnerResourcePool();
 +                    if (!vmMo.migrate(morPool, targetHyperHost.getMor())) {
 +                        throw new Exception("VM migration to target host failed during storage migration");
 +                    } else {
 +                        s_logger.debug("Successfully migrated VM " + vmName + " from " + sourceHyperHost.getHyperHostName() + " to " + targetHyperHost.getHyperHostName());
 +                    }
 +                }
 +            } else {
 +                // Add target host to relocate spec
 +                if (targetHyperHost != null) {
 +                    relocateSpec.setHost(targetHyperHost.getMor());
 +                    relocateSpec.setPool(targetHyperHost.getHyperHostOwnerResourcePool());
 +                }
 +                if (!vmMo.changeDatastore(relocateSpec)) {
 +                    throw new Exception("Change datastore operation failed during storage migration");
 +                } else {
 +                    s_logger.debug("Successfully migrated VM " + vmName +
 +                            (hostInTargetCluster != null ? " from " + sourceHyperHost.getHyperHostName() + " to " + targetHyperHost.getHyperHostName() + " and " : " with ") +
 +                            "its storage to target datastore(s)");
 +                }
 +            }
 +
 +            // Consolidate VM disks.
 +            // In case of a linked clone VM, if VM's disks are not consolidated, further VM operations such as volume snapshot, VM snapshot etc. will result in DB inconsistencies.
 +            if (!vmMo.consolidateVmDisks()) {
 +                s_logger.warn("VM disk consolidation failed after storage migration. Yet proceeding with VM migration.");
 +            } else {
 +                s_logger.debug("Successfully consolidated disks of VM " + vmName + ".");
 +            }
 +
 +            if (MapUtils.isNotEmpty(volumeDeviceKey)) {
 +                // Update and return volume path and chain info for every disk because that could have changed after migration
 +                VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
 +                for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
 +                    final VolumeTO volume = entry.first();
 +                    final long volumeId = volume.getId();
 +                    VirtualDisk[] disks = vmMo.getAllDiskDevice();
 +                    for (VirtualDisk disk : disks) {
 +                        if (volumeDeviceKey.get(volumeId) == disk.getKey()) {
 +                            VolumeObjectTO newVol = new VolumeObjectTO();
 +                            newVol.setDataStoreUuid(entry.second().getUuid());
 +                            String newPath = vmMo.getVmdkFileBaseName(disk);
-                             String poolName = entry.second().getUuid().replace("-", "");
-                             VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(newPath, poolName);
++                            ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(targetHyperHost, entry.second().getUuid());
++                            DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs);
++                            VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(newPath, dsMo.getName());
 +                            newVol.setId(volumeId);
 +                            newVol.setPath(newPath);
 +                            newVol.setChainInfo(_gson.toJson(diskInfo));
 +                            volumeToList.add(newVol);
 +                            break;
 +                        }
 +                    }
 +                }
 +            }
 +        } catch (Throwable e) {
 +            if (e instanceof RemoteException) {
 +                s_logger.warn("Encountered remote exception at vCenter, invalidating VMware session context");
 +                invalidateServiceContext();
 +            }
 +            throw e;
 +        } finally {
 +            // Cleanup datastores mounted on source host
 +            for (String mountedDatastore : mountedDatastoresAtSource) {
 +                s_logger.debug("Attempting to unmount datastore " + mountedDatastore + " at " + sourceHyperHost.getHyperHostName());
 +                try {
 +                    sourceHyperHost.unmountDatastore(mountedDatastore);
 +                } catch (Exception unmountEx) {
 +                    s_logger.warn("Failed to unmount datastore " + mountedDatastore + " at " + sourceHyperHost.getHyperHostName() + ". Seems the datastore is still being used by " + sourceHyperHost.getHyperHostName() +
 +                            ". Please unmount manually to cleanup.");
 +                }
 +                s_logger.debug("Successfully unmounted datastore " + mountedDatastore + " at " + sourceHyperHost.getHyperHostName());
 +            }
 +        }
 +
 +        // Only when volToFiler is not empty a filled list of VolumeObjectTO is returned else it will be empty
 +        return volumeToList;
 +    }
 +
 +    private String getMountedDatastoreName(VmwareHypervisorHost sourceHyperHost, String sourceHostApiVersion, StorageFilerTO filerTo) throws Exception {
 +        String mountedDatastoreName = null;
 +        // If host version is below 5.1 then simultaneous change of VM's datastore and host is not supported.
 +        // So since only the datastore will be changed first, ensure the target datastore is mounted on source host.
 +        if (sourceHostApiVersion.compareTo("5.1") < 0) {
 +            s_logger.debug(String.format("Host: %s version is %s, vMotion without shared storage cannot be done. Check source host has target datastore mounted or can be mounted", sourceHyperHost.getHyperHostName(), sourceHostApiVersion));
 +            ManagedObjectReference morVolumeDatastoreAtSource = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(sourceHyperHost, filerTo.getUuid());
 +            String volumeDatastoreName = filerTo.getUuid().replace("-", "");
 +            String volumeDatastoreHost = filerTo.getHost();
 +            String volumeDatastorePath = filerTo.getPath();
 +            int volumeDatastorePort = filerTo.getPort();
 +
 +            // If datastore is NFS and target datastore is not already mounted on source host then mount the datastore.
 +            if (filerTo.getType().equals(StoragePoolType.NetworkFilesystem)) {
 +                if (morVolumeDatastoreAtSource == null) {
 +                    morVolumeDatastoreAtSource = sourceHyperHost.mountDatastore(false, volumeDatastoreHost, volumeDatastorePort, volumeDatastorePath, volumeDatastoreName, false);
 +                    if (morVolumeDatastoreAtSource == null) {
 +                        throw new Exception("Unable to mount NFS datastore " + volumeDatastoreHost + ":/" + volumeDatastorePath + " on host: " + sourceHyperHost.getHyperHostName());
 +                    }
 +                    mountedDatastoreName = volumeDatastoreName;
 +                    s_logger.debug("Mounted NFS datastore " + volumeDatastoreHost + ":/" + volumeDatastorePath + " on host: " + sourceHyperHost.getHyperHostName());
 +                }
 +            }
 +
 +            // If datastore is VMFS and target datastore is not mounted or accessible to source host then fail migration.
 +            if (filerTo.getType().equals(StoragePoolType.VMFS)) {
 +                if (morVolumeDatastoreAtSource == null) {
 +                    s_logger.warn("Host: " + sourceHyperHost.getHyperHostName() + " version is below 5.1, target VMFS datastore(s) need to be manually mounted on host for successful storage migration.");
 +                    throw new Exception("Target VMFS datastore: " + volumeDatastorePath + " is not mounted on host: " + sourceHyperHost.getHyperHostName());
 +                }
 +                DatastoreMO dsAtSourceMo = new DatastoreMO(getServiceContext(), morVolumeDatastoreAtSource);
 +                String srcHostValue = sourceHyperHost.getMor().getValue();
 +                if (!dsAtSourceMo.isAccessibleToHost(srcHostValue)) {
 +                    s_logger.warn("Host " + sourceHyperHost.getHyperHostName() + " version is below 5.1, target VMFS datastore(s) need to be accessible to host for a successful storage migration.");
 +                    throw new Exception("Target VMFS datastore: " + volumeDatastorePath + " is not accessible on host: " + sourceHyperHost.getHyperHostName());
 +                }
 +            }
 +        }
 +        return mountedDatastoreName;
 +    }
 +
      private Answer execute(ValidateVcenterDetailsCommand cmd) {
          if (s_logger.isInfoEnabled()) {
              s_logger.info("Executing resource ValidateVcenterDetailsCommand " + _gson.toJson(cmd));
diff --cc server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index bdad40f,ccb91f1..0bd0861
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@@ -223,10 -218,10 +225,12 @@@ public class VolumeApiServiceImpl exten
      @Inject
      private SnapshotDao _snapshotDao;
      @Inject
 +    private SnapshotDataStoreDao _snapshotDataStoreDao;
 +    @Inject
      private ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
      @Inject
+     private ServiceOfferingJoinDao serviceOfferingJoinDao;
+     @Inject
      private UserVmDao _userVmDao;
      @Inject
      private UserVmDetailsDao userVmDetailsDao;