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 releaseNetworkServices( final VmInstanceSpec spec, NetworkServiceExtensionPosition position, final NoErrorCompletion completion) { if (!spec.getVmInventory().getType().equals(VmInstanceConstant.USER_VM_TYPE)) { completion.done(); return; } if (nsExts.isEmpty()) { completion.done(); return; } // we run into this situation when VM nics are all detached and the // VM is being rebooted if (spec.getDestNics().isEmpty()) { completion.done(); return; } List<String> nsTypes = spec.getRequiredNetworkServiceTypes(); FlowChain schain = FlowChainBuilder.newSimpleFlowChain() .setName( String.format( "release-network-services-from-vm-%s", spec.getVmInventory().getUuid())); schain.allowEmptyFlow(); for (final NetworkServiceExtensionPoint ns : nsExts) { if (position != null && ns.getNetworkServiceExtensionPosition() != position) { continue; } if (!nsTypes.contains(ns.getNetworkServiceType().toString())) { continue; } NoRollbackFlow flow = new NoRollbackFlow() { String __name__ = String.format("release-network-service-%s", ns.getNetworkServiceType()); @Override public void run(final FlowTrigger chain, Map data) { logger.debug( String.format( "NetworkServiceExtensionPoint[%s] is asking back ends to release network service[%s] if needed", ns.getClass().getName(), ns.getNetworkServiceType())); ns.releaseNetworkService( spec, data, new NoErrorCompletion() { @Override public void done() { chain.next(); } }); } }; schain.then(flow); } schain .done( new FlowDoneHandler(completion) { @Override public void handle(Map data) { logger.debug( String.format( "successfully released network services for vm[uuid:%s, name:%s]", spec.getVmInventory().getUuid(), spec.getVmInventory().getName())); completion.done(); } }) .start(); }