private void handle(APIDeleteImageMsg msg) { final APIDeleteImageEvent evt = new APIDeleteImageEvent(msg.getId()); final String issuer = ImageVO.class.getSimpleName(); ImageDeletionStruct struct = new ImageDeletionStruct(); struct.setImage(ImageInventory.valueOf(self)); struct.setBackupStorageUuids(msg.getBackupStorageUuids()); final List<ImageDeletionStruct> ctx = Arrays.asList(struct); FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName(String.format("delete-image-%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 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(); }
private void handle(final ImageDeletionMsg msg) { final ImageDeletionReply reply = new ImageDeletionReply(); if (self.getBackupStorageRefs().isEmpty()) { // the image is not on any backup storage; mostly likely the image is not in the status of // Ready, for example // it's still downloading // in this case, we directly delete it from the database dbf.remove(self); bus.reply(msg, reply); return; } final ImageDeletionPolicy deletionPolicy = msg.getDeletionPolicy() == null ? deletionPolicyMgr.getDeletionPolicy(self.getUuid()) : ImageDeletionPolicy.valueOf(msg.getDeletionPolicy()); FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName(String.format("delete-image-%s", self.getUuid())); Collection<ImageBackupStorageRefVO> toDelete = msg.getBackupStorageUuids() == null ? self.getBackupStorageRefs() : CollectionUtils.transformToList( self.getBackupStorageRefs(), new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() { @Override public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) { return msg.getBackupStorageUuids().contains(arg.getBackupStorageUuid()) ? arg : null; } }); for (final ImageBackupStorageRefVO ref : toDelete) { chain.then( new NoRollbackFlow() { String __name__ = String.format( "delete-image-%s-from-backup-storage-%s", self.getUuid(), ref.getBackupStorageUuid()); @Override public void run(final FlowTrigger trigger, Map data) { if (deletionPolicy == ImageDeletionPolicy.Direct) { DeleteBitsOnBackupStorageMsg dmsg = new DeleteBitsOnBackupStorageMsg(); dmsg.setBackupStorageUuid(ref.getBackupStorageUuid()); dmsg.setInstallPath(ref.getInstallPath()); bus.makeTargetServiceIdByResourceUuid( dmsg, BackupStorageConstant.SERVICE_ID, dmsg.getBackupStorageUuid()); bus.send( dmsg, new CloudBusCallBack(trigger) { @Override public void run(MessageReply reply) { if (!reply.isSuccess()) { // TODO logger.warn( String.format( "failed to delete image[uuid:%s, name:%s] from backup storage[uuid:%s] because %s, need to garbage collect it", self.getUuid(), self.getName(), reply.getError(), ref.getBackupStorageUuid())); } else { returnBackupStorageCapacity(ref.getBackupStorageUuid(), self.getSize()); dbf.remove(ref); } trigger.next(); } }); } else if (deletionPolicy == ImageDeletionPolicy.DeleteReference) { dbf.remove(ref); logger.debug( String.format( "delete the image[uuid: %s, name:%s]'s reference of the backup storage[uuid:%s]", self.getUuid(), self.getName(), ref.getBackupStorageUuid())); trigger.next(); } else { ref.setStatus(ImageStatus.Deleted); dbf.update(ref); trigger.next(); } } }); } chain .done( new FlowDoneHandler(msg) { @Override public void handle(Map data) { self = dbf.reload(self); if (self.getBackupStorageRefs().isEmpty()) { dbf.remove(self); if (deletionPolicy == ImageDeletionPolicy.DeleteReference) { logger.debug( String.format( "successfully directly deleted the image[uuid:%s, name:%s] from the database," + " as the policy is DeleteReference, it's still on the physical backup storage", self.getUuid(), self.getName())); } else { logger.debug( String.format( "successfully directly deleted the image[uuid:%s, name:%s]", self.getUuid(), self.getName())); } } else { int deleteCount = 0; for (ImageBackupStorageRefVO ref : self.getBackupStorageRefs()) { if (ref.getStatus() == ImageStatus.Deleted) { deleteCount++; } } if (deleteCount == self.getBackupStorageRefs().size()) { self.setStatus(ImageStatus.Deleted); self = dbf.updateAndRefresh(self); logger.debug( String.format( "successfully deleted the image[uuid:%s, name:%s] with deletion policy[%s]", self.getUuid(), self.getName(), deletionPolicy)); } } bus.reply(msg, reply); } }) .error( new FlowErrorHandler(msg) { @Override public void handle(ErrorCode errCode, Map data) { reply.setError(errCode); bus.reply(msg, reply); } }) .start(); }
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 applyEip( final VirtualRouterVmInventory vr, final EipStruct struct, final Completion completion) { FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName(String.format("apply-eip-%s-vr-%s", struct.getEip().getUuid(), vr.getUuid())); chain .then( new Flow() { @Override public void run(final FlowTrigger trigger, Map data) { asf.openFirewall( vr.getUuid(), struct.getVip().getL3NetworkUuid(), getFirewallRules(struct), new Completion(trigger) { @Override public void success() { trigger.next(); } @Override public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } }); } @Override public void rollback(final FlowRollback trigger, Map data) { asf.removeFirewall( vr.getUuid(), struct.getVip().getL3NetworkUuid(), getFirewallRules(struct), new Completion(trigger) { @Override public void success() { trigger.rollback(); } @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.rollback(); } }); } }) .then( new NoRollbackFlow() { @Override public void run(final FlowTrigger trigger, Map data) { 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.setVipIp(struct.getVip().getIp()); to.setGuestIp(struct.getNic().getIp()); to.setSnatInboundTraffic(struct.isSnatInboundTraffic()); VirtualRouterCommands.CreateEipCmd cmd = new VirtualRouterCommands.CreateEipCmd(); cmd.setEip(to); VirtualRouterAsyncHttpCallMsg msg = new VirtualRouterAsyncHttpCallMsg(); msg.setCheckStatus(true); msg.setPath(VirtualRouterConstant.VR_CREATE_EIP); msg.setCommand(cmd); msg.setVmInstanceUuid(vr.getUuid()); bus.makeTargetServiceIdByResourceUuid( msg, VmInstanceConstant.SERVICE_ID, vr.getUuid()); bus.send( msg, new CloudBusCallBack(completion) { @Override public void run(MessageReply reply) { if (!reply.isSuccess()) { trigger.fail(reply.getError()); return; } VirtualRouterAsyncHttpCallReply re = reply.castReply(); CreateEipRsp ret = re.toResponse(CreateEipRsp.class); if (ret.isSuccess()) { trigger.next(); } else { trigger.fail( errf.stringToOperationError( String.format( "failed to create 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()))); } } }); } }) .done( new FlowDoneHandler(completion) { @Override public void handle(Map data) { String info = String.format( "successfully created 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()); new VirtualRouterRoleManager().makeEipRole(vr.getUuid()); logger.debug(info); completion.success(); } }) .error( new FlowErrorHandler(completion) { @Override public void handle(ErrorCode errCode, Map data) { completion.fail(errCode); } }) .start(); }
@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(); }
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(); }
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(); }