package org.zstack.network.l2.vxlan.vxlanNetwork; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.zstack.core.cascade.CascadeFacade; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusListCallBack; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.core.inventory.InventoryFacade; import org.zstack.core.workflow.FlowChainBuilder; import org.zstack.header.core.Completion; import org.zstack.header.core.workflow.*; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.host.HostConstant; import org.zstack.header.host.HostInventory; import org.zstack.header.host.HypervisorType; import org.zstack.header.message.APIMessage; import org.zstack.header.message.Message; import org.zstack.header.message.MessageReply; import org.zstack.header.network.l2.*; import org.zstack.network.l2.L2NetworkExtensionPointEmitter; import org.zstack.network.l2.L2NetworkManager; import org.zstack.network.l2.L2NoVlanNetwork; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import java.util.*; /** * Created by weiwang on 01/03/2017. */ @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class VxlanNetwork extends L2NoVlanNetwork { private static final CLogger logger = Utils.getLogger(VxlanNetwork.class); @Autowired protected L2NetworkExtensionPointEmitter extpEmitter; @Autowired protected CloudBus bus; @Autowired protected DatabaseFacade dbf; @Autowired protected L2NetworkManager l2Mgr; @Autowired protected InventoryFacade inventoryMgr; @Autowired protected CascadeFacade casf; @Autowired protected ErrorFacade errf; public VxlanNetwork(L2NetworkVO self) { super(self); } private VxlanNetworkVO getSelf() { return (VxlanNetworkVO) self; } @Override public void deleteHook() { } @Override protected L2NetworkInventory getSelfInventory() { return L2VxlanNetworkInventory.valueOf(getSelf()); } @Override public void handleMessage(Message msg) { try { if (msg instanceof APIMessage) { handleApiMessage((APIMessage) msg); } else { handleLocalMessage(msg); } } catch (Exception e) { bus.logExceptionWithMessageDump(msg, e); bus.replyErrorByMessageType(msg, e); } } private void handleLocalMessage(Message msg) { if (msg instanceof PrepareL2NetworkOnHostMsg) { handle((PrepareL2NetworkOnHostMsg) msg); } else if (msg instanceof L2NetworkDeletionMsg) { handle((L2NetworkDeletionMsg) msg); } else if (msg instanceof CheckL2NetworkOnHostMsg) { handle((CheckL2NetworkOnHostMsg) msg); } else if (msg instanceof L2NetworkMessage) { superHandle((L2NetworkMessage) msg); } else { bus.dealWithUnknownMessage(msg); } } private void handle(final PrepareL2NetworkOnHostMsg msg) { final PrepareL2NetworkOnHostReply reply = new PrepareL2NetworkOnHostReply(); prepareL2NetworkOnHosts(Arrays.asList(msg.getHost()), new Completion(msg) { @Override public void success() { bus.reply(msg, reply); } @Override public void fail(ErrorCode errorCode) { reply.setError(errorCode); bus.reply(msg, reply); } }); } private void prepareL2NetworkOnHosts(final List<HostInventory> hosts, final Completion completion) { FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName(String.format("prepare-l2-%s-on-hosts", self.getUuid())); chain.then(new NoRollbackFlow() { @Override public void run(final FlowTrigger trigger, Map data) { List<CheckL2NetworkOnHostMsg> cmsgs = new ArrayList<CheckL2NetworkOnHostMsg>(); for (HostInventory h : hosts) { CheckL2NetworkOnHostMsg cmsg = new CheckL2NetworkOnHostMsg(); cmsg.setHostUuid(h.getUuid()); cmsg.setL2NetworkUuid(self.getUuid()); bus.makeTargetServiceIdByResourceUuid(cmsg, L2NetworkConstant.SERVICE_ID, h.getUuid()); cmsgs.add(cmsg); } if (cmsgs.isEmpty()) { trigger.next(); return; } bus.send(cmsgs, new CloudBusListCallBack(trigger) { @Override public void run(List<MessageReply> replies) { for (MessageReply r : replies) { if (!r.isSuccess()) { trigger.fail(r.getError()); return; } } trigger.next(); } }); } }).then(new NoRollbackFlow() { private void realize(final Iterator<HostInventory> it, final FlowTrigger trigger) { if (!it.hasNext()) { trigger.next(); return; } HostInventory host = it.next(); realizeNetwork(host.getUuid(), host.getHypervisorType(), new Completion(trigger) { @Override public void success() { realize(it, trigger); } @Override public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } }); } @Override public void run(FlowTrigger trigger, Map data) { realize(hosts.iterator(), trigger); } }).done(new FlowDoneHandler(completion) { @Override public void handle(Map data) { completion.success(); } }).error(new FlowErrorHandler(completion) { @Override public void handle(ErrorCode errCode, Map data) { completion.fail(errCode); } }).start(); } protected void realizeNetwork(String hostUuid, String htype, Completion completion) { final HypervisorType hvType = HypervisorType.valueOf(htype); final L2NetworkType l2Type = L2NetworkType.valueOf(self.getType()); L2NetworkRealizationExtensionPoint ext = l2Mgr.getRealizationExtension(l2Type, hvType); ext.realize(getSelfInventory(), hostUuid, completion); } private void handle(final CheckL2NetworkOnHostMsg msg) { superHandle((L2NetworkMessage) msg); } private void handle(L2NetworkDeletionMsg msg) { L2NetworkInventory inv = L2NetworkInventory.valueOf(self); extpEmitter.beforeDelete(inv); deleteHook(); dbf.removeByPrimaryKey(msg.getL2NetworkUuid(), L2NetworkVO.class); extpEmitter.afterDelete(inv); L2NetworkDeletionReply reply = new L2NetworkDeletionReply(); bus.reply(msg, reply); } private void handleApiMessage(APIMessage msg) { if (msg instanceof APIAttachL2NetworkToClusterMsg) { handle((APIAttachL2NetworkToClusterMsg) msg); } else if (msg instanceof APIDetachL2NetworkFromClusterMsg) { handle((APIDetachL2NetworkFromClusterMsg) msg); } else if (msg instanceof L2NetworkMessage) { superHandle((L2NetworkMessage) msg); } else { bus.dealWithUnknownMessage(msg); } } private void handle(final APIDetachL2NetworkFromClusterMsg msg) { throw new CloudRuntimeException("VxlanNetwork can not detach from cluster which VxlanNetworkPool should be used"); } private void handle(final APIAttachL2NetworkToClusterMsg msg) { throw new CloudRuntimeException("VxlanNetwork can not attach to cluster which VxlanNetworkPool should be used"); } private void superHandle(L2NetworkMessage msg) { super.handleMessage((Message) msg); } }