package org.zstack.network.service.vip; import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.cascade.AbstractAsyncCascadeExtension; import org.zstack.core.cascade.CascadeAction; import org.zstack.core.cascade.CascadeConstant; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusListCallBack; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.SimpleQuery; import org.zstack.core.db.SimpleQuery.Op; import org.zstack.header.core.Completion; import org.zstack.header.message.MessageReply; import org.zstack.header.network.l3.IpRangeInventory; import org.zstack.header.network.l3.IpRangeVO; import org.zstack.header.network.l3.L3NetworkInventory; import org.zstack.header.network.l3.L3NetworkVO; import org.zstack.utils.CollectionUtils; import org.zstack.utils.Utils; import org.zstack.utils.function.Function; import org.zstack.utils.logging.CLogger; import java.util.Arrays; import java.util.List; /** */ public class VipCascadeExtension extends AbstractAsyncCascadeExtension { private static final CLogger logger = Utils.getLogger(VipCascadeExtension.class); private static final String NAME = VipVO.class.getSimpleName(); @Autowired private DatabaseFacade dbf; @Autowired private CloudBus bus; public void asyncCascade(CascadeAction action, Completion completion) { if (action.isActionCode(CascadeConstant.DELETION_CHECK_CODE)) { handleDeletionCheck(action, completion); } else if (action.isActionCode(CascadeConstant.DELETION_DELETE_CODE, CascadeConstant.DELETION_FORCE_DELETE_CODE)) { handleDeletion(action, completion); } else if (action.isActionCode(CascadeConstant.DELETION_CLEANUP_CODE)) { handleDeletionCleanup(action, completion); } else { completion.success(); } } private void handleDeletionCleanup(CascadeAction action, Completion completion) { dbf.eoCleanup(VipVO.class); completion.success(); } private void handleDeletion(CascadeAction action, final Completion completion) { final List<VipInventory> vipinvs = vipFromAction(action); if (vipinvs == null || vipinvs.isEmpty()) { completion.success(); return; } List<VipDeletionMsg> msgs = CollectionUtils.transformToList(vipinvs, new Function<VipDeletionMsg, VipInventory>() { @Override public VipDeletionMsg call(VipInventory arg) { VipDeletionMsg msg = new VipDeletionMsg(); msg.setVipUuid(arg.getUuid()); bus.makeTargetServiceIdByResourceUuid(msg, VipConstant.SERVICE_ID, msg.getVipUuid()); return msg; } }); bus.send(msgs, 10, new CloudBusListCallBack(completion) { @Override public void run(List<MessageReply> replies) { for (MessageReply r : replies) { VipInventory vip = vipinvs.get(replies.indexOf(r)); if (!r.isSuccess()) { logger.warn(String.format("failed to delete vip[uuid:%s, ip: %s, name:%s], %s", vip.getUuid(), vip.getIp(), vip.getName(), r.getError())); } } completion.success(); } }); } private void handleDeletionCheck(CascadeAction action, Completion completion) { completion.success(); } @Override public List<String> getEdgeNames() { return Arrays.asList(L3NetworkVO.class.getSimpleName(), IpRangeVO.class.getSimpleName()); } @Override public String getCascadeResourceName() { return NAME; } @Override public CascadeAction createActionForChildResource(CascadeAction action) { if (CascadeConstant.DELETION_CODES.contains(action.getActionCode())) { List<VipInventory> vips = vipFromAction(action); if (vips != null) { return action.copy().setParentIssuer(NAME).setParentIssuerContext(vips); } } return null; } private List<VipInventory> vipFromAction(CascadeAction action) { if (L3NetworkVO.class.getSimpleName().equals(action.getParentIssuer())) { List<String> l3Uuids = CollectionUtils.transformToList((List<L3NetworkInventory>) action.getParentIssuerContext(), new Function<String, L3NetworkInventory>() { @Override public String call(L3NetworkInventory arg) { return arg.getUuid(); } }); if (l3Uuids.isEmpty()) { return null; } SimpleQuery<VipVO> q = dbf.createQuery(VipVO.class); q.add(VipVO_.l3NetworkUuid, Op.IN, l3Uuids); List<VipVO> vipVOs = q.list(); return VipInventory.valueOf(vipVOs); } else if (IpRangeVO.class.getSimpleName().equals(action.getParentIssuer())) { List<String> iprUuids = CollectionUtils.transformToList((List<IpRangeInventory>) action.getParentIssuerContext(), new Function<String, IpRangeInventory>() { @Override public String call(IpRangeInventory arg) { return arg.getUuid(); } }); SimpleQuery<VipVO> q = dbf.createQuery(VipVO.class); q.add(VipVO_.ipRangeUuid, Op.IN, iprUuids); List<VipVO> vipVOs = q.list(); return VipInventory.valueOf(vipVOs); } else if (VipVO.class.getSimpleName().equals(action.getParentIssuer())) { return action.getParentIssuerContext(); } return null; } }