private void handle(final ExpungeImageMsg msg) { final ExpungeImageReply reply = new ExpungeImageReply(); final ImageBackupStorageRefVO ref = CollectionUtils.find( self.getBackupStorageRefs(), new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() { @Override public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) { return arg.getBackupStorageUuid().equals(msg.getBackupStorageUuid()) ? arg : null; } }); if (ref == null) { logger.debug( String.format( "cannot find reference for the image[uuid:%s] on the backup storage[uuid:%s], assume it's been deleted", self.getUuid(), msg.getBackupStorageUuid())); bus.reply(msg, reply); return; } 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(msg) { @Override public void run(MessageReply r) { if (!r.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(), r.getError(), ref.getBackupStorageUuid())); reply.setError(r.getError()); } else { returnBackupStorageCapacity(ref.getBackupStorageUuid(), self.getSize()); dbf.remove(ref); logger.debug( String.format( "successfully expunged the image[uuid: %s, name: %s] on the backup storage[uuid: %s]", self.getUuid(), self.getName(), ref.getBackupStorageUuid())); self = dbf.findByUuid(self.getUuid(), ImageVO.class); if (self.getBackupStorageRefs().isEmpty()) { logger.debug( String.format( "the image[uuid:%s, name:%s] has been expunged on all backup storage, remove it from database", self.getUuid(), self.getName())); dbf.remove(self); } } bus.reply(msg, reply); } }); }
private void handle(APIChangeImageStateMsg msg) { ImageStateEvent sevt = ImageStateEvent.valueOf(msg.getStateEvent()); if (sevt == ImageStateEvent.disable) { self.setState(ImageState.Disabled); } else { self.setState(ImageState.Enabled); } self = dbf.updateAndRefresh(self); APIChangeImageStateEvent evt = new APIChangeImageStateEvent(msg.getId()); evt.setInventory(ImageInventory.valueOf(self)); bus.publish(evt); }
private void handle(APIUpdateImageMsg msg) { boolean update = false; if (msg.getName() != null) { self.setName(msg.getName()); update = true; } if (msg.getDescription() != null) { self.setDescription(msg.getDescription()); update = true; } if (msg.getSystem() != null) { self.setSystem(msg.getSystem()); update = true; } if (msg.getGuestOsType() != null) { self.setGuestOsType(msg.getGuestOsType()); update = true; } if (msg.getMediaType() != null) { self.setMediaType(ImageMediaType.valueOf(msg.getMediaType())); update = true; } if (msg.getFormat() != null) { self.setFormat(msg.getFormat()); update = true; } if (msg.getPlatform() != null) { self.setPlatform(ImagePlatform.valueOf(msg.getPlatform())); update = true; } if (update) { self = dbf.updateAndRefresh(self); } APIUpdateImageEvent evt = new APIUpdateImageEvent(msg.getId()); evt.setInventory(getSelfInventory()); bus.publish(evt); }
private void handle(final APIExpungeImageMsg msg) { List<String> bsUuids = new ArrayList<String>(); if (msg.getBackupStorageUuids() == null || msg.getBackupStorageUuids().isEmpty()) { bsUuids = CollectionUtils.transformToList( self.getBackupStorageRefs(), new Function<String, ImageBackupStorageRefVO>() { @Override public String call(ImageBackupStorageRefVO arg) { return ImageStatus.Deleted == arg.getStatus() ? arg.getBackupStorageUuid() : null; } }); if (bsUuids.isEmpty()) { throw new OperationFailureException( errf.stringToOperationError( String.format( "the image[uuid:%s, name:%s] is not deleted on any backup storage", self.getUuid(), self.getName()))); } } else { for (final String bsUuid : msg.getBackupStorageUuids()) { ImageBackupStorageRefVO ref = CollectionUtils.find( self.getBackupStorageRefs(), new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() { @Override public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) { return arg.getBackupStorageUuid().equals(bsUuid) ? arg : null; } }); if (ref == null) { throw new OperationFailureException( errf.stringToInvalidArgumentError( String.format( "the image[uuid:%s, name:%s] is not on the backup storage[uuid:%s]", self.getUuid(), self.getName(), bsUuid))); } if (ref.getStatus() != ImageStatus.Deleted) { throw new OperationFailureException( errf.stringToInvalidArgumentError( String.format( "the image[uuid:%s, name:%s] is not deleted on the backup storage[uuid:%s]", self.getUuid(), self.getName(), bsUuid))); } bsUuids.add(bsUuid); } } List<ExpungeImageMsg> emsgs = CollectionUtils.transformToList( bsUuids, new Function<ExpungeImageMsg, String>() { @Override public ExpungeImageMsg call(String arg) { ExpungeImageMsg emsg = new ExpungeImageMsg(); emsg.setBackupStorageUuid(arg); emsg.setImageUuid(self.getUuid()); bus.makeTargetServiceIdByResourceUuid( emsg, ImageConstant.SERVICE_ID, self.getUuid()); return emsg; } }); final List<String> finalBsUuids = bsUuids; final APIExpungeImageEvent evt = new APIExpungeImageEvent(msg.getId()); bus.send( emsgs, new CloudBusListCallBack(msg) { @Override public void run(List<MessageReply> replies) { for (MessageReply r : replies) { if (!r.isSuccess()) { String bsUuid = finalBsUuids.get(replies.indexOf(r)); // TODO logger.warn( String.format( "failed to expunge the image[uuid:%s, name:%s] on the backup storage[uuid:%s]" + ", %s", self.getUuid(), self.getName(), bsUuid, r.getError())); } } bus.publish(evt); } }); }
private void handle(APIRecoverImageMsg msg) { List<String> toRecoverBsUuids; if (msg.getBackupStorageUuids() == null || msg.getBackupStorageUuids().isEmpty()) { toRecoverBsUuids = CollectionUtils.transformToList( self.getBackupStorageRefs(), new Function<String, ImageBackupStorageRefVO>() { @Override public String call(ImageBackupStorageRefVO arg) { return arg.getStatus() == ImageStatus.Deleted ? arg.getBackupStorageUuid() : null; } }); if (toRecoverBsUuids.isEmpty()) { throw new OperationFailureException( errf.stringToOperationError( String.format( "the image[uuid:%s, name:%s] is not deleted on any backup storage", self.getUuid(), self.getName()))); } } else { toRecoverBsUuids = new ArrayList<String>(); for (final String bsUuid : msg.getBackupStorageUuids()) { ImageBackupStorageRefVO ref = CollectionUtils.find( self.getBackupStorageRefs(), new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() { @Override public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) { return bsUuid.equals(arg.getBackupStorageUuid()) ? arg : null; } }); if (ref == null) { throw new OperationFailureException( errf.stringToInvalidArgumentError( String.format( "the image[uuid:%s, name:%s] is not on the backup storage[uuid:%s]", self.getUuid(), self.getName(), bsUuid))); } if (ref.getStatus() != ImageStatus.Deleted) { throw new OperationFailureException( errf.stringToInvalidArgumentError( String.format( "the image[uuid:%s, name:%s]'s status[%s] is not Deleted on the backup storage[uuid:%s]", self.getUuid(), self.getName(), ref.getStatus(), bsUuid))); } toRecoverBsUuids.add(bsUuid); } } for (ImageBackupStorageRefVO ref : self.getBackupStorageRefs()) { if (toRecoverBsUuids.contains(ref.getBackupStorageUuid())) { ref.setStatus(ImageStatus.Ready); dbf.update(ref); } } self.setStatus(ImageStatus.Ready); self = dbf.updateAndRefresh(self); logger.debug( String.format( "successfully recovered the image[uuid:%s, name:%s] on the backup storage%s", self.getUuid(), self.getName(), toRecoverBsUuids)); APIRecoverImageEvent evt = new APIRecoverImageEvent(msg.getId()); evt.setInventory(getSelfInventory()); bus.publish(evt); }
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(); }
@Override protected void startVmFromNewCreate( final StartNewCreatedVmInstanceMsg msg, final SyncTaskChain taskChain) { boolean callNext = true; try { refreshVO(); ErrorCode allowed = validateOperationByState(msg, self.getState(), null); if (allowed != null) { bus.replyErrorByMessageType(msg, allowed); return; } ErrorCode preCreated = extEmitter.preStartNewCreatedVm(msg.getVmInstanceInventory()); if (preCreated != null) { bus.replyErrorByMessageType(msg, preCreated); return; } StartNewCreatedApplianceVmMsg smsg = (StartNewCreatedApplianceVmMsg) msg; ApplianceVmSpec aspec = smsg.getApplianceVmSpec(); final VmInstanceSpec spec = new VmInstanceSpec(); spec.setVmInventory(msg.getVmInstanceInventory()); if (msg.getL3NetworkUuids() != null && !msg.getL3NetworkUuids().isEmpty()) { SimpleQuery<L3NetworkVO> nwquery = dbf.createQuery(L3NetworkVO.class); nwquery.add(L3NetworkVO_.uuid, SimpleQuery.Op.IN, msg.getL3NetworkUuids()); List<L3NetworkVO> vos = nwquery.list(); List<L3NetworkInventory> nws = L3NetworkInventory.valueOf(vos); spec.setL3Networks(nws); } else { spec.setL3Networks(new ArrayList<L3NetworkInventory>(0)); } if (msg.getDataDiskOfferingUuids() != null && !msg.getDataDiskOfferingUuids().isEmpty()) { SimpleQuery<DiskOfferingVO> dquery = dbf.createQuery(DiskOfferingVO.class); dquery.add(DiskOfferingVO_.uuid, SimpleQuery.Op.IN, msg.getDataDiskOfferingUuids()); List<DiskOfferingVO> vos = dquery.list(); // allow create multiple data volume from the same disk offering List<DiskOfferingInventory> disks = new ArrayList<DiskOfferingInventory>(); for (final String duuid : msg.getDataDiskOfferingUuids()) { DiskOfferingVO dvo = CollectionUtils.find( vos, new Function<DiskOfferingVO, DiskOfferingVO>() { @Override public DiskOfferingVO call(DiskOfferingVO arg) { if (duuid.equals(arg.getUuid())) { return arg; } return null; } }); disks.add(DiskOfferingInventory.valueOf(dvo)); } spec.setDataDiskOfferings(disks); } else { spec.setDataDiskOfferings(new ArrayList<DiskOfferingInventory>(0)); } ImageVO imvo = dbf.findByUuid(spec.getVmInventory().getImageUuid(), ImageVO.class); spec.getImageSpec().setInventory(ImageInventory.valueOf(imvo)); spec.putExtensionData(ApplianceVmConstant.Params.applianceVmSpec.toString(), aspec); spec.setCurrentVmOperation(VmInstanceConstant.VmOperation.NewCreate); spec.putExtensionData( ApplianceVmConstant.Params.applianceVmSubType.toString(), getSelf().getApplianceVmType()); changeVmStateInDb(VmInstanceStateEvent.starting); extEmitter.beforeStartNewCreatedVm(VmInstanceInventory.valueOf(self)); FlowChain chain = apvmf.getCreateApplianceVmWorkFlowBuilder().build(); chain.setName(String.format("create-appliancevm-%s", msg.getVmInstanceUuid())); chain.getData().put(VmInstanceConstant.Params.VmInstanceSpec.toString(), spec); chain .getData() .put( ApplianceVmConstant.Params.applianceVmFirewallRules.toString(), aspec.getFirewallRules()); addBootstrapFlows( chain, VolumeFormat.getMasterHypervisorTypeByVolumeFormat(imvo.getFormat())); List<Flow> subCreateFlows = getPostCreateFlows(); if (subCreateFlows != null) { for (Flow f : subCreateFlows) { chain.then(f); } } chain.then( new NoRollbackFlow() { String __name__ = "change-appliancevm-status-to-connected"; @Override public void run(FlowTrigger trigger, Map data) { // must reload here, otherwise it will override changes created by previous flows self = dbf.reload(self); getSelf().setStatus(ApplianceVmStatus.Connected); dbf.update(self); trigger.next(); } }); boolean noRollbackOnFailure = ApplianceVmGlobalProperty.NO_ROLLBACK_ON_POST_FAILURE; chain.noRollback(noRollbackOnFailure); chain .done( new FlowDoneHandler(msg, taskChain) { @Override public void handle(Map data) { VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); self = dbf.reload(self); self.setLastHostUuid(spec.getDestHost().getUuid()); self.setHostUuid(spec.getDestHost().getUuid()); self.setClusterUuid(spec.getDestHost().getClusterUuid()); self.setZoneUuid(spec.getDestHost().getZoneUuid()); self.setHypervisorType(spec.getDestHost().getHypervisorType()); self.setRootVolumeUuid(spec.getDestRootVolume().getUuid()); changeVmStateInDb(VmInstanceStateEvent.running); logger.debug( String.format( "appliance vm[uuid:%s, name: %s, type:%s] is running ..", self.getUuid(), self.getName(), getSelf().getApplianceVmType())); VmInstanceInventory inv = VmInstanceInventory.valueOf(self); extEmitter.afterStartNewCreatedVm(inv); StartNewCreatedVmInstanceReply reply = new StartNewCreatedVmInstanceReply(); reply.setVmInventory(inv); bus.reply(msg, reply); taskChain.next(); } }) .error( new FlowErrorHandler(msg, taskChain) { @Override public void handle(ErrorCode errCode, Map data) { extEmitter.failedToStartNewCreatedVm(VmInstanceInventory.valueOf(self), errCode); dbf.remove(self); StartNewCreatedVmInstanceReply reply = new StartNewCreatedVmInstanceReply(); reply.setError(errCode); reply.setSuccess(false); bus.reply(msg, reply); taskChain.next(); } }) .start(); callNext = false; } finally { if (callNext) { taskChain.next(); } } }