package org.zstack.network.service; import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.SimpleQuery; import org.zstack.core.db.SimpleQuery.Op; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.header.errorcode.SysErrors; import org.zstack.header.apimediator.ApiMessageInterceptionException; import org.zstack.header.apimediator.ApiMessageInterceptor; import org.zstack.header.message.APIMessage; import org.zstack.header.network.service.*; import org.zstack.utils.CollectionUtils; import org.zstack.utils.function.Function; import static org.zstack.core.Platform.argerr; import static org.zstack.core.Platform.operr; import java.util.*; /** */ public class NetworkServiceApiInterceptor implements ApiMessageInterceptor { @Autowired private DatabaseFacade dbf; @Autowired private ErrorFacade errf; @Override public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException { if (msg instanceof APIAttachNetworkServiceToL3NetworkMsg) { validate((APIAttachNetworkServiceToL3NetworkMsg)msg); } return msg; } private void validate(APIAttachNetworkServiceToL3NetworkMsg msg) { if (msg.getNetworkServices().isEmpty()) { throw new ApiMessageInterceptionException(argerr("networkServices cannot be empty")); } SimpleQuery<NetworkServiceTypeVO> q = dbf.createQuery(NetworkServiceTypeVO.class); q.add(NetworkServiceTypeVO_.networkServiceProviderUuid, Op.IN, msg.getNetworkServices().keySet()); List<NetworkServiceTypeVO> vos = q.list(); Map<String, Set<String>> actual = new HashMap<String, Set<String>>(); for (NetworkServiceTypeVO vo : vos) { Set<String> types = actual.get(vo.getNetworkServiceProviderUuid()); if (types == null) { types = new HashSet<String>(); actual.put(vo.getNetworkServiceProviderUuid(), types); } types.add(vo.getType()); } for (Map.Entry<String, List<String>> e : msg.getNetworkServices().entrySet()) { String puuid = e.getKey(); List<String> types = e.getValue(); if (types == null || types.isEmpty()) { throw new ApiMessageInterceptionException(argerr("network service for provider[uuid:%s] must be specified", puuid)); } final Set<String> actualTypes = actual.get(puuid); if (actualTypes == null) { throw new ApiMessageInterceptionException(argerr("cannot find network service provider[uuid:%s] or it provides no services", puuid)); } if (!actualTypes.containsAll(types)) { List<String> notSupported = CollectionUtils.transformToList(types, new Function<String, String>() { @Override public String call(String type) { if (!actualTypes.contains(type)) { return type; } return null; } }); throw new ApiMessageInterceptionException(argerr("network service provider[uuid:%s] doesn't provide services%s", puuid, notSupported)); } } SimpleQuery<NetworkServiceL3NetworkRefVO> nwsq = dbf.createQuery(NetworkServiceL3NetworkRefVO.class); nwsq.select(NetworkServiceL3NetworkRefVO_.networkServiceType); nwsq.add(NetworkServiceL3NetworkRefVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid()); List<String> existingNwsTypes = nwsq.listValue(); for (List<String> types : msg.getNetworkServices().values()) { for (String type : types) { if (existingNwsTypes.contains(type)) { throw new ApiMessageInterceptionException(operr("there has been a network service[%s] attached to L3 network[uuid:%s]", type, msg.getL3NetworkUuid())); } } } } }