Example #1
0
  private void delete(
      boolean forceDelete, boolean detachBeforeDeleting, final Completion completion) {
    final String issuer = VolumeVO.class.getSimpleName();
    VolumeDeletionStruct struct = new VolumeDeletionStruct();
    struct.setInventory(getSelfInventory());
    struct.setDetachBeforeDeleting(detachBeforeDeleting);
    struct.setDeletionPolicy(deletionPolicyMgr.getDeletionPolicy(self.getUuid()).toString());
    final List<VolumeDeletionStruct> ctx = list(struct);
    FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
    chain.setName("delete-data-volume");
    if (!forceDelete) {
      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(completion) {
              @Override
              public void handle(Map data) {
                casf.asyncCascadeFull(
                    CascadeConstant.DELETION_CLEANUP_CODE, issuer, ctx, new NopeCompletion());
                completion.success();
              }
            })
        .error(
            new FlowErrorHandler(completion) {
              @Override
              public void handle(ErrorCode errCode, Map data) {
                completion.fail(errCode);
              }
            })
        .start();
  }
Example #2
0
  private void deleteVolume(final VolumeDeletionMsg msg, final NoErrorCompletion completion) {
    final VolumeDeletionReply reply = new VolumeDeletionReply();
    for (VolumeDeletionExtensionPoint extp :
        pluginRgty.getExtensionList(VolumeDeletionExtensionPoint.class)) {
      extp.preDeleteVolume(getSelfInventory());
    }

    CollectionUtils.safeForEach(
        pluginRgty.getExtensionList(VolumeDeletionExtensionPoint.class),
        new ForEachFunction<VolumeDeletionExtensionPoint>() {
          @Override
          public void run(VolumeDeletionExtensionPoint arg) {
            arg.beforeDeleteVolume(getSelfInventory());
          }
        });

    FlowChain chain = FlowChainBuilder.newShareFlowChain();
    chain.setName(String.format("delete-volume-%s", self.getUuid()));
    // for NotInstantiated Volume, no flow to execute
    chain.allowEmptyFlow();
    chain
        .then(
            new ShareFlow() {
              VolumeDeletionPolicy deletionPolicy;

              {
                if (msg.getDeletionPolicy() == null) {
                  deletionPolicy = deletionPolicyMgr.getDeletionPolicy(self.getUuid());
                } else {
                  deletionPolicy = VolumeDeletionPolicy.valueOf(msg.getDeletionPolicy());
                }
              }

              @Override
              public void setup() {
                if (self.getVmInstanceUuid() != null
                    && self.getType() == VolumeType.Data
                    && msg.isDetachBeforeDeleting()) {
                  flow(
                      new NoRollbackFlow() {
                        String __name__ = "detach-volume-from-vm";

                        public void run(final FlowTrigger trigger, Map data) {
                          DetachDataVolumeFromVmMsg dmsg = new DetachDataVolumeFromVmMsg();
                          dmsg.setVolume(getSelfInventory());
                          bus.makeTargetServiceIdByResourceUuid(
                              dmsg, VmInstanceConstant.SERVICE_ID, dmsg.getVmInstanceUuid());
                          bus.send(
                              dmsg,
                              new CloudBusCallBack(trigger) {
                                @Override
                                public void run(MessageReply reply) {
                                  self.setVmInstanceUuid(null);
                                  self = dbf.updateAndRefresh(self);
                                  trigger.next();
                                }
                              });
                        }
                      });
                }

                if (deletionPolicy == VolumeDeletionPolicy.Direct) {
                  flow(
                      new NoRollbackFlow() {
                        String __name__ = "delete-data-volume-from-primary-storage";

                        @Override
                        public void run(final FlowTrigger trigger, Map data) {
                          if (self.getStatus() == VolumeStatus.Ready) {
                            DeleteVolumeOnPrimaryStorageMsg dmsg =
                                new DeleteVolumeOnPrimaryStorageMsg();
                            dmsg.setVolume(getSelfInventory());
                            dmsg.setUuid(self.getPrimaryStorageUuid());
                            bus.makeTargetServiceIdByResourceUuid(
                                dmsg,
                                PrimaryStorageConstant.SERVICE_ID,
                                self.getPrimaryStorageUuid());
                            logger.debug(
                                String.format(
                                    "Asking primary storage[uuid:%s] to remove data volume[uuid:%s]",
                                    self.getPrimaryStorageUuid(), self.getUuid()));
                            bus.send(
                                dmsg,
                                new CloudBusCallBack(trigger) {
                                  @Override
                                  public void run(MessageReply reply) {
                                    if (!reply.isSuccess()) {
                                      logger.warn(
                                          String.format(
                                              "failed to delete volume[uuid:%s, name:%s], %s",
                                              self.getUuid(), self.getName(), reply.getError()));
                                    }

                                    trigger.next();
                                  }
                                });
                          } else {
                            trigger.next();
                          }
                        }
                      });
                }

                if (self.getPrimaryStorageUuid() != null
                    && deletionPolicy == VolumeDeletionPolicy.Direct) {
                  flow(
                      new NoRollbackFlow() {
                        String __name__ = "return-primary-storage-capacity";

                        @Override
                        public void run(FlowTrigger trigger, Map data) {
                          ReturnPrimaryStorageCapacityMsg rmsg =
                              new ReturnPrimaryStorageCapacityMsg();
                          rmsg.setPrimaryStorageUuid(self.getPrimaryStorageUuid());
                          rmsg.setDiskSize(self.getSize());
                          bus.makeTargetServiceIdByResourceUuid(
                              rmsg,
                              PrimaryStorageConstant.SERVICE_ID,
                              self.getPrimaryStorageUuid());
                          bus.send(rmsg);
                          trigger.next();
                        }
                      });
                }

                done(
                    new FlowDoneHandler(msg) {
                      @Override
                      public void handle(Map data) {
                        VolumeStatus oldStatus = self.getStatus();

                        if (deletionPolicy == VolumeDeletionPolicy.Direct) {
                          dbf.remove(self);
                        } else if (deletionPolicy == VolumeDeletionPolicy.Delay) {
                          self.setStatus(VolumeStatus.Deleted);
                          self = dbf.updateAndRefresh(self);
                        } else if (deletionPolicy == VolumeDeletionPolicy.Never) {
                          self.setStatus(VolumeStatus.Deleted);
                          self = dbf.updateAndRefresh(self);
                        }

                        new FireVolumeCanonicalEvent()
                            .fireVolumeStatusChangedEvent(oldStatus, getSelfInventory());

                        CollectionUtils.safeForEach(
                            pluginRgty.getExtensionList(VolumeDeletionExtensionPoint.class),
                            new ForEachFunction<VolumeDeletionExtensionPoint>() {
                              @Override
                              public void run(VolumeDeletionExtensionPoint arg) {
                                arg.afterDeleteVolume(getSelfInventory());
                              }
                            });
                        bus.reply(msg, reply);
                      }
                    });

                error(
                    new FlowErrorHandler(msg) {
                      @Override
                      public void handle(final ErrorCode errCode, Map data) {
                        CollectionUtils.safeForEach(
                            pluginRgty.getExtensionList(VolumeDeletionExtensionPoint.class),
                            new ForEachFunction<VolumeDeletionExtensionPoint>() {
                              @Override
                              public void run(VolumeDeletionExtensionPoint arg) {
                                arg.failedToDeleteVolume(getSelfInventory(), errCode);
                              }
                            });

                        reply.setError(errCode);
                        bus.reply(msg, reply);
                      }
                    });

                Finally(
                    new FlowFinallyHandler() {
                      @Override
                      public void Finally() {
                        completion.done();
                      }
                    });
              }
            })
        .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();
                                volumeUsage =
                                    ratioMgr.calculateByRatio(self.getUuid(), volumeUsage);
                                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;
                                }

                                // note: snapshot size is physical size,
                                // don't calculate over-provisioning here
                                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);
                      }

                      private void writeToDb() {
                        PrimaryStorageCapacityUpdater updater =
                            new PrimaryStorageCapacityUpdater(self.getUuid());
                        updater.run(
                            new PrimaryStorageCapacityUpdaterRunnable() {
                              @Override
                              public PrimaryStorageCapacityVO call(PrimaryStorageCapacityVO cap) {
                                long avail = cap.getTotalCapacity() - volumeUsage - snapshotUsage;
                                cap.setAvailableCapacity(avail);
                                cap.setAvailablePhysicalCapacity(availablePhysicalSize);
                                cap.setTotalPhysicalCapacity(totalPhysicalSize);
                                return cap;
                              }
                            });
                      }
                    });

                error(
                    new FlowErrorHandler(msg) {
                      @Override
                      public void handle(ErrorCode errCode, Map data) {
                        evt.setErrorCode(errCode);
                        bus.publish(evt);
                      }
                    });
              }
            })
        .start();
  }
  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);

                PrimaryStorageDeletedData d = new PrimaryStorageDeletedData();
                d.setPrimaryStorageUuid(self.getUuid());
                d.setInventory(PrimaryStorageInventory.valueOf(self));
                evtf.fire(PrimaryStorageCanonicalEvent.PRIMARY_STORAGE_DELETED_PATH, d);
              }
            })
        .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();
  }
Example #5
0
  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();
  }