@Override
  @Transactional(readOnly = true)
  public void preRecoverVm(VmInstanceInventory vm) {
    String rootVolUuid = vm.getRootVolumeUuid();

    String sql =
        "select ps.uuid from PrimaryStorageVO ps, VolumeVO vol where ps.uuid = vol.primaryStorageUuid"
            + " and vol.uuid = :uuid and ps.type = :pstype";
    TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("uuid", rootVolUuid);
    q.setParameter("pstype", LocalStorageConstants.LOCAL_STORAGE_TYPE);
    String psuuid = dbf.find(q);
    if (psuuid == null) {
      return;
    }

    sql =
        "select count(ref) from LocalStorageResourceRefVO ref where ref.resourceUuid = :uuid and ref.resourceType = :rtype";
    TypedQuery<Long> rq = dbf.getEntityManager().createQuery(sql, Long.class);
    rq.setParameter("uuid", rootVolUuid);
    rq.setParameter("rtype", VolumeVO.class.getSimpleName());
    long count = rq.getSingleResult();
    if (count == 0) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "unable to recover the vm[uuid:%s, name:%s]. The vm's root volume is on the local"
                      + " storage[uuid:%s]; however, the host on which the root volume is has been deleted",
                  vm.getUuid(), vm.getName(), psuuid)));
    }
  }
  @Transactional
  private void updateCapacity(long total, long avail) {
    PrimaryStorageCapacityVO cvo =
        dbf.getEntityManager()
            .find(PrimaryStorageCapacityVO.class, self.getUuid(), LockModeType.PESSIMISTIC_WRITE);
    DebugUtils.Assert(
        cvo != null,
        String.format("how can there is no PrimaryStorageCapacityVO[uuid:%s]", self.getUuid()));

    cvo.setTotalPhysicalCapacity(total);
    cvo.setAvailablePhysicalCapacity(avail);
    dbf.getEntityManager().merge(cvo);
  }
  @Override
  @Transactional
  public void delete(String uuid) {
    String sql = "delete from KeyValueVO vo where vo.uuid = :uuid";
    Query q = dbf.getEntityManager().createQuery(sql);
    q.setParameter("uuid", uuid);
    q.executeUpdate();

    sql = "delete from KeyValueBinaryVO vo where vo.uuid = :uuid";
    q = dbf.getEntityManager().createQuery(sql);
    q.setParameter("uuid", uuid);
    q.executeUpdate();
  }
 @Transactional
 private void handle(TakePrimaryStorageCapacityMsg msg) {
   PrimaryStorageCapacityVO vo =
       dbf.getEntityManager()
           .find(PrimaryStorageCapacityVO.class, self.getUuid(), LockModeType.PESSIMISTIC_WRITE);
   vo.setAvailableCapacity(vo.getAvailableCapacity() - msg.getSize());
   if (vo.getAvailableCapacity() < 0) {
     vo.setAvailableCapacity(0);
   }
   dbf.getEntityManager().merge(vo);
   TakePrimaryStorageCapacityReply reply = new TakePrimaryStorageCapacityReply();
   bus.reply(msg, reply);
 }
  @Transactional
  public void updatePhysicalCapacityByKvmAgentResponse(
      String psUuid, String hostUuid, AgentResponse rsp) {
    LocalStorageHostRefVO ref =
        dbf.getEntityManager()
            .find(LocalStorageHostRefVO.class, hostUuid, LockModeType.PESSIMISTIC_WRITE);
    if (ref == null) {
      return;
    }

    if (ref.getAvailablePhysicalCapacity() == rsp.getAvailableCapacity()
        && ref.getTotalPhysicalCapacity() == rsp.getTotalCapacity()) {
      return;
    }

    long originalPhysicalTotal = ref.getTotalPhysicalCapacity();
    long originalPhysicalAvailable = ref.getAvailablePhysicalCapacity();

    ref.setTotalPhysicalCapacity(rsp.getTotalCapacity());
    ref.setAvailablePhysicalCapacity(rsp.getAvailableCapacity());
    dbf.getEntityManager().merge(ref);

    if (logger.isTraceEnabled()) {
      logger.trace(
          String.format(
              "[Local Storage Capacity] changed the physical capacity of the host[uuid:%s] of "
                  + "the local primary storage[uuid:%s] as:\n"
                  + "physical total: %s --> %s\n"
                  + "physical available: %s --> %s\n",
              hostUuid,
              psUuid,
              originalPhysicalTotal,
              ref.getTotalPhysicalCapacity(),
              originalPhysicalAvailable,
              ref.getAvailablePhysicalCapacity()));
    }

    final long totalChange = rsp.getTotalCapacity() - ref.getTotalPhysicalCapacity();
    final long availChange = rsp.getAvailableCapacity() - ref.getAvailablePhysicalCapacity();

    new PrimaryStorageCapacityUpdater(psUuid)
        .run(
            new PrimaryStorageCapacityUpdaterRunnable() {
              @Override
              public PrimaryStorageCapacityVO call(PrimaryStorageCapacityVO cap) {
                cap.setTotalPhysicalCapacity(cap.getTotalPhysicalCapacity() + totalChange);
                cap.setAvailablePhysicalCapacity(cap.getAvailablePhysicalCapacity() + availChange);
                return cap;
              }
            });
  }
  @Transactional
  private void handle(PrimaryStorageReportCapacityMsg msg) {
    PrimaryStorageCapacityVO vo =
        dbf.getEntityManager()
            .find(PrimaryStorageCapacityVO.class, self.getUuid(), LockModeType.PESSIMISTIC_WRITE);
    if (vo.getTotalCapacity() == 0) {
      vo.setTotalCapacity(msg.getTotalCapacity());
      vo.setAvailableCapacity(msg.getAvailableCapacity());
      dbf.getEntityManager().merge(vo);
    }

    PrimaryStorageReportCapacityReply reply = new PrimaryStorageReportCapacityReply();
    bus.reply(msg, reply);
  }
