@Override
  public void preRecoverDataVolume(VolumeInventory vol) {
    if (vol.getPrimaryStorageUuid() == null) {
      return;
    }

    SimpleQuery<PrimaryStorageVO> q = dbf.createQuery(PrimaryStorageVO.class);
    q.select(PrimaryStorageVO_.type);
    q.add(PrimaryStorageVO_.uuid, Op.EQ, vol.getPrimaryStorageUuid());
    String type = q.findValue();
    if (!LocalStorageConstants.LOCAL_STORAGE_TYPE.equals(type)) {
      return;
    }

    SimpleQuery<LocalStorageResourceRefVO> rq = dbf.createQuery(LocalStorageResourceRefVO.class);
    rq.add(LocalStorageResourceRefVO_.resourceUuid, Op.EQ, vol.getUuid());
    rq.add(LocalStorageResourceRefVO_.resourceType, Op.EQ, VolumeVO.class.getSimpleName());
    if (!rq.isExists()) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "the data volume[name:%s, uuid:%s] is on the local storage[uuid:%s]; however,"
                      + "the host on which the data volume is has been deleted. Unable to recover this volume",
                  vol.getName(), vol.getUuid(), vol.getPrimaryStorageUuid())));
    }
  }
  @Override
  public void run(FlowTrigger trigger, Map data) {
    PrimaryStorageAllocationSpec spec =
        (PrimaryStorageAllocationSpec) data.get(AllocatorParams.SPEC);
    List<PrimaryStorageVO> candidates =
        (List<PrimaryStorageVO>) data.get(AllocatorParams.CANDIDATES);
    DebugUtils.Assert(
        candidates != null && !candidates.isEmpty(),
        "PrimaryStorageTagAllocatorFlow cannot be the first element in allocator chain");

    List<SystemTagVO> tvos = null;
    if (spec.getVmInstanceUuid() != null) {
      SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
      q.add(SystemTagVO_.resourceType, Op.EQ, VmInstanceVO.class.getSimpleName());
      q.add(SystemTagVO_.resourceUuid, Op.EQ, spec.getVmInstanceUuid());
      tvos = q.list();
    } else if (spec.getDiskOfferingUuid() != null) {
      SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
      q.add(SystemTagVO_.resourceType, Op.EQ, DiskOfferingVO.class.getSimpleName());
      q.add(SystemTagVO_.resourceUuid, Op.EQ, spec.getDiskOfferingUuid());
      tvos = q.list();
    }

    if (tvos != null && !tvos.isEmpty()) {
      candidates = callTagExtensions(SystemTagInventory.valueOf(tvos), candidates);
      data.put(AllocatorParams.CANDIDATES, candidates);
    }

    trigger.next();
  }
  @Override
  public NetworkServiceProviderType getTypeOfNetworkServiceProviderForService(
      String l3NetworkUuid, NetworkServiceType serviceType) {
    L3NetworkVO l3vo = dbf.findByUuid(l3NetworkUuid, L3NetworkVO.class);
    L3NetworkInventory l3inv = L3NetworkInventory.valueOf(l3vo);
    NetworkServiceL3NetworkRefInventory targetRef = null;
    for (NetworkServiceL3NetworkRefInventory ref : l3inv.getNetworkServices()) {
      if (ref.getNetworkServiceType().equals(serviceType.toString())) {
        targetRef = ref;
        break;
      }
    }

    if (targetRef == null) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "L3Network[uuid:%s] doesn't have network service[type:%s] enabled or no provider provides this network service",
                  l3NetworkUuid, serviceType)));
    }

    SimpleQuery<NetworkServiceProviderVO> q = dbf.createQuery(NetworkServiceProviderVO.class);
    q.select(NetworkServiceProviderVO_.type);
    q.add(NetworkServiceProviderVO_.uuid, Op.EQ, targetRef.getNetworkServiceProviderUuid());
    String providerType = q.findValue();
    return NetworkServiceProviderType.valueOf(providerType);
  }
Exemple #4
0
 public boolean hasTag(String resourceUuid, Class resourceClass) {
   SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
   q.add(SystemTagVO_.resourceType, Op.EQ, resourceClass.getSimpleName());
   q.add(SystemTagVO_.resourceUuid, Op.EQ, resourceUuid);
   q.add(SystemTagVO_.tag, useOp(), useTagFormat());
   return q.isExists();
 }
