private void handleDeletion(final CascadeAction action, final Completion completion) {
    int op = toDeletionOpCode(action);
    if (op == OP_NOPE) {
      completion.success();
      return;
    }

    if (op == OP_REMOVE_INSTANCE_OFFERING) {
      if (VmGlobalConfig.UPDATE_INSTANCE_OFFERING_TO_NULL_WHEN_DELETING.value(Boolean.class)) {
        new Runnable() {
          @Override
          @Transactional
          public void run() {
            List<InstanceOfferingInventory> offerings = action.getParentIssuerContext();
            List<String> offeringUuids =
                CollectionUtils.transformToList(
                    offerings,
                    new Function<String, InstanceOfferingInventory>() {
                      @Override
                      public String call(InstanceOfferingInventory arg) {
                        return arg.getUuid();
                      }
                    });

            String sql =
                "update VmInstanceVO vm set vm.instanceOfferingUuid = null where vm.instanceOfferingUuid in (:offeringUuids)";
            Query q = dbf.getEntityManager().createQuery(sql);
            q.setParameter("offeringUuids", offeringUuids);
            q.executeUpdate();
          }
        }.run();
      }

      completion.success();
      return;
    }

    final List<VmInstanceInventory> vminvs = vmFromDeleteAction(action);
    if (vminvs == null) {
      completion.success();
      return;
    }

    if (op == OP_STOP) {
      List<StopVmInstanceMsg> msgs = new ArrayList<StopVmInstanceMsg>();
      for (VmInstanceInventory inv : vminvs) {
        StopVmInstanceMsg msg = new StopVmInstanceMsg();
        msg.setVmInstanceUuid(inv.getUuid());
        bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, inv.getUuid());
        msgs.add(msg);
      }

      bus.send(
          msgs,
          20,
          new CloudBusListCallBack(completion) {
            @Override
            public void run(List<MessageReply> replies) {
              if (!action.isActionCode(CascadeConstant.DELETION_FORCE_DELETE_CODE)) {
                for (MessageReply r : replies) {
                  if (!r.isSuccess()) {
                    completion.fail(r.getError());
                    return;
                  }
                }
              }

              completion.success();
            }
          });
    } else if (op == OP_DELETION) {
      List<VmInstanceDeletionMsg> msgs = new ArrayList<VmInstanceDeletionMsg>();
      for (VmInstanceInventory inv : vminvs) {
        VmInstanceDeletionMsg msg = new VmInstanceDeletionMsg();
        msg.setForceDelete(action.isActionCode(CascadeConstant.DELETION_FORCE_DELETE_CODE));
        msg.setVmInstanceUuid(inv.getUuid());
        bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, inv.getUuid());
        msgs.add(msg);
      }

      bus.send(
          msgs,
          20,
          new CloudBusListCallBack(completion) {
            @Override
            public void run(List<MessageReply> replies) {
              if (!action.isActionCode(CascadeConstant.DELETION_FORCE_DELETE_CODE)) {
                for (MessageReply r : replies) {
                  if (!r.isSuccess()) {
                    completion.fail(r.getError());
                    return;
                  }
                }
              }

              completion.success();
            }
          });
    } else if (op == OP_DETACH_NIC) {
      List<DetachNicFromVmMsg> msgs = new ArrayList<DetachNicFromVmMsg>();
      List<L3NetworkInventory> l3s = action.getParentIssuerContext();
      for (VmInstanceInventory vm : vminvs) {
        for (L3NetworkInventory l3 : l3s) {
          DetachNicFromVmMsg msg = new DetachNicFromVmMsg();
          msg.setVmInstanceUuid(vm.getUuid());
          msg.setVmNicUuid(vm.findNic(l3.getUuid()).getUuid());
          bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, vm.getUuid());
          msgs.add(msg);
        }
      }

      bus.send(
          msgs,
          new CloudBusListCallBack(completion) {
            @Override
            public void run(List<MessageReply> replies) {
              if (!action.isActionCode(CascadeConstant.DELETION_FORCE_DELETE_CODE)) {
                for (MessageReply r : replies) {
                  if (!r.isSuccess()) {
                    completion.fail(r.getError());
                    return;
                  }
                }
              }

              completion.success();
            }
          });
    }
  }