Beispiel #7
0
  @Transactional
  private void handle(ReturnBackupStorageMsg msg) {
    self =
        dbf.getEntityManager()
            .find(BackupStorageVO.class, self.getUuid(), LockModeType.PESSIMISTIC_WRITE);
    long availSize = self.getAvailableCapacity() + msg.getSize();
    if (availSize > self.getTotalCapacity()) {
      availSize = self.getTotalCapacity();
    }

    self.setAvailableCapacity(availSize);
    dbf.getEntityManager().merge(self);
    bus.reply(msg, new ReturnBackupStorageReply());
  }
  @Override
  @Transactional(readOnly = true)
  public List<VmInstanceVO> returnAttachableVms(
      VolumeInventory vol, List<VmInstanceVO> candidates) {
    String sql =
        "select ref.hostUuid from LocalStorageResourceRefVO ref where ref.resourceUuid = :uuid"
            + " and ref.resourceType = :rtype";
    TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("uuid", vol.getUuid());
    q.setParameter("rtype", VolumeVO.class.getSimpleName());
    List<String> ret = q.getResultList();
    if (ret.isEmpty()) {
      return candidates;
    }

    String hostUuid = ret.get(0);

    List<String> vmRootVolumeUuids =
        CollectionUtils.transformToList(
            candidates,
            new Function<String, VmInstanceVO>() {
              @Override
              public String call(VmInstanceVO arg) {
                return arg.getRootVolumeUuid();
              }
            });

    sql =
        "select ref.resourceUuid from LocalStorageResourceRefVO ref where ref.hostUuid = :huuid"
            + " and ref.resourceUuid in (:rootVolumeUuids) and ref.resourceType = :rtype";
    q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("huuid", hostUuid);
    q.setParameter("rootVolumeUuids", vmRootVolumeUuids);
    q.setParameter("rtype", VolumeVO.class.getSimpleName());
    final List<String> toInclude = q.getResultList();

    candidates =
        CollectionUtils.transformToList(
            candidates,
            new Function<VmInstanceVO, VmInstanceVO>() {
              @Override
              public VmInstanceVO call(VmInstanceVO arg) {
                return toInclude.contains(arg.getRootVolumeUuid()) ? arg : null;
              }
            });

    return candidates;
  }