Exemple #5
0
 public List<String> getTags(String resourceUuid, Class resourceClass) {
   SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
   q.select(SystemTagVO_.tag);
   q.add(SystemTagVO_.resourceType, Op.EQ, resourceClass.getSimpleName());
   q.add(SystemTagVO_.resourceUuid, Op.EQ, resourceUuid);
   q.add(SystemTagVO_.tag, useOp(), useTagFormat());
   return q.listValue();
 }
Exemple #6
0
 public AccountInventory useAccount(String name) throws ApiSenderException {
   SimpleQuery<AccountVO> q = dbf.createQuery(AccountVO.class);
   q.add(AccountVO_.name, Op.EQ, name);
   AccountVO vo = q.find();
   DebugUtils.Assert(vo != null, String.format("cannot find account[name:%s]", name));
   account = AccountInventory.valueOf(vo);
   accountSession = api.loginByAccount(name, vo.getPassword());
   return account;
 }
  private void handle(APIDetachNetworkServiceProviderFromL2NetworkMsg msg) {
    NetworkServiceProviderVO vo =
        dbf.findByUuid(msg.getNetworkServiceProviderUuid(), NetworkServiceProviderVO.class);
    NetworkServiceProviderFactory factory = getProviderFactory(vo.getType());
    NetworkServiceProvider provider = factory.getNetworkServiceProvider(vo);
    L2NetworkVO l2vo = dbf.findByUuid(msg.getL2NetworkUuid(), L2NetworkVO.class);

    APIDetachNetworkServiceProviderFromL2NetworkEvent evt =
        new APIDetachNetworkServiceProviderFromL2NetworkEvent(msg.getId());
    try {
      provider.detachFromL2Network(L2NetworkInventory.valueOf(l2vo), msg);
    } catch (NetworkException e) {
      String err =
          String.format(
              "unable to detach network service provider[uuid:%s, name:%s, type:%s] to l2network[uuid:%s, name:%s, type:%s], %s",
              vo.getUuid(),
              vo.getName(),
              vo.getType(),
              l2vo.getUuid(),
              l2vo.getName(),
              l2vo.getType(),
              e.getMessage());
      logger.warn(err, e);
      evt.setErrorCode(
          errf.instantiateErrorCode(
              NetworkServiceErrors.DETACH_NETWORK_SERVICE_PROVIDER_ERROR, err));
      bus.publish(evt);
      return;
    }

    SimpleQuery<NetworkServiceProviderL2NetworkRefVO> query =
        dbf.createQuery(NetworkServiceProviderL2NetworkRefVO.class);
    query.select(NetworkServiceProviderL2NetworkRefVO_.id);
    query.add(NetworkServiceProviderL2NetworkRefVO_.l2NetworkUuid, Op.EQ, l2vo.getUuid());
    query.add(
        NetworkServiceProviderL2NetworkRefVO_.networkServiceProviderUuid, Op.EQ, vo.getUuid());
    Long id = query.findValue();
    if (id != null) {
      dbf.removeByPrimaryKey(id, NetworkServiceProviderL2NetworkRefVO.class);
    }

    vo = dbf.findByUuid(vo.getUuid(), NetworkServiceProviderVO.class);
    evt.setInventory(NetworkServiceProviderInventory.valueOf(vo));
    String info =
        String.format(
            "successfully detach network service provider[uuid:%s, name:%s, type:%s] to l2network[uuid:%s, name:%s, type:%s]",
            vo.getUuid(),
            vo.getName(),
            vo.getType(),
            l2vo.getUuid(),
            l2vo.getName(),
            l2vo.getType());
    logger.debug(info);
    bus.publish(evt);
  }
 @Override
 public void run(FlowTrigger trigger, Map data) {
   final String vrUuid = (String) data.get(Param.VR_UUID.toString());
   SimpleQuery<VirtualRouterVipVO> q = dbf.createQuery(VirtualRouterVipVO.class);
   q.add(VirtualRouterVipVO_.virtualRouterVmUuid, Op.EQ, vrUuid);
   List<VirtualRouterVipVO> refs = q.list();
   if (!refs.isEmpty()) {
     dbf.removeCollection(refs, VirtualRouterVipVO.class);
   }
   trigger.next();
 }
 @Override
 public void afterHostConnected(HostInventory host) {
   SimpleQuery<LocalStorageHostRefVO> q = dbf.createQuery(LocalStorageHostRefVO.class);
   q.add(LocalStorageHostRefVO_.hostUuid, Op.EQ, host.getUuid());
   LocalStorageHostRefVO ref = q.find();
   if (ref != null) {
     RecalculatePrimaryStorageCapacityMsg msg = new RecalculatePrimaryStorageCapacityMsg();
     msg.setPrimaryStorageUuid(ref.getPrimaryStorageUuid());
     bus.makeTargetServiceIdByResourceUuid(
         msg, PrimaryStorageConstant.SERVICE_ID, ref.getPrimaryStorageUuid());
     bus.send(msg);
   }
 }
  @Override
  public void preAttachVolume(VmInstanceInventory vm, final VolumeInventory volume) {
    SimpleQuery<LocalStorageResourceRefVO> q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.add(
        LocalStorageResourceRefVO_.resourceUuid,
        Op.IN,
        list(vm.getRootVolumeUuid(), volume.getUuid()));
    q.groupBy(LocalStorageResourceRefVO_.hostUuid);
    long count = q.count();

    if (count < 2) {
      return;
    }

    q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.select(LocalStorageResourceRefVO_.hostUuid);
    q.add(LocalStorageResourceRefVO_.resourceUuid, Op.EQ, vm.getRootVolumeUuid());
    String rootHost = q.findValue();

    q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.select(LocalStorageResourceRefVO_.hostUuid);
    q.add(LocalStorageResourceRefVO_.resourceUuid, Op.EQ, volume.getUuid());
    String dataHost = q.findValue();

    if (!rootHost.equals(dataHost)) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "cannot attach the data volume[uuid:%s] to the vm[uuid:%s]. Both vm's root volume and the data volume are"
                      + " on local primary storage, but they are on different hosts. The root volume[uuid:%s] is on the host[uuid:%s] but the data volume[uuid: %s]"
                      + " is on the host[uuid: %s]",
                  volume.getUuid(),
                  vm.getUuid(),
                  vm.getRootVolumeUuid(),
                  rootHost,
                  volume.getUuid(),
                  dataHost)));
    }
  }
  @Override
  public void run(final FlowTrigger trigger, final Map data) {
    final VmInstanceSpec spec =
        (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());
    VolumeInventory volume = spec.getDestDataVolumes().get(0);

    SimpleQuery<LocalStorageResourceRefVO> q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.select(LocalStorageResourceRefVO_.hostUuid, LocalStorageResourceRefVO_.primaryStorageUuid);
    q.add(
        LocalStorageResourceRefVO_.resourceUuid, Op.EQ, spec.getVmInventory().getRootVolumeUuid());
    Tuple t = q.findTuple();
    final String hostUuid = t.get(0, String.class);
    String priUuid = t.get(1, String.class);

    AllocatePrimaryStorageMsg msg = new AllocatePrimaryStorageMsg();
    if (isThereOtherStorageForTheHost(hostUuid, priUuid)) {
      // use network-shared primary storage
      msg.addExcludeAllocatorStrategy(LocalStorageConstants.LOCAL_STORAGE_ALLOCATOR_STRATEGY);
      msg.addExcludePrimaryStoratgeUuid(priUuid);
    } else {
      msg.setAllocationStrategy(LocalStorageConstants.LOCAL_STORAGE_ALLOCATOR_STRATEGY);
      msg.setRequiredPrimaryStorageUuid(
          spec.getVmInventory().getRootVolume().getPrimaryStorageUuid());
    }

    msg.setRequiredHostUuid(hostUuid);
    msg.setVmInstanceUuid(spec.getVmInventory().getUuid());
    msg.setSize(volume.getSize());
    msg.setPurpose(PrimaryStorageAllocationPurpose.CreateVolume.toString());
    bus.makeLocalServiceId(msg, PrimaryStorageConstant.SERVICE_ID);
    bus.send(
        msg,
        new CloudBusCallBack(trigger) {
          @Override
          public void run(MessageReply reply) {
            if (!reply.isSuccess()) {
              trigger.fail(reply.getError());
              return;
            }

            spec.setDestHost(HostInventory.valueOf(dbf.findByUuid(hostUuid, HostVO.class)));

            AllocatePrimaryStorageReply ar = (AllocatePrimaryStorageReply) reply;
            data.put(
                VmInstanceConstant.Params.DestPrimaryStorageInventoryForAttachingVolume.toString(),
                ar.getPrimaryStorageInventory());
            data.put(LocalStorageAllocateCapacityForAttachingVolumeFlow.class, ar.getSize());
            trigger.next();
          }
        });
  }
