package org.zstack.network.l3;
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.Platform;
import org.zstack.core.cascade.CascadeConstant;
import org.zstack.core.cascade.CascadeFacade;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.cloudbus.CloudBusCallBack;
import org.zstack.core.componentloader.PluginRegistry;
import org.zstack.core.db.*;
import org.zstack.core.db.SimpleQuery.Op;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.core.workflow.*;
import org.zstack.header.core.Completion;
import org.zstack.header.core.NopeCompletion;
import org.zstack.header.core.workflow.*;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.errorcode.SysErrors;
import org.zstack.header.message.*;
import org.zstack.header.network.l3.*;
import org.zstack.header.network.service.*;
import org.zstack.identity.AccountManager;
import org.zstack.tag.TagManager;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.data.FieldPrinter;
import org.zstack.utils.function.ForEachFunction;
import org.zstack.utils.function.Function;
import org.zstack.utils.gson.JSONObjectUtil;
import org.zstack.utils.logging.CLogger;
import org.zstack.utils.network.NetworkUtils;
import javax.persistence.Tuple;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class L3BasicNetwork implements L3Network {
private static final CLogger logger = Utils.getLogger(L3BasicNetwork.class);
private static final FieldPrinter printer = Utils.getFieldPrinter();
@Autowired
protected L3NetworkExtensionPointEmitter extpEmitter;
@Autowired
protected CloudBus bus;
@Autowired
protected DatabaseFacade dbf;
@Autowired
protected L3NetworkManager l3NwMgr;
@Autowired
protected AccountManager acntMgr;
@Autowired
protected CascadeFacade casf;
@Autowired
protected ErrorFacade errf;
@Autowired
protected TagManager tagMgr;
@Autowired
protected PluginRegistry pluginRgty;
private L3NetworkVO self;
public L3BasicNetwork(L3NetworkVO vo) {
this.self = vo;
}
protected L3NetworkVO getSelf() {
return self;
}
protected L3NetworkInventory getSelfInventory() {
return L3NetworkInventory.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);
}
}
@Override
public void deleteHook() {
}
private IpRangeInventory createIpRange(APICreateMessage msg, IpRangeInventory ipr) {
IpRangeVO vo = new SQLBatchWithReturn<IpRangeVO>() {
@Override
protected IpRangeVO scripts() {
IpRangeVO vo = new IpRangeVO();
vo.setUuid(ipr.getUuid() == null ? Platform.getUuid() : ipr.getUuid());
vo.setDescription(ipr.getDescription());
vo.setEndIp(ipr.getEndIp());
vo.setGateway(ipr.getGateway());
vo.setL3NetworkUuid(ipr.getL3NetworkUuid());
vo.setName(ipr.getName());
vo.setNetmask(ipr.getNetmask());
vo.setStartIp(ipr.getStartIp());
vo.setNetworkCidr(ipr.getNetworkCidr());
dbf.getEntityManager().persist(vo);
dbf.getEntityManager().flush();
dbf.getEntityManager().refresh(vo);
acntMgr.createAccountResourceRef(msg.getSession().getAccountUuid(), vo.getUuid(), IpRangeVO.class);
return vo;
}
}.execute();
tagMgr.createTagsFromAPICreateMessage(msg, vo.getUuid(), IpRangeVO.class.getSimpleName());
IpRangeInventory inv = IpRangeInventory.valueOf(vo);
logger.debug(String.format("Successfully added ip range: %s", JSONObjectUtil.toJsonString(inv)));
return inv;
}
private void handle(APIAddIpRangeMsg msg) {
IpRangeInventory ipr = IpRangeInventory.fromMessage(msg);
ipr = createIpRange(msg, ipr);
final IpRangeInventory finalIpr = ipr;
CollectionUtils.safeForEach(pluginRgty.getExtensionList(AfterAddIpRangeExtensionPoint.class), new ForEachFunction<AfterAddIpRangeExtensionPoint>() {
@Override
public void run(AfterAddIpRangeExtensionPoint ext) {
ext.afterAddIpRange(finalIpr);
}
});
APIAddIpRangeEvent evt = new APIAddIpRangeEvent(msg.getId());
evt.setInventory(ipr);
bus.publish(evt);
}
private void handleLocalMessage(Message msg) {
if (msg instanceof AllocateIpMsg) {
handle((AllocateIpMsg)msg);
} else if (msg instanceof ReturnIpMsg) {
handle((ReturnIpMsg)msg);
} else if (msg instanceof L3NetworkDeletionMsg) {
handle((L3NetworkDeletionMsg) msg);
} else if (msg instanceof IpRangeDeletionMsg) {
handle((IpRangeDeletionMsg) msg);
} else if (msg instanceof CheckIpAvailabilityMsg) {
handle((CheckIpAvailabilityMsg) msg);
} else {
bus.dealWithUnknownMessage(msg);
}
}
private void handle(CheckIpAvailabilityMsg msg) {
CheckIpAvailabilityReply reply = new CheckIpAvailabilityReply();
reply.setAvailable(checkIpAvailability(msg.getIp()));
bus.reply(msg, reply);
}
private void handle(IpRangeDeletionMsg msg) {
IpRangeDeletionReply reply = new IpRangeDeletionReply();
List<IpRangeDeletionExtensionPoint> exts = pluginRgty.getExtensionList(IpRangeDeletionExtensionPoint.class);
IpRangeVO iprvo = dbf.findByUuid(msg.getIpRangeUuid(), IpRangeVO.class);
if (iprvo == null) {
bus.reply(msg, reply);
return;
}
final IpRangeInventory inv = IpRangeInventory.valueOf(iprvo);
for (IpRangeDeletionExtensionPoint ext : exts) {
ext.preDeleteIpRange(inv);
}
CollectionUtils.safeForEach(exts, new ForEachFunction<IpRangeDeletionExtensionPoint>() {
@Override
public void run(IpRangeDeletionExtensionPoint arg) {
arg.beforeDeleteIpRange(inv);
}
});
dbf.remove(iprvo);
CollectionUtils.safeForEach(exts, new ForEachFunction<IpRangeDeletionExtensionPoint>() {
@Override
public void run(IpRangeDeletionExtensionPoint arg) {
arg.afterDeleteIpRange(inv);
}
});
bus.reply(msg, reply);
}
private void handle(L3NetworkDeletionMsg msg) {
L3NetworkInventory inv = L3NetworkInventory.valueOf(self);
extpEmitter.beforeDelete(inv);
deleteHook();
extpEmitter.afterDelete(inv);
L3NetworkDeletionReply reply = new L3NetworkDeletionReply();
bus.reply(msg, reply);
}
private void handle(ReturnIpMsg msg) {
ReturnIpReply reply = new ReturnIpReply();
SQL.New(UsedIpVO.class).eq(UsedIpVO_.uuid, msg.getUsedIpUuid()).hardDelete();
logger.debug(String.format("Successfully released used ip[%s]", msg.getUsedIpUuid()));
bus.reply(msg, reply);
}
private void handle(AllocateIpMsg msg) {
IpAllocatorType strategyType = msg.getAllocatorStrategy() == null ? RandomIpAllocatorStrategy.type : IpAllocatorType.valueOf(msg.getAllocatorStrategy());
IpAllocatorStrategy ias = l3NwMgr.getIpAllocatorStrategy(strategyType);
AllocateIpReply reply = new AllocateIpReply();
UsedIpInventory ip = ias.allocateIp(msg);
if (ip == null) {
reply.setError(errf.instantiateErrorCode(L3Errors.ALLOCATE_IP_ERROR, String.format("IP allocator strategy[%s] returns nothing, because no ip is available in this l3Network[name:%s, uuid:%s]", strategyType, self.getName(), self.getUuid())));
} else {
logger.debug(String.format("Ip allocator strategy[%s] successfully allocates an ip[%s]", strategyType, printer.print(ip)));
reply.setIpInventory(ip);
}
bus.reply(msg, reply);
}
private void handleApiMessage(APIMessage msg) {
if (msg instanceof APIDeleteL3NetworkMsg) {
handle((APIDeleteL3NetworkMsg) msg);
} else if (msg instanceof APIDeleteIpRangeMsg) {
handle((APIDeleteIpRangeMsg)msg);
} else if (msg instanceof APIAddIpRangeMsg) {
handle((APIAddIpRangeMsg) msg);
} else if (msg instanceof APIAttachNetworkServiceToL3NetworkMsg) {
handle((APIAttachNetworkServiceToL3NetworkMsg) msg);
} else if (msg instanceof APIDetachNetworkServiceFromL3NetworkMsg) {
handle((APIDetachNetworkServiceFromL3NetworkMsg) msg);
} else if (msg instanceof APIAddDnsToL3NetworkMsg) {
handle((APIAddDnsToL3NetworkMsg)msg);
} else if (msg instanceof APIRemoveDnsFromL3NetworkMsg) {
handle((APIRemoveDnsFromL3NetworkMsg) msg);
} else if (msg instanceof APIChangeL3NetworkStateMsg) {
handle((APIChangeL3NetworkStateMsg) msg);
} else if (msg instanceof APIAddIpRangeByNetworkCidrMsg) {
handle((APIAddIpRangeByNetworkCidrMsg) msg);
} else if (msg instanceof APIUpdateL3NetworkMsg) {
handle((APIUpdateL3NetworkMsg) msg);
} else if (msg instanceof APIGetFreeIpMsg) {
handle((APIGetFreeIpMsg) msg);
} else if (msg instanceof APIUpdateIpRangeMsg) {
handle((APIUpdateIpRangeMsg) msg);
} else if (msg instanceof APICheckIpAvailabilityMsg) {
handle((APICheckIpAvailabilityMsg) msg);
} else {
bus.dealWithUnknownMessage(msg);
}
}
protected boolean checkIpAvailability(String ip) {
SimpleQuery<IpRangeVO> rq = dbf.createQuery(IpRangeVO.class);
rq.select(IpRangeVO_.startIp, IpRangeVO_.endIp, IpRangeVO_.gateway);
rq.add(IpRangeVO_.l3NetworkUuid, Op.EQ, self.getUuid());
List<Tuple> ts = rq.listTuple();
boolean inRange = false;
boolean isGateway = false;
for (Tuple t : ts) {
String sip = t.get(0, String.class);
String eip = t.get(1, String.class);
String gw = t.get(2, String.class);
if (ip.equals(gw)) {
isGateway = true;
break;
}
if (NetworkUtils.isIpv4InRange(ip, sip, eip)) {
inRange = true;
break;
}
}
if (!inRange || isGateway) {
// not an IP of this L3 or is a gateway
return false;
} else {
SimpleQuery<UsedIpVO> q = dbf.createQuery(UsedIpVO.class);
q.add(UsedIpVO_.l3NetworkUuid, Op.EQ, self.getUuid());
q.add(UsedIpVO_.ip, Op.EQ, ip);
return !q.isExists();
}
}
private void handle(APICheckIpAvailabilityMsg msg) {
APICheckIpAvailabilityReply reply = new APICheckIpAvailabilityReply();
reply.setAvailable(checkIpAvailability(msg.getIp()));
bus.reply(msg, reply);
}
private void handle(APIDetachNetworkServiceFromL3NetworkMsg msg) {
for (Map.Entry<String, List<String>> e : msg.getNetworkServices().entrySet()) {
SimpleQuery<NetworkServiceL3NetworkRefVO> q = dbf.createQuery(NetworkServiceL3NetworkRefVO.class);
q.add(NetworkServiceL3NetworkRefVO_.networkServiceProviderUuid, Op.EQ, e.getKey());
q.add(NetworkServiceL3NetworkRefVO_.l3NetworkUuid, Op.EQ, self.getUuid());
q.add(NetworkServiceL3NetworkRefVO_.networkServiceType, Op.IN, e.getValue());
List<NetworkServiceL3NetworkRefVO> refs = q.list();
if (refs.isEmpty()) {
logger.warn(String.format("no network service references found for the provider[uuid:%s] and L3 network[uuid:%s]",
e.getKey(), self.getUuid()));
} else {
dbf.removeCollection(refs, NetworkServiceL3NetworkRefVO.class);
}
logger.debug(String.format("successfully detached network service provider[uuid:%s] to l3network[uuid:%s, name:%s] with services%s", e.getKey(), self.getUuid(), self.getName(), e.getValue()));
}
self = dbf.reload(self);
APIDetachNetworkServiceFromL3NetworkEvent evt = new APIDetachNetworkServiceFromL3NetworkEvent(msg.getId());
evt.setInventory(L3NetworkInventory.valueOf(self));
bus.publish(evt);
}
private void handle(APIUpdateIpRangeMsg msg) {
IpRangeVO vo = dbf.findByUuid(msg.getUuid(), IpRangeVO.class);
boolean update = false;
if (msg.getName() != null) {
vo.setName(msg.getName());
update = true;
}
if (msg.getDescription() != null) {
vo.setDescription(msg.getDescription());
update = true;
}
if (update) {
vo = dbf.updateAndRefresh(vo);
}
APIUpdateIpRangeEvent evt = new APIUpdateIpRangeEvent(msg.getId());
evt.setInventory(IpRangeInventory.valueOf(vo));
bus.publish(evt);
}
private List<FreeIpInventory> getFreeIp(final IpRangeVO ipr, int limit, String start) {
SimpleQuery<UsedIpVO> q = dbf.createQuery(UsedIpVO.class);
q.select(UsedIpVO_.ip);
q.add(UsedIpVO_.ipRangeUuid, Op.EQ, ipr.getUuid());
List<String> used = q.listValue();
List<String> spareIps = NetworkUtils.getFreeIpInRange(ipr.getStartIp(), ipr.getEndIp(), used, limit, start);
return CollectionUtils.transformToList(spareIps, new Function<FreeIpInventory, String>() {
@Override
public FreeIpInventory call(String arg) {
FreeIpInventory f = new FreeIpInventory();
f.setGateway(ipr.getGateway());
f.setIp(arg);
f.setNetmask(ipr.getNetmask());
f.setIpRangeUuid(ipr.getUuid());
return f;
}
});
}
private void handle(APIGetFreeIpMsg msg) {
APIGetFreeIpReply reply = new APIGetFreeIpReply();
if (msg.getIpRangeUuid() != null) {
final IpRangeVO ipr = dbf.findByUuid(msg.getIpRangeUuid(), IpRangeVO.class);
List<FreeIpInventory> free = getFreeIp(ipr, msg.getLimit(),msg.getStart());
reply.setInventories(free);
} else {
SimpleQuery<IpRangeVO> q = dbf.createQuery(IpRangeVO.class);
q.add(IpRangeVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
List<IpRangeVO> iprs = q.list();
List<FreeIpInventory> res = new ArrayList<FreeIpInventory>();
int limit = msg.getLimit();
for (IpRangeVO ipr : iprs) {
List<FreeIpInventory> i = getFreeIp(ipr, limit,msg.getStart());
res.addAll(i);
if (res.size() >= msg.getLimit()) {
break;
}
limit -= res.size();
}
reply.setInventories(res);
}
bus.reply(msg, reply);
}
private void handle(APIUpdateL3NetworkMsg 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 (update) {
self = dbf.updateAndRefresh(self);
}
APIUpdateL3NetworkEvent evt = new APIUpdateL3NetworkEvent(msg.getId());
evt.setInventory(getSelfInventory());
bus.publish(evt);
}
private void handle(APIAddIpRangeByNetworkCidrMsg msg) {
IpRangeInventory ipr = IpRangeInventory.fromMessage(msg);
ipr = createIpRange(msg, ipr);
APIAddIpRangeByNetworkCidrEvent evt = new APIAddIpRangeByNetworkCidrEvent(msg.getId());
evt.setInventory(ipr);
bus.publish(evt);
}
private void handle(APIChangeL3NetworkStateMsg msg) {
if (L3NetworkStateEvent.enable.toString().equals(msg.getStateEvent())) {
self.setState(L3NetworkState.Enabled);
} else {
self.setState(L3NetworkState.Disabled);
}
self = dbf.updateAndRefresh(self);
APIChangeL3NetworkStateEvent evt = new APIChangeL3NetworkStateEvent(msg.getId());
evt.setInventory(L3NetworkInventory.valueOf(self));
bus.publish(evt);
}
private void handle(final APIRemoveDnsFromL3NetworkMsg msg) {
final APIRemoveDnsFromL3NetworkEvent evt = new APIRemoveDnsFromL3NetworkEvent(msg.getId());
FlowChain chain = FlowChainBuilder.newShareFlowChain();
chain.setName(String.format("remove-dns-%s-from-l3-%s", msg.getDns(), msg.getL3NetworkUuid()));
chain.then(new ShareFlow() {
@Override
public void setup() {
if (!self.getNetworkServices().isEmpty()) {
flow(new NoRollbackFlow() {
String __name__ = "remove-dns-from-backend";
@Override
public void run(final FlowTrigger trigger, Map data) {
RemoveDnsMsg rmsg = new RemoveDnsMsg();
rmsg.setDns(msg.getDns());
rmsg.setL3NetworkUuid(self.getUuid());
bus.makeLocalServiceId(rmsg, NetworkServiceConstants.DNS_SERVICE_ID);
bus.send(rmsg, new CloudBusCallBack(trigger) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
trigger.fail(reply.getError());
} else {
trigger.next();
}
}
});
}
});
}
flow(new NoRollbackFlow() {
String __name__ = "remove-dns-from-db";
@Override
public void run(FlowTrigger trigger, Map data) {
SimpleQuery<L3NetworkDnsVO> q = dbf.createQuery(L3NetworkDnsVO.class);
q.add(L3NetworkDnsVO_.dns, Op.EQ, msg.getDns());
q.add(L3NetworkDnsVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
L3NetworkDnsVO dns = q.find();
if (dns != null) {
//TODO: create extension points
dbf.remove(dns);
}
trigger.next();
}
});
done(new FlowDoneHandler(msg) {
@Override
public void handle(Map data) {
evt.setInventory(L3NetworkInventory.valueOf(dbf.reload(self)));
bus.publish(evt);
}
});
error(new FlowErrorHandler(msg) {
@Override
public void handle(ErrorCode errCode, Map data) {
evt.setError(errCode);
bus.publish(evt);
}
});
}
}).start();
}
private void handle(final APIAddDnsToL3NetworkMsg msg) {
final APIAddDnsToL3NetworkEvent evt = new APIAddDnsToL3NetworkEvent(msg.getId());
FlowChain chain = FlowChainBuilder.newShareFlowChain();
chain.setName(String.format("add-dns-%s-to-l3-%s", msg.getDns(), msg.getL3NetworkUuid()));
chain.then(new ShareFlow() {
@Override
public void setup() {
flow(new Flow() {
String __name__ = "write-dns-to-db";
L3NetworkDnsVO dnsvo;
boolean s = false;
@Override
public void run(FlowTrigger trigger, Map data) {
dnsvo = new L3NetworkDnsVO();
dnsvo.setDns(msg.getDns());
dnsvo.setL3NetworkUuid(self.getUuid());
dnsvo = dbf.persist(dnsvo);
s = true;
trigger.next();
}
@Override
public void rollback(FlowRollback trigger, Map data) {
if (s) {
dbf.remove(dnsvo);
}
trigger.rollback();
}
});
if (!self.getNetworkServices().isEmpty()) {
flow(new NoRollbackFlow() {
String __name__ = "apply-to-backend";
@Override
public void run(final FlowTrigger trigger, Map data) {
AddDnsMsg amsg = new AddDnsMsg();
amsg.setL3NetworkUuid(self.getUuid());
amsg.setDns(msg.getDns());
bus.makeLocalServiceId(amsg, NetworkServiceConstants.DNS_SERVICE_ID);
bus.send(amsg, new CloudBusCallBack(trigger) {
@Override
public void run(MessageReply reply) {
if (reply.isSuccess()) {
trigger.next();
} else {
trigger.fail(reply.getError());
}
}
});
}
});
}
done(new FlowDoneHandler(msg) {
@Override
public void handle(Map data) {
self = dbf.reload(self);
evt.setInventory(L3NetworkInventory.valueOf(self));
logger.debug(String.format("successfully added dns[%s] to L3Network[uuid:%s, name:%s]", msg.getDns(), self.getUuid(), self.getName()));
bus.publish(evt);
}
});
error(new FlowErrorHandler(msg) {
@Override
public void handle(ErrorCode errCode, Map data) {
evt.setError(errCode);
bus.publish(evt);
}
});
}
}).start();
}
private void handle(APIAttachNetworkServiceToL3NetworkMsg msg) {
for (Map.Entry<String, List<String>> e : msg.getNetworkServices().entrySet()) {
for (String nsType : e.getValue()) {
NetworkServiceL3NetworkRefVO ref = new NetworkServiceL3NetworkRefVO();
ref.setL3NetworkUuid(self.getUuid());
ref.setNetworkServiceProviderUuid(e.getKey());
ref.setNetworkServiceType(nsType);
dbf.persist(ref);
}
logger.debug(String.format("successfully attached network service provider[uuid:%s] to l3network[uuid:%s, name:%s] with services%s", e.getKey(), self.getUuid(), self.getName(), e.getValue()));
}
self = dbf.reload(self);
APIAttachNetworkServiceToL3NetworkEvent evt = new APIAttachNetworkServiceToL3NetworkEvent(msg.getId());
evt.setInventory(L3NetworkInventory.valueOf(self));
bus.publish(evt);
}
private void handle(APIDeleteIpRangeMsg msg) {
IpRangeVO vo = dbf.findByUuid(msg.getUuid(), IpRangeVO.class);
final APIDeleteIpRangeEvent evt = new APIDeleteIpRangeEvent(msg.getId());
final String issuer = IpRangeVO.class.getSimpleName();
final List<IpRangeInventory> ctx = IpRangeInventory.valueOf(Arrays.asList(vo));
FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
chain.setName(String.format("delete-ip-range-%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.setError(errf.instantiateErrorCode(SysErrors.DELETE_RESOURCE_ERROR, errCode));
bus.publish(evt);
}
}).start();
}
private void handle(APIDeleteL3NetworkMsg msg) {
final APIDeleteL3NetworkEvent evt = new APIDeleteL3NetworkEvent(msg.getId());
final String issuer = L3NetworkVO.class.getSimpleName();
final List<L3NetworkInventory> ctx = L3NetworkInventory.valueOf(Arrays.asList(self));
FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
chain.setName(String.format("delete-l3-network-%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.setError(errf.instantiateErrorCode(SysErrors.DELETE_RESOURCE_ERROR, errCode));
bus.publish(evt);
}
}).start();
}
}