Beispiel #9
0
 @Transactional
 private void batchWrite(List lst) {
   for (Object obj : lst) {
     LogVO vo = (LogVO) obj;
     dbf.getEntityManager().persist(vo);
   }
 }
  @Override
  @Transactional(
      readOnly = true,
      noRollbackForClassName = {"org.zstack.header.errorcode.OperationFailureException"})
  public void preVmMigration(VmInstanceInventory vm) {
    List<String> volUuids =
        CollectionUtils.transformToList(
            vm.getAllVolumes(),
            new Function<String, VolumeInventory>() {
              @Override
              public String call(VolumeInventory arg) {
                return arg.getUuid();
              }
            });

    String sql =
        "select count(ps) from PrimaryStorageVO ps, VolumeVO vol where ps.uuid = vol.primaryStorageUuid and"
            + " vol.uuid in (:volUuids) and ps.type = :ptype";
    TypedQuery<Long> q = dbf.getEntityManager().createQuery(sql, Long.class);
    q.setParameter("volUuids", volUuids);
    q.setParameter("ptype", LocalStorageConstants.LOCAL_STORAGE_TYPE);
    q.setMaxResults(1);
    Long count = q.getSingleResult();
    if (count > 0) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "unable to live migrate with local storage. The vm[uuid:%s] has volumes on local storage,"
                      + "to protect your data, please stop the vm and do the volume migration",
                  vm.getUuid())));
    }
  }
 @Transactional(readOnly = true)
 private boolean isThereOtherStorageForTheHost(String hostUuid, String localStorageUuid) {
   String sql =
       "select count(pri) from PrimaryStorageVO pri, PrimaryStorageClusterRefVO ref, HostVO host where pri.uuid = ref.primaryStorageUuid and ref.clusterUuid = host.clusterUuid and host.uuid = :huuid and pri.uuid != :puuid";
   TypedQuery<Long> q = dbf.getEntityManager().createQuery(sql, Long.class);
   q.setParameter("huuid", hostUuid);
   q.setParameter("puuid", localStorageUuid);
   return q.getSingleResult() > 0;
 }
  @Transactional(readOnly = true)
  private Collection<PortForwardingRuleTO> calculateAllRules(
      Map<String, PortForwardingRuleVO> ruleMap, String vrUuid) {
    String sql =
        "select rule.uuid, nic.ip, vip.ip from PortForwardingRuleVO rule, VmNicVO nic, VipVO vip where rule.vmNicUuid = nic.uuid and rule.uuid in (:ruleUuids) and vip.uuid = rule.vipUuid";
    TypedQuery<Tuple> q = dbf.getEntityManager().createQuery(sql, Tuple.class);
    q.setParameter("ruleUuids", ruleMap.keySet());
    List<Tuple> privateIps = q.getResultList();

    Map<String, PortForwardingRuleTO> tos = new HashMap<String, PortForwardingRuleTO>();
    for (Tuple t : privateIps) {
      String ruleUuid = t.get(0, String.class);
      PortForwardingRuleTO to = new PortForwardingRuleTO();
      to.setPrivateIp(t.get(1, String.class));

      PortForwardingRuleVO ruleVO = ruleMap.get(ruleUuid);
      to.setAllowedCidr(ruleVO.getAllowedCidr());
      to.setPrivatePortEnd(ruleVO.getPrivatePortEnd());
      to.setPrivatePortStart(ruleVO.getPrivatePortStart());
      to.setVipPortEnd(ruleVO.getVipPortEnd());
      to.setSnatInboundTraffic(
          PortForwardingGlobalConfig.SNAT_INBOUND_TRAFFIC.value(Boolean.class));
      to.setVipPortStart(ruleVO.getVipPortStart());
      to.setVipIp(t.get(2, String.class));
      to.setProtocolType(ruleVO.getProtocolType().toString());
      tos.put(ruleUuid, to);
    }

    assert tos.size() == ruleMap.size();

    sql =
        "select rule.uuid, vrnic.mac from PortForwardingRuleVO rule, VmNicVO vrnic, VmNicVO nic2, ApplianceVmVO vr where vr.uuid = vrnic.vmInstanceUuid and vrnic.l3NetworkUuid = nic2.l3NetworkUuid and nic2.uuid = rule.vmNicUuid and rule.uuid in (:ruleUuids) and vr.uuid = :vrUuid";
    TypedQuery<Tuple> privateMacQuery = dbf.getEntityManager().createQuery(sql, Tuple.class);
    privateMacQuery.setParameter("ruleUuids", ruleMap.keySet());
    privateMacQuery.setParameter("vrUuid", vrUuid);
    List<Tuple> privateMacs = privateMacQuery.getResultList();
    for (Tuple t : privateMacs) {
      String ruleUuid = t.get(0, String.class);
      PortForwardingRuleTO to = tos.get(ruleUuid);
      to.setPrivateMac(t.get(1, String.class));
    }

    return tos.values();
  }
