protected void handle(APIDeletePrimaryStorageMsg msg) {
    final APIDeletePrimaryStorageEvent evt = new APIDeletePrimaryStorageEvent(msg.getId());
    final String issuer = PrimaryStorageVO.class.getSimpleName();
    final List<PrimaryStorageInventory> ctx = PrimaryStorageInventory.valueOf(Arrays.asList(self));
    FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
    chain.setName(String.format("delete-primary-storage-%s", msg.getUuid()));
    if (msg.getDeletionMode() == APIDeleteMessage.DeletionMode.Permissive) {
      chain
          .then(
              new NoRollbackFlow() {
                @Override
                public void run(final FlowTrigger trigger, Map data) {
                  casf.asyncCascade(
                      CascadeConstant.DELETION_CHECK_CODE,
                      issuer,
                      ctx,
                      new Completion(trigger) {
                        @Override
                        public void success() {
                          trigger.next();
                        }

                        @Override
                        public void fail(ErrorCode errorCode) {
                          trigger.fail(errorCode);
                        }
                      });
                }
              })
          .then(
              new NoRollbackFlow() {
                @Override
                public void run(final FlowTrigger trigger, Map data) {
                  casf.asyncCascade(
                      CascadeConstant.DELETION_DELETE_CODE,
                      issuer,
                      ctx,
                      new Completion(trigger) {
                        @Override
                        public void success() {
                          trigger.next();
                        }

                        @Override
                        public void fail(ErrorCode errorCode) {
                          trigger.fail(errorCode);
                        }
                      });
                }
              });
    } else {
      chain.then(
          new NoRollbackFlow() {
            @Override
            public void run(final FlowTrigger trigger, Map data) {
              casf.asyncCascade(
                  CascadeConstant.DELETION_FORCE_DELETE_CODE,
                  issuer,
                  ctx,
                  new Completion(trigger) {
                    @Override
                    public void success() {
                      trigger.next();
                    }

                    @Override
                    public void fail(ErrorCode errorCode) {
                      trigger.fail(errorCode);
                    }
                  });
            }
          });
    }

    chain
        .done(
            new FlowDoneHandler(msg) {
              @Override
              public void handle(Map data) {
                casf.asyncCascadeFull(
                    CascadeConstant.DELETION_CLEANUP_CODE, issuer, ctx, new NopeCompletion());
                bus.publish(evt);
              }
            })
        .error(
            new FlowErrorHandler(msg) {
              @Override
              public void handle(ErrorCode errCode, Map data) {
                evt.setErrorCode(
                    errf.instantiateErrorCode(SysErrors.DELETE_RESOURCE_ERROR, errCode));
                bus.publish(evt);
              }
            })
        .start();
  }
  private void handle(final APISyncPrimaryStorageCapacityMsg msg) {
    final APISyncPrimaryStorageCapacityEvent evt =
        new APISyncPrimaryStorageCapacityEvent(msg.getId());

    FlowChain chain = FlowChainBuilder.newShareFlowChain();
    chain.setName(String.format("sync-capacity-of-primary-storage-%s", self.getUuid()));
    chain
        .then(
            new ShareFlow() {
              Long volumeUsage;
              Long snapshotUsage;
              Long totalPhysicalSize;
              Long availablePhysicalSize;

              @Override
              public void setup() {
                flow(
                    new NoRollbackFlow() {
                      String __name__ = "sync-capacity-used-by-volumes";

                      @Override
                      public void run(final FlowTrigger trigger, Map data) {
                        VolumeReportPrimaryStorageCapacityUsageMsg msg =
                            new VolumeReportPrimaryStorageCapacityUsageMsg();
                        msg.setPrimaryStorageUuid(self.getUuid());
                        bus.makeLocalServiceId(msg, VolumeConstant.SERVICE_ID);
                        bus.send(
                            msg,
                            new CloudBusCallBack(trigger) {
                              @Override
                              public void run(MessageReply reply) {
                                if (!reply.isSuccess()) {
                                  trigger.fail(reply.getError());
                                  return;
                                }

                                VolumeReportPrimaryStorageCapacityUsageReply r = reply.castReply();
                                volumeUsage = r.getUsedCapacity();
                                trigger.next();
                              }
                            });
                      }
                    });

                flow(
                    new NoRollbackFlow() {
                      String __name__ = "sync-capacity-used-by-volume-snapshots";

                      @Override
                      public void run(final FlowTrigger trigger, Map data) {
                        VolumeSnapshotReportPrimaryStorageCapacityUsageMsg msg =
                            new VolumeSnapshotReportPrimaryStorageCapacityUsageMsg();
                        msg.setPrimaryStorageUuid(self.getUuid());
                        bus.makeLocalServiceId(msg, VolumeSnapshotConstant.SERVICE_ID);
                        bus.send(
                            msg,
                            new CloudBusCallBack(trigger) {
                              @Override
                              public void run(MessageReply reply) {
                                if (!reply.isSuccess()) {
                                  trigger.fail(reply.getError());
                                  return;
                                }

                                VolumeSnapshotReportPrimaryStorageCapacityUsageReply r =
                                    reply.castReply();
                                snapshotUsage = r.getUsedSize();
                                trigger.next();
                              }
                            });
                      }
                    });

                flow(
                    new NoRollbackFlow() {
                      String __name__ = "sync-physical-capacity";

                      @Override
                      public void run(final FlowTrigger trigger, Map data) {
                        syncPhysicalCapacity(
                            new ReturnValueCompletion<PhysicalCapacityUsage>(trigger) {
                              @Override
                              public void success(PhysicalCapacityUsage returnValue) {
                                totalPhysicalSize = returnValue.totalPhysicalSize;
                                availablePhysicalSize = returnValue.availablePhysicalSize;
                                availablePhysicalSize =
                                    availablePhysicalSize < 0 ? 0 : availablePhysicalSize;
                                trigger.next();
                              }

                              @Override
                              public void fail(ErrorCode errorCode) {
                                trigger.fail(errorCode);
                              }
                            });
                      }
                    });

                done(
                    new FlowDoneHandler(msg) {
                      @Override
                      public void handle(Map data) {
                        writeToDb();
                        self = dbf.reload(self);
                        evt.setInventory(getSelfInventory());
                        bus.publish(evt);
                      }

                      @Transactional
                      private void writeToDb() {
                        PrimaryStorageCapacityVO vo =
                            dbf.getEntityManager()
                                .find(
                                    PrimaryStorageCapacityVO.class,
                                    self.getUuid(),
                                    LockModeType.PESSIMISTIC_WRITE);

                        long avail = vo.getTotalCapacity() - volumeUsage - snapshotUsage;
                        avail = avail < 0 ? 0 : avail;
                        vo.setAvailableCapacity(avail);
                        vo.setAvailablePhysicalCapacity(availablePhysicalSize);
                        vo.setTotalPhysicalCapacity(totalPhysicalSize);
                        dbf.getEntityManager().merge(vo);
                      }
                    });

                error(
                    new FlowErrorHandler(msg) {
                      @Override
                      public void handle(ErrorCode errCode, Map data) {
                        evt.setErrorCode(errCode);
                        bus.publish(evt);
                      }
                    });
              }
            })
        .start();
  }