Exemple #12
0
 public Map<String, List<String>> getTags(List<String> resourceUuids, Class resourceClass) {
   SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
   q.select(SystemTagVO_.tag, SystemTagVO_.resourceUuid);
   q.add(SystemTagVO_.resourceType, Op.EQ, resourceClass.getSimpleName());
   q.add(SystemTagVO_.resourceUuid, Op.IN, resourceUuids);
   q.add(SystemTagVO_.tag, useOp(), useTagFormat());
   List<Tuple> ts = q.listTuple();
   Map<String, List<String>> ret = new HashMap<String, List<String>>();
   for (Tuple t : ts) {
     String uuid = t.get(1, String.class);
     List<String> tags = ret.get(uuid);
     if (tags == null) {
       tags = new ArrayList<String>();
       ret.put(uuid, tags);
     }
     tags.add(t.get(0, String.class));
   }
   return ret;
 }
Exemple #13
0
  private List<VmInstanceInventory> vmFromDeleteAction(CascadeAction action) {
    List<VmInstanceInventory> ret = null;
    if (HostVO.class.getSimpleName().equals(action.getParentIssuer())) {
      List<HostInventory> hosts = action.getParentIssuerContext();
      List<String> huuids =
          CollectionUtils.transformToList(
              hosts,
              new Function<String, HostInventory>() {
                @Override
                public String call(HostInventory arg) {
                  return arg.getUuid();
                }
              });

      Map<String, VmInstanceVO> vmvos = new HashMap<String, VmInstanceVO>();
      SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
      q.add(VmInstanceVO_.hostUuid, SimpleQuery.Op.IN, huuids);
      q.add(VmInstanceVO_.type, Op.EQ, VmInstanceConstant.USER_VM_TYPE);
      List<VmInstanceVO> lst = q.list();
      for (VmInstanceVO vo : lst) {
        vmvos.put(vo.getUuid(), vo);
      }

      if (ClusterVO.class.getSimpleName().equals(action.getRootIssuer())) {
        List<ClusterInventory> clusters = action.getRootIssuerContext();
        List<String> clusterUuids =
            CollectionUtils.transformToList(
                clusters,
                new Function<String, ClusterInventory>() {
                  @Override
                  public String call(ClusterInventory arg) {
                    return arg.getUuid();
                  }
                });
        q = dbf.createQuery(VmInstanceVO.class);
        q.add(VmInstanceVO_.clusterUuid, Op.IN, clusterUuids);
        q.add(VmInstanceVO_.type, Op.EQ, VmInstanceConstant.USER_VM_TYPE);
        lst = q.list();
        for (VmInstanceVO vo : lst) {
          vmvos.put(vo.getUuid(), vo);
        }
      } else if (ZoneVO.class.getSimpleName().equals(action.getRootIssuer())) {
        List<ZoneInventory> zones = action.getRootIssuerContext();
        List<String> zoneUuids =
            CollectionUtils.transformToList(
                zones,
                new Function<String, ZoneInventory>() {
                  @Override
                  public String call(ZoneInventory arg) {
                    return arg.getUuid();
                  }
                });
        q = dbf.createQuery(VmInstanceVO.class);
        q.add(VmInstanceVO_.zoneUuid, Op.IN, zoneUuids);
        q.add(VmInstanceVO_.type, Op.EQ, VmInstanceConstant.USER_VM_TYPE);
        lst = q.list();
        for (VmInstanceVO vo : lst) {
          vmvos.put(vo.getUuid(), vo);
        }
      }

      if (!vmvos.isEmpty()) {
        ret = VmInstanceInventory.valueOf(vmvos.values());
      }
    } else if (NAME.equals(action.getParentIssuer())) {
      return action.getParentIssuerContext();
    } else if (PrimaryStorageVO.class.getSimpleName().equals(action.getParentIssuer())) {
      final List<String> pruuids =
          CollectionUtils.transformToList(
              (List<PrimaryStorageInventory>) action.getParentIssuerContext(),
              new Function<String, PrimaryStorageInventory>() {
                @Override
                public String call(PrimaryStorageInventory arg) {
                  return arg.getUuid();
                }
              });

      List<VmInstanceVO> vmvos =
          new Callable<List<VmInstanceVO>>() {
            @Override
            @Transactional(readOnly = true)
            public List<VmInstanceVO> call() {
              String sql =
                  "select vm from VmInstanceVO vm, VolumeVO vol, PrimaryStorageVO pr where vm.type = :vmType and vm.uuid = vol.vmInstanceUuid"
                      + " and vol.primaryStorageUuid = pr.uuid and vol.type = :volType and pr.uuid in (:uuids) group by vm.uuid";
              TypedQuery<VmInstanceVO> q =
                  dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
              q.setParameter("vmType", VmInstanceConstant.USER_VM_TYPE);
              q.setParameter("uuids", pruuids);
              q.setParameter("volType", VolumeType.Root);
              return q.getResultList();
            }
          }.call();

      if (!vmvos.isEmpty()) {
        ret = VmInstanceInventory.valueOf(vmvos);
      }
    } else if (L3NetworkVO.class.getSimpleName().equals(action.getParentIssuer())) {
      final List<String> l3uuids =
          CollectionUtils.transformToList(
              (List<L3NetworkInventory>) action.getParentIssuerContext(),
              new Function<String, L3NetworkInventory>() {
                @Override
                public String call(L3NetworkInventory arg) {
                  return arg.getUuid();
                }
              });

      List<VmInstanceVO> vmvos =
          new Callable<List<VmInstanceVO>>() {
            @Override
            @Transactional(readOnly = true)
            public List<VmInstanceVO> call() {
              String sql =
                  "select vm from VmInstanceVO vm, L3NetworkVO l3, VmNicVO nic where vm.type = :vmType and vm.uuid = nic.vmInstanceUuid and vm.state not in (:vmStates)"
                      + " and nic.l3NetworkUuid = l3.uuid and l3.uuid in (:uuids) group by vm.uuid";
              TypedQuery<VmInstanceVO> q =
                  dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
              q.setParameter("vmType", VmInstanceConstant.USER_VM_TYPE);
              q.setParameter(
                  "vmStates", Arrays.asList(VmInstanceState.Stopped, VmInstanceState.Stopping));
              q.setParameter("uuids", l3uuids);
              return q.getResultList();
            }
          }.call();

      if (!vmvos.isEmpty()) {
        ret = VmInstanceInventory.valueOf(vmvos);
      }
    } else if (IpRangeVO.class.getSimpleName().equals(action.getParentIssuer())) {
      final List<String> ipruuids =
          CollectionUtils.transformToList(
              (List<IpRangeInventory>) action.getParentIssuerContext(),
              new Function<String, IpRangeInventory>() {
                @Override
                public String call(IpRangeInventory arg) {
                  return arg.getUuid();
                }
              });

      List<VmInstanceVO> vmvos =
          new Callable<List<VmInstanceVO>>() {
            @Override
            @Transactional(readOnly = true)
            public List<VmInstanceVO> call() {
              String sql =
                  "select vm from VmInstanceVO vm, VmNicVO nic, UsedIpVO ip, IpRangeVO ipr where vm.type = :vmType and vm.uuid = nic.vmInstanceUuid and vm.state not in (:vmStates)"
                      + " and nic.usedIpUuid = ip.uuid and ip.ipRangeUuid = ipr.uuid and ipr.uuid in (:uuids) group by vm.uuid";
              TypedQuery<VmInstanceVO> q =
                  dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
              q.setParameter("vmType", VmInstanceConstant.USER_VM_TYPE);
              q.setParameter(
                  "vmStates", Arrays.asList(VmInstanceState.Stopped, VmInstanceState.Stopping));
              q.setParameter("uuids", ipruuids);
              return q.getResultList();
            }
          }.call();

      if (!vmvos.isEmpty()) {
        ret = VmInstanceInventory.valueOf(vmvos);
      }
    } else if (AccountVO.class.getSimpleName().equals(action.getParentIssuer())) {
      final List<String> auuids =
          CollectionUtils.transformToList(
              (List<AccountInventory>) action.getParentIssuerContext(),
              new Function<String, AccountInventory>() {
                @Override
                public String call(AccountInventory arg) {
                  return arg.getUuid();
                }
              });

      List<VmInstanceVO> vmvos =
          new Callable<List<VmInstanceVO>>() {
            @Override
            @Transactional(readOnly = true)
            public List<VmInstanceVO> call() {
              String sql =
                  "select d from VmInstanceVO d, AccountResourceRefVO r where d.uuid = r.resourceUuid and"
                      + " r.resourceType = :rtype and r.accountUuid in (:auuids) group by d.uuid";
              TypedQuery<VmInstanceVO> q =
                  dbf.getEntityManager().createQuery(sql, VmInstanceVO.class);
              q.setParameter("rtype", VmInstanceVO.class.getSimpleName());
              q.setParameter("auuids", auuids);
              return q.getResultList();
            }
          }.call();

      if (!vmvos.isEmpty()) {
        ret = VmInstanceInventory.valueOf(vmvos);
      }
    }

    return ret;
  }
  @Override
  public void beforeDeleteHost(final HostInventory inventory) {
    SimpleQuery<LocalStorageHostRefVO> q = dbf.createQuery(LocalStorageHostRefVO.class);
    q.select(LocalStorageHostRefVO_.primaryStorageUuid);
    q.add(LocalStorageHostRefVO_.hostUuid, Op.EQ, inventory.getUuid());
    final String psUuid = q.findValue();
    if (psUuid == null) {
      return;
    }

    logger.debug(
        String.format(
            "the host[uuid:%s] belongs to the local storage[uuid:%s], starts to delete vms and"
                + " volumes on the host",
            inventory.getUuid(), psUuid));

    final List<String> vmUuids =
        new Callable<List<String>>() {
          @Override
          @Transactional(readOnly = true)
          public List<String> call() {
            String sql =
                "select vm.uuid from VolumeVO vol, LocalStorageResourceRefVO ref, VmInstanceVO vm where ref.primaryStorageUuid = :psUuid"
                    + " and vol.type = :vtype and ref.resourceUuid = vol.uuid and ref.resourceType = :rtype and ref.hostUuid = :huuid"
                    + " and vm.uuid = vol.vmInstanceUuid";
            TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
            q.setParameter("vtype", VolumeType.Root);
            q.setParameter("rtype", VolumeVO.class.getSimpleName());
            q.setParameter("huuid", inventory.getUuid());
            q.setParameter("psUuid", psUuid);
            return q.getResultList();
          }
        }.call();

    // destroy vms
    if (!vmUuids.isEmpty()) {
      List<DestroyVmInstanceMsg> msgs =
          CollectionUtils.transformToList(
              vmUuids,
              new Function<DestroyVmInstanceMsg, String>() {
                @Override
                public DestroyVmInstanceMsg call(String uuid) {
                  DestroyVmInstanceMsg msg = new DestroyVmInstanceMsg();
                  msg.setVmInstanceUuid(uuid);
                  bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, uuid);
                  return msg;
                }
              });

      final FutureCompletion completion = new FutureCompletion();
      bus.send(
          msgs,
          new CloudBusListCallBack(completion) {
            @Override
            public void run(List<MessageReply> replies) {
              for (MessageReply r : replies) {
                if (!r.isSuccess()) {
                  String vmUuid = vmUuids.get(replies.indexOf(r));
                  // TODO
                  logger.warn(
                      String.format("failed to destroy the vm[uuid:%s], %s", vmUuid, r.getError()));
                }
              }

              completion.success();
            }
          });

      completion.await(TimeUnit.MINUTES.toMillis(15));
    }

    final List<String> volUuids =
        new Callable<List<String>>() {
          @Override
          @Transactional(readOnly = true)
          public List<String> call() {
            String sql =
                "select vol.uuid from VolumeVO vol, LocalStorageResourceRefVO ref where ref.primaryStorageUuid = :psUuid"
                    + " and vol.type = :vtype and ref.resourceUuid = vol.uuid and ref.resourceType = :rtype and ref.hostUuid = :huuid";
            TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
            q.setParameter("psUuid", psUuid);
            q.setParameter("vtype", VolumeType.Data);
            q.setParameter("rtype", VolumeVO.class.getSimpleName());
            q.setParameter("huuid", inventory.getUuid());
            return q.getResultList();
          }
        }.call();

    // delete data volumes
    if (!volUuids.isEmpty()) {
      List<DeleteVolumeMsg> msgs =
          CollectionUtils.transformToList(
              volUuids,
              new Function<DeleteVolumeMsg, String>() {
                @Override
                public DeleteVolumeMsg call(String uuid) {
                  DeleteVolumeMsg msg = new DeleteVolumeMsg();
                  msg.setUuid(uuid);
                  msg.setDetachBeforeDeleting(true);
                  bus.makeTargetServiceIdByResourceUuid(msg, VolumeConstant.SERVICE_ID, uuid);
                  return msg;
                }
              });

      final FutureCompletion completion = new FutureCompletion();
      bus.send(
          msgs,
          new CloudBusListCallBack(completion) {
            @Override
            public void run(List<MessageReply> replies) {
              for (MessageReply r : replies) {
                if (!r.isSuccess()) {
                  String uuid = volUuids.get(replies.indexOf(r));
                  // TODO
                  logger.warn(
                      String.format(
                          "failed to delete the data volume[uuid:%s], %s", uuid, r.getError()));
                }
              }

              completion.success();
            }
          });

      completion.await(TimeUnit.MINUTES.toMillis(15));
    }
  }
  @Override
  public void revokeEip(final EipStruct struct, final Completion completion) {
    SimpleQuery<VirtualRouterEipRefVO> q = dbf.createQuery(VirtualRouterEipRefVO.class);
    q.add(VirtualRouterEipRefVO_.eipUuid, SimpleQuery.Op.EQ, struct.getEip().getUuid());
    final VirtualRouterEipRefVO ref = q.find();
    if (ref == null) {
      // vr may have been deleted
      completion.success();
      return;
    }

    VirtualRouterVmVO vrvo = dbf.findByUuid(ref.getVirtualRouterVmUuid(), VirtualRouterVmVO.class);
    if (vrvo.getState() != VmInstanceState.Running) {
      // rule will be synced when vr state changes to Running
      completion.success();
      return;
    }

    final VirtualRouterVmInventory vr = VirtualRouterVmInventory.valueOf(vrvo);

    // TODO: how to cleanup on failure
    final FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
    chain.setName(String.format("revoke-eip-%s-vr-%s", struct.getEip().getUuid(), vr.getUuid()));
    chain
        .then(
            new NoRollbackFlow() {
              @Override
              public void run(final FlowTrigger trigger, Map data) {
                VirtualRouterCommands.RemoveEipCmd cmd = new VirtualRouterCommands.RemoveEipCmd();
                EipTO to = new EipTO();
                String priMac =
                    CollectionUtils.find(
                        vr.getVmNics(),
                        new Function<String, VmNicInventory>() {
                          @Override
                          public String call(VmNicInventory arg) {
                            if (arg.getL3NetworkUuid().equals(struct.getNic().getL3NetworkUuid())) {
                              return arg.getMac();
                            }
                            return null;
                          }
                        });

                to.setPrivateMac(priMac);
                to.setSnatInboundTraffic(struct.isSnatInboundTraffic());
                to.setVipIp(struct.getVip().getIp());
                to.setGuestIp(struct.getNic().getIp());
                cmd.setEip(to);

                VirtualRouterAsyncHttpCallMsg msg = new VirtualRouterAsyncHttpCallMsg();
                msg.setVmInstanceUuid(vr.getUuid());
                msg.setCommand(cmd);
                msg.setCheckStatus(true);
                msg.setPath(VirtualRouterConstant.VR_REMOVE_EIP);
                bus.makeTargetServiceIdByResourceUuid(
                    msg, VmInstanceConstant.SERVICE_ID, vr.getUuid());
                bus.send(
                    msg,
                    new CloudBusCallBack(trigger) {
                      @Override
                      public void run(MessageReply reply) {
                        if (!reply.isSuccess()) {
                          trigger.setError(reply.getError());
                        } else {
                          VirtualRouterAsyncHttpCallReply re = reply.castReply();
                          RemoveEipRsp ret = re.toResponse(RemoveEipRsp.class);
                          if (!ret.isSuccess()) {
                            String err =
                                String.format(
                                    "failed to remove eip[uuid:%s, name:%s, ip:%s] for vm nic[uuid:%s] on virtual router[uuid:%s], %s",
                                    struct.getEip().getUuid(),
                                    struct.getEip().getName(),
                                    struct.getVip().getIp(),
                                    struct.getNic().getUuid(),
                                    vr.getUuid(),
                                    ret.getError());
                            trigger.setError(errf.stringToOperationError(err));
                          }
                        }

                        trigger.next();
                      }
                    });
              }
            })
        .then(
            new NoRollbackFlow() {
              @Override
              public void run(final FlowTrigger trigger, Map data) {
                asf.removeFirewall(
                    vr.getUuid(),
                    struct.getVip().getL3NetworkUuid(),
                    getFirewallRules(struct),
                    new Completion() {
                      @Override
                      public void success() {
                        trigger.next();
                      }

                      @Override
                      public void fail(ErrorCode errorCode) {
                        logger.warn(
                            String.format(
                                "failed to remove firewall rules on virtual router[uuid:%s, l3Network uuid:%s], %s",
                                vr.getUuid(), struct.getVip().getL3NetworkUuid(), errorCode));
                        trigger.next();
                      }
                    });
              }
            })
        .done(
            new FlowDoneHandler(completion) {
              @Override
              public void handle(Map data) {
                String info =
                    String.format(
                        "successfully removed eip[uuid:%s, name:%s, ip:%s] for vm nic[uuid:%s] on virtual router[uuid:%s]",
                        struct.getEip().getUuid(),
                        struct.getEip().getName(),
                        struct.getVip().getIp(),
                        struct.getNic().getUuid(),
                        vr.getUuid());
                logger.debug(info);
                dbf.remove(ref);
                completion.success();
              }
            })
        .error(
            new FlowErrorHandler(completion) {
              @Override
              public void handle(ErrorCode errCode, Map data) {
                completion.fail(errCode);
              }
            })
        .start();
  }
  @Override
  public void run(final FlowTrigger chain, final Map data) {
    final VirtualRouterVmInventory vr =
        (VirtualRouterVmInventory) data.get(VirtualRouterConstant.Param.VR.toString());

    List<String> nwServed = vr.getGuestL3Networks();
    List<String> l3Uuids =
        vrMgr.selectL3NetworksNeedingSpecificNetworkService(nwServed, NetworkServiceType.DNS);
    if (l3Uuids.isEmpty()) {
      chain.next();
      return;
    }

    if (VirtualRouterSystemTags.DEDICATED_ROLE_VR.hasTag(vr.getUuid())
        && !VirtualRouterSystemTags.VR_DNS_ROLE.hasTag(vr.getUuid())) {
      chain.next();
      return;
    }

    new VirtualRouterRoleManager().makeDnsRole(vr.getUuid());

    SimpleQuery<L3NetworkDnsVO> query = dbf.createQuery(L3NetworkDnsVO.class);
    query.select(L3NetworkDnsVO_.dns);
    query.add(L3NetworkDnsVO_.l3NetworkUuid, Op.IN, l3Uuids);
    List<String> lst = query.listValue();
    if (lst.isEmpty()) {
      chain.next();
      return;
    }

    Set<String> dnsAddresses = new HashSet<String>(lst.size());
    dnsAddresses.addAll(lst);

    final List<DnsInfo> dns = new ArrayList<DnsInfo>(dnsAddresses.size());
    for (String d : dnsAddresses) {
      DnsInfo dinfo = new DnsInfo();
      dinfo.setDnsAddress(d);
      dns.add(dinfo);
    }

    SetDnsCmd cmd = new SetDnsCmd();
    cmd.setDns(dns);

    VirtualRouterAsyncHttpCallMsg msg = new VirtualRouterAsyncHttpCallMsg();
    msg.setVmInstanceUuid(vr.getUuid());
    msg.setPath(VirtualRouterConstant.VR_SET_DNS_PATH);
    msg.setCommand(cmd);
    msg.setCommandTimeout(apiTimeoutManager.getTimeout(cmd.getClass(), "5m"));
    bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, vr.getUuid());
    bus.send(
        msg,
        new CloudBusCallBack(chain) {
          @Override
          public void run(MessageReply reply) {
            if (!reply.isSuccess()) {
              chain.fail(reply.getError());
              return;
            }

            VirtualRouterAsyncHttpCallReply re = reply.castReply();
            SetDnsRsp ret = re.toResponse(SetDnsRsp.class);
            if (ret.isSuccess()) {
              chain.next();
            } else {
              String err =
                  String.format(
                      "virtual router[name: %s, uuid: %s] failed to configure dns%s, %s ",
                      vr.getName(), vr.getUuid(), JSONObjectUtil.toJsonString(dns), ret.getError());
              logger.warn(err);
              chain.fail(errf.stringToOperationError(err));
            }
          }
        });
  }
 private boolean isRootVolumeOnLocalStorage(String rootVolumeUuid) {
   SimpleQuery<LocalStorageResourceRefVO> q = dbf.createQuery(LocalStorageResourceRefVO.class);
   q.add(LocalStorageResourceRefVO_.resourceUuid, Op.EQ, rootVolumeUuid);
   return q.isExists();
 }