Beispiel #13
0
 @Override
 @Transactional
 public <T> T find(String uuid) {
   KeyValueBinaryVO bvo = dbf.getEntityManager().find(KeyValueBinaryVO.class, uuid);
   try {
     return SerializableHelper.readObject(bvo.getContents());
   } catch (Exception e) {
     throw new CloudRuntimeException(e);
   }
 }
  @Transactional
  private List<PortForwardingRuleVO> findRulesForThisRouter(
      VirtualRouterVmInventory vr, Map<String, Object> data, boolean isNewCreated) {
    if (!isNewCreated) {
      String sql =
          "select rule from PortForwardingRuleVO rule, VirtualRouterPortForwardingRuleRefVO ref, VmNicVO nic, VmInstanceVO vm where vm.state = :vmState and nic.vmInstanceUuid = vm.uuid and rule.vmNicUuid = nic.uuid and rule.uuid = ref.uuid and ref.virtualRouterVmUuid = :vrUuid";
      TypedQuery<PortForwardingRuleVO> q =
          dbf.getEntityManager().createQuery(sql, PortForwardingRuleVO.class);
      q.setParameter("vrUuid", vr.getUuid());
      q.setParameter("vmState", VmInstanceState.Running);
      return q.getResultList();
    } else {
      VmNicInventory publicNic = vr.getPublicNic();
      VmNicInventory guestNic = vr.getGuestNic();
      String sql =
          "select rule from PortForwardingRuleVO rule, VipVO vip, VmNicVO nic, VmInstanceVO vm where vm.uuid = nic.vmInstanceUuid and vm.state = :vmState and rule.vipUuid = vip.uuid and rule.vmNicUuid = nic.uuid and vip.l3NetworkUuid = :vipL3Uuid and nic.l3NetworkUuid = :guestL3Uuid";
      TypedQuery<PortForwardingRuleVO> q =
          dbf.getEntityManager().createQuery(sql, PortForwardingRuleVO.class);
      q.setParameter("vipL3Uuid", publicNic.getL3NetworkUuid());
      q.setParameter("guestL3Uuid", guestNic.getL3NetworkUuid());
      q.setParameter("vmState", VmInstanceState.Running);

      List<PortForwardingRuleVO> rules = q.getResultList();

      if (!rules.isEmpty()) {
        List<VirtualRouterPortForwardingRuleRefVO> refs =
            new ArrayList<VirtualRouterPortForwardingRuleRefVO>();
        for (PortForwardingRuleVO rule : rules) {
          VirtualRouterPortForwardingRuleRefVO ref = new VirtualRouterPortForwardingRuleRefVO();
          ref.setVirtualRouterVmUuid(vr.getUuid());
          ref.setVipUuid(rule.getVipUuid());
          ref.setUuid(rule.getUuid());
          dbf.getEntityManager().persist(ref);
          refs.add(ref);
        }

        data.put(VirtualRouterSyncPortForwardingRulesOnStartFlow.class.getName(), refs);
      }

      return rules;
    }
  }
 @Override
 @Transactional(readOnly = true)
 public HostMaintenancePolicy getHostMaintenancePolicy(HostInventory host) {
   String sql =
       "select count(ps) from PrimaryStorageVO ps, PrimaryStorageClusterRefVO ref where ps.uuid = ref.primaryStorageUuid"
           + " and ps.type = :type and ref.clusterUuid = :cuuid";
   TypedQuery<Long> q = dbf.getEntityManager().createQuery(sql, Long.class);
   q.setParameter("type", LocalStorageConstants.LOCAL_STORAGE_TYPE);
   q.setParameter("cuuid", host.getClusterUuid());
   q.setMaxResults(1);
   Long count = q.getSingleResult();
   return count > 0 ? HostMaintenancePolicy.StopVm : null;
 }
Beispiel #16
0
  @Override
  @Transactional
  public void persist(KeyValueEntity entity) {
    KeyValueBinaryVO bvo = new KeyValueBinaryVO();
    bvo.setUuid(entity.getUuid());
    try {
      bvo.setContents(SerializableHelper.writeObject(entity));
    } catch (IOException e) {
      throw new CloudRuntimeException(e);
    }
    dbf.getEntityManager().persist(bvo);

    List<KeyValueStruct> structs = new KeyValueSerializer().build(entity);
    for (KeyValueStruct struct : structs) {
      KeyValueVO vo = new KeyValueVO();
      vo.setClassName(entity.getClass().getName());
      vo.setUuid(entity.getUuid());
      vo.setEntityKey(struct.getKey());
      vo.setEntityValue(struct.getValue());
      vo.setValueType(struct.getType().getName());
      dbf.getEntityManager().persist(vo);
    }
  }
  @Transactional(readOnly = true)
  private String getLocalStorageInCluster(String clusterUuid) {
    String sql =
        "select pri.uuid from PrimaryStorageVO pri, PrimaryStorageClusterRefVO ref where pri.uuid = ref.primaryStorageUuid and ref.clusterUuid = :cuuid and pri.type = :ptype";
    TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("cuuid", clusterUuid);
    q.setParameter("ptype", LocalStorageConstants.LOCAL_STORAGE_TYPE);
    List<String> ret = q.getResultList();
    if (ret.isEmpty()) {
      return null;
    }

    return ret.get(0);
  }
 @Transactional(readOnly = true)
 private void checkIfBackupStorageAttachedToMyZone(String bsUuid) {
   String sql =
       "select bs.uuid from BackupStorageVO bs, BackupStorageZoneRefVO ref where bs.uuid = ref.backupStorageUuid and ref.zoneUuid = :zoneUuid and bs.uuid = :bsUuid";
   TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
   q.setParameter("zoneUuid", self.getZoneUuid());
   q.setParameter("bsUuid", bsUuid);
   if (q.getResultList().isEmpty()) {
     throw new OperationFailureException(
         errf.stringToOperationError(
             String.format(
                 "backup storage[uuid:%s] is not attached to zone[uuid:%s] the primary storage[uuid:%s] belongs to",
                 bsUuid, self.getZoneUuid(), self.getUuid())));
   }
 }
Beispiel #19
0
  @Transactional(readOnly = true)
  private List<String> getVmUuidFromL2NetworkDetached(List<L2NetworkDetachStruct> structs) {
    List<String> vmUuids = new ArrayList<String>();
    for (L2NetworkDetachStruct s : structs) {
      String sql =
          "select vm.uuid from VmInstanceVO vm, L2NetworkVO l2, L3NetworkVO l3, VmNicVO nic where vm.type = :vmType and vm.clusterUuid = :clusterUuid and vm.state not in (:vmStates) and vm.uuid = nic.vmInstanceUuid and nic.l3NetworkUuid = l3.uuid and l3.l2NetworkUuid = l2.uuid and l2.uuid = :l2Uuid";
      TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
      q.setParameter("vmType", VmInstanceConstant.USER_VM_TYPE);
      q.setParameter(
          "vmStates",
          Arrays.asList(
              VmInstanceState.Stopped, VmInstanceState.Migrating, VmInstanceState.Stopping));
      q.setParameter("clusterUuid", s.getClusterUuid());
      q.setParameter("l2Uuid", s.getL2NetworkUuid());
      vmUuids.addAll(q.getResultList());
    }

    return vmUuids;
  }
Beispiel #20
0
  @Transactional(readOnly = true)
  private List<String> getVmUuidForPrimaryStorageDetached(
      List<PrimaryStorageDetachStruct> structs) {
    List<String> vmUuids = new ArrayList<String>();
    for (PrimaryStorageDetachStruct s : structs) {
      String sql =
          "select vm.uuid from VmInstanceVO vm, PrimaryStorageVO ps, VolumeVO vol where vm.type = :vmType and vm.state not in (:vmStates) and vm.clusterUuid = :clusterUuid and vm.uuid = vol.vmInstanceUuid and vol.primaryStorageUuid = :psUuid";
      TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
      q.setParameter("vmType", VmInstanceConstant.USER_VM_TYPE);
      q.setParameter(
          "vmStates",
          Arrays.asList(
              VmInstanceState.Stopped, VmInstanceState.Migrating, VmInstanceState.Stopping));
      q.setParameter("clusterUuid", s.getClusterUuid());
      q.setParameter("psUuid", s.getPrimaryStorageUuid());
      vmUuids.addAll(q.getResultList());
    }

    return vmUuids;
  }
Beispiel #21
0
  @Transactional(readOnly = true)
  private List<VmInstanceVO> getCandidateVmForAttaching(String accountUuid) {
    List<String> vmUuids =
        acntMgr.getResourceUuidsCanAccessByAccount(accountUuid, VmInstanceVO.class);

    if (vmUuids != null && vmUuids.isEmpty()) {
      return new ArrayList<VmInstanceVO>();
    }

    TypedQuery<VmInstanceVO> q = null;
    String sql;
    if (vmUuids == null) {
      // all vms
      if (self.getStatus() == VolumeStatus.Ready) {
        sql =
            "select vm from VmInstanceVO vm, PrimaryStorageClusterRefVO ref, VolumeVO vol where vm.state in (:vmStates) and vol.uuid = :volUuid and vm.hypervisorType in (:hvTypes) and vm.clusterUuid = ref.clusterUuid and ref.primaryStorageUuid = vol.primaryStorageUuid group by vm.uuid";
        q = dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
        q.setParameter("volUuid", self.getUuid());
        List<String> hvTypes =
            VolumeFormat.valueOf(self.getFormat())
                .getHypervisorTypesSupportingThisVolumeFormatInString();
        q.setParameter("hvTypes", hvTypes);
      } else if (self.getStatus() == VolumeStatus.NotInstantiated) {
        sql = "select vm from VmInstanceVO vm where vm.state in (:vmStates) group by vm.uuid";
        q = dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
      } else {
        DebugUtils.Assert(
            false, String.format("should not reach here, volume[uuid:%s]", self.getUuid()));
      }
    } else {
      if (self.getStatus() == VolumeStatus.Ready) {
        sql =
            "select vm from VmInstanceVO vm, PrimaryStorageClusterRefVO ref, VolumeVO vol where vm.uuid in (:vmUuids) and vm.state in (:vmStates) and vol.uuid = :volUuid and vm.hypervisorType in (:hvTypes) and vm.clusterUuid = ref.clusterUuid and ref.primaryStorageUuid = vol.primaryStorageUuid group by vm.uuid";
        q = dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
        q.setParameter("volUuid", self.getUuid());
        List<String> hvTypes =
            VolumeFormat.valueOf(self.getFormat())
                .getHypervisorTypesSupportingThisVolumeFormatInString();
        q.setParameter("hvTypes", hvTypes);
      } else if (self.getStatus() == VolumeStatus.NotInstantiated) {
        sql =
            "select vm from VmInstanceVO vm where vm.uuid in (:vmUuids) and vm.state in (:vmStates) group by vm.uuid";
        q = dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
      } else {
        DebugUtils.Assert(
            false, String.format("should not reach here, volume[uuid:%s]", self.getUuid()));
      }

      q.setParameter("vmUuids", vmUuids);
    }

    q.setParameter("vmStates", Arrays.asList(VmInstanceState.Running, VmInstanceState.Stopped));
    List<VmInstanceVO> vms = q.getResultList();
    if (vms.isEmpty()) {
      return vms;
    }

    VolumeInventory vol = getSelfInventory();
    for (VolumeGetAttachableVmExtensionPoint ext :
        pluginRgty.getExtensionList(VolumeGetAttachableVmExtensionPoint.class)) {
      vms = ext.returnAttachableVms(vol, vms);
    }

    return vms;
  }
  @Override
  @Transactional(readOnly = true)
  public List<VolumeVO> returnAttachableVolumes(VmInstanceInventory vm, List<VolumeVO> candidates) {
    // find instantiated volumes
    List<String> volUuids =
        CollectionUtils.transformToList(
            candidates,
            new Function<String, VolumeVO>() {
              @Override
              public String call(VolumeVO arg) {
                return VolumeStatus.Ready == arg.getStatus() ? arg.getUuid() : null;
              }
            });

    if (volUuids.isEmpty()) {
      return candidates;
    }

    List<VolumeVO> uninstantiatedVolumes =
        CollectionUtils.transformToList(
            candidates,
            new Function<VolumeVO, VolumeVO>() {
              @Override
              public VolumeVO call(VolumeVO arg) {
                return arg.getStatus() == VolumeStatus.NotInstantiated ? arg : null;
              }
            });

    String sql =
        "select ref.hostUuid from LocalStorageResourceRefVO ref where ref.resourceUuid = :volUuid and ref.resourceType = :rtype";
    TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("volUuid", vm.getRootVolumeUuid());
    q.setParameter("rtype", VolumeVO.class.getSimpleName());
    List<String> ret = q.getResultList();
    if (ret.isEmpty()) {
      return candidates;
    }

    String hostUuid = ret.get(0);
    sql =
        "select ref.resourceUuid from LocalStorageResourceRefVO ref where ref.resourceUuid in (:uuids) and ref.resourceType = :rtype"
            + " and ref.hostUuid != :huuid";
    q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("uuids", volUuids);
    q.setParameter("huuid", hostUuid);
    q.setParameter("rtype", VolumeVO.class.getSimpleName());
    final List<String> toExclude = q.getResultList();

    candidates =
        CollectionUtils.transformToList(
            candidates,
            new Function<VolumeVO, VolumeVO>() {
              @Override
              public VolumeVO call(VolumeVO arg) {
                return toExclude.contains(arg.getUuid()) ? null : arg;
              }
            });

    candidates.addAll(uninstantiatedVolumes);

    return candidates;
  }