// // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // package com.cloud.network.element; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; import org.apache.commons.net.util.SubnetUtils; import com.cloud.agent.AgentManager; import com.cloud.agent.api.BcfAnswer; import com.cloud.agent.api.UpdateBcfRouterCommand; import com.cloud.agent.api.CreateBcfAttachmentCommand; import com.cloud.agent.api.CreateBcfStaticNatCommand; import com.cloud.agent.api.DeleteBcfAttachmentCommand; import com.cloud.agent.api.DeleteBcfStaticNatCommand; import com.cloud.agent.api.StartupBigSwitchBcfCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.api.ApiDBUtils; import com.cloud.api.commands.AddBigSwitchBcfDeviceCmd; import com.cloud.api.commands.DeleteBigSwitchBcfDeviceCmd; import com.cloud.api.commands.ListBigSwitchBcfDevicesCmd; import com.cloud.api.commands.BcfConstants; import com.cloud.api.response.BigSwitchBcfDeviceResponse; import com.cloud.configuration.ConfigurationManager; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.DetailVO; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.BigSwitchBcfDeviceVO; import com.cloud.network.IpAddressManager; import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PublicIpAddress; import com.cloud.network.bigswitch.AclData; import com.cloud.network.bigswitch.BigSwitchBcfApi; import com.cloud.network.bigswitch.BigSwitchBcfUtils; import com.cloud.network.bigswitch.TopologyData; import com.cloud.network.dao.BigSwitchBcfDao; import com.cloud.network.dao.FirewallRulesCidrsDao; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.resource.BigSwitchBcfResource; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.StaticNat; import com.cloud.network.vpc.NetworkACLItem; import com.cloud.network.vpc.NetworkACLItemCidrsDao; import com.cloud.network.vpc.NetworkACLItemDao; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.offering.NetworkOffering; import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.TransactionCallback; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.VMInstanceDao; /** * BigSwitchBcfElement is responsible for creating and plugging a nic into a BCF Segment network. * When a VM is created and needs to be plugged into a BCF Segment network, BigSwitchBcfElement is * called by NetworkOrchestrator to create a "port" and an "attachment" for each nic, and * register them with the controller to be plugged into the corresponding network. It also * removes them when the VM is destroyed. */ @Component public class BigSwitchBcfElement extends AdapterBase implements BigSwitchBcfElementService, ConnectivityProvider, IpDeployer, SourceNatServiceProvider, StaticNatServiceProvider, NetworkACLServiceProvider, FirewallServiceProvider, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(BigSwitchBcfElement.class); private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities(); @Inject ResourceManager _resourceMgr; @Inject PhysicalNetworkDao _physicalNetworkDao; @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; @Inject BigSwitchBcfDao _bigswitchBcfDao; @Inject HostDetailsDao _hostDetailsDao; @Inject HostDao _hostDao; @Inject AgentManager _agentMgr; @Inject NetworkDao _networkDao; @Inject DomainRouterDao _routerDao; @Inject NicDao _nicDao; @Inject VMInstanceDao _vmDao; @Inject AccountDao _accountDao; @Inject VpcDao _vpcDao; @Inject NetworkModel _networkModel; @Inject ConfigurationManager _configMgr; @Inject NetworkServiceMapDao _ntwkSrvcDao; @Inject DataCenterDao _zoneDao; @Inject IPAddressDao _ipAddressDao; @Inject IpAddressManager _ipAddrMgr; @Inject VlanDao _vlanDao; @Inject FirewallRulesDao _fwRulesDao; @Inject FirewallRulesCidrsDao _fwCidrsDao; @Inject NetworkACLItemDao _aclItemDao; @Inject NetworkACLItemCidrsDao _aclItemCidrsDao; private BigSwitchBcfUtils _bcfUtils = null; @Override public Map<Service, Map<Capability, String>> getCapabilities() { return capabilities; } @Override public Provider getProvider() { return Provider.BigSwitchBcf; } private boolean canHandle(Network network, Service service) { s_logger.debug("Checking if BigSwitchBcfElement can handle service " + service.getName() + " on network " + network.getDisplayText()); if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) { return false; } if (!_networkModel.isProviderForNetwork(getProvider(), network.getId())) { s_logger.debug("BigSwitchBcfElement is not a provider for network " + network.getDisplayText()); return false; } if (!_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), service, BcfConstants.BIG_SWITCH_BCF)) { s_logger.debug("BigSwitchBcfElement can't provide the " + service.getName() + " service on network " + network.getDisplayText()); return false; } return true; } @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { super.configure(name, params); _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @Override public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { updateBcfRouter(network); return true; } @Override public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { if (!canHandle(network, Service.Connectivity)) { return false; } bcfUtilsInit(); // get arguments for CreateBcfAttachmentCommand // determine whether this is VPC network or stand-alone network Vpc vpc = null; if(network.getVpcId()!=null){ vpc = _vpcDao.acquireInLockTable(network.getVpcId()); } String tenantId; String tenantName; if (vpc != null) { tenantId = vpc.getUuid(); tenantName = vpc.getName(); _vpcDao.releaseFromLockTable(vpc.getId()); } else { // use account in CS as tenant in BSN // use network id/name as tenant id/name for non-VPC networks tenantId = network.getUuid(); tenantName = network.getName(); } String networkId = network.getUuid(); String hostname = dest.getHost().getName(); String nicId = nic.getUuid(); Integer vlan = Integer.valueOf(BroadcastDomainType.getValue(nic.getIsolationUri())); String ipv4 = nic.getIPv4Address(); String mac = nic.getMacAddress(); long zoneId = network.getDataCenterId(); String vmwareVswitchLabel = _networkModel.getDefaultGuestTrafficLabel(zoneId, HypervisorType.VMware); String[] labelArray = null; String vswitchName = null; if(vmwareVswitchLabel!=null){ labelArray=vmwareVswitchLabel.split(","); vswitchName = labelArray[0]; } // hypervisor type: // kvm: ivs port name // vmware: specific portgroup naming convention String pgName = ""; if (dest.getHost().getHypervisorType() == HypervisorType.KVM){ pgName = hostname; } else if (dest.getHost().getHypervisorType() == HypervisorType.VMware){ pgName = hostname + "-" + vswitchName; } CreateBcfAttachmentCommand cmd = new CreateBcfAttachmentCommand(tenantId, tenantName, networkId, pgName, nicId, vlan, ipv4, mac); _bcfUtils.sendBcfCommandWithNetworkSyncCheck(cmd, network); return true; } @Override public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { if (!canHandle(network, Service.Connectivity)) { return false; } if (network.getBroadcastUri() == null) { s_logger.error("Nic has no broadcast Uri"); return false; } bcfUtilsInit(); String networkId = network.getUuid(); String nicId = nic.getUuid(); String tenantId; if(network.getVpcId()!=null) { tenantId = network.getNetworkDomain(); } else { tenantId = networkId; } DeleteBcfAttachmentCommand cmd = new DeleteBcfAttachmentCommand(tenantId, networkId, nicId); _bcfUtils.sendBcfCommandWithNetworkSyncCheck(cmd, network); return true; } @Override public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException { if (!canHandle(network, Service.Connectivity)) { return false; } return true; } @Override public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { if (!canHandle(network, Service.Connectivity)) { return false; } return true; } @Override public boolean isReady(PhysicalNetworkServiceProvider provider) { return true; } @Override public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; } @Override public boolean canEnableIndividualServices() { return true; } @Override public boolean verifyServicesCombination(Set<Service> services) { if (!services.contains(Service.Connectivity)) { s_logger.warn("Unable to provide services without Connectivity service enabled for this element"); return false; } return true; } private static Map<Service, Map<Capability, String>> setCapabilities() { Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>(); // L2 Support capabilities.put(Service.Connectivity, null); // L3 Support capabilities.put(Service.Gateway, null); // L3 Support : SourceNat Map<Capability, String> sourceNatCapabilities = new HashMap<Capability, String>(); sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "peraccount"); sourceNatCapabilities.put(Capability.RedundantRouter, "false"); capabilities.put(Service.SourceNat, sourceNatCapabilities); // L3 support : StaticNat capabilities.put(Service.StaticNat, null); //add network ACL capability Map<Network.Capability, String> networkACLCapabilities = new HashMap<Network.Capability, String>(); networkACLCapabilities.put(Network.Capability.SupportedProtocols, "tcp,udp,icmp"); capabilities.put(Network.Service.NetworkACL, networkACLCapabilities); // Set capabilities for Firewall service Map<Capability, String> firewallCapabilities = new HashMap<Capability, String>(); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp, all"); firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress"); firewallCapabilities.put(Capability.MultipleIps, "true"); capabilities.put(Service.Firewall, firewallCapabilities); return capabilities; } @Override @DB public BigSwitchBcfDeviceVO addBigSwitchBcfDevice(AddBigSwitchBcfDeviceCmd cmd) { BigSwitchBcfDeviceVO newBcfDevice; bcfUtilsInit(); ServerResource resource = new BigSwitchBcfResource(); final String deviceName = BcfConstants.BIG_SWITCH_BCF.getName(); NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName); final Long physicalNetworkId = cmd.getPhysicalNetworkId(); final String hostname = cmd.getHost(); final String username = cmd.getUsername(); final String password = cmd.getPassword(); final Boolean nat = cmd.getNat(); PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (physicalNetwork == null) { throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); } long zoneId = physicalNetwork.getDataCenterId(); final PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(physicalNetwork.getId(), networkDevice.getNetworkServiceProvder()); if (ntwkSvcProvider == null) { throw new CloudRuntimeException("Network Service Provider: " + networkDevice.getNetworkServiceProvder() + " is not enabled in the physical network: " + physicalNetworkId + "to add this device"); } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) { throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device"); } ntwkSvcProvider.setFirewallServiceProvided(true); ntwkSvcProvider.setGatewayServiceProvided(true); ntwkSvcProvider.setNetworkAclServiceProvided(true); ntwkSvcProvider.setSourcenatServiceProvided(true); ntwkSvcProvider.setStaticnatServiceProvided(true); if (_bigswitchBcfDao.listByPhysicalNetwork(physicalNetworkId).size() > 1) { throw new CloudRuntimeException("At most two BCF controllers can be configured"); } DataCenterVO zone = _zoneDao.findById(physicalNetwork.getDataCenterId()); String zoneName; if(zone!= null){ zoneName = zone.getName(); } else { zoneName = String.valueOf(zoneId); } Boolean natNow = _bcfUtils.isNatEnabled(); if (!nat && natNow){ throw new CloudRuntimeException("NAT is enabled in existing controller. Enable NAT for new controller or remove existing controller first."); } else if (nat && !natNow){ throw new CloudRuntimeException("NAT is disabled in existing controller. Disable NAT for new controller or remove existing controller first."); } Map<String, String> params = new HashMap<String, String>(); params.put("guid", UUID.randomUUID().toString()); params.put("zoneId", zoneName); params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId())); params.put("name", "BigSwitch Controller - " + cmd.getHost()); params.put("hostname", cmd.getHost()); params.put("username", username); params.put("password", password); params.put("nat", nat.toString()); // FIXME What to do with multiple isolation types params.put("transportzoneisotype", physicalNetwork.getIsolationMethods().get(0).toLowerCase()); Map<String, Object> hostdetails = new HashMap<String, Object>(); hostdetails.putAll(params); try { resource.configure(cmd.getHost(), hostdetails); // store current topology in bcf resource TopologyData topo = _bcfUtils.getTopology(physicalNetwork.getId()); ((BigSwitchBcfResource) resource).setTopology(topo); final Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.L2Networking, params); if (host != null) { newBcfDevice = Transaction.execute(new TransactionCallback<BigSwitchBcfDeviceVO>() { @Override public BigSwitchBcfDeviceVO doInTransaction(TransactionStatus status) { BigSwitchBcfDeviceVO bigswitchBcfDevice = new BigSwitchBcfDeviceVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), deviceName, hostname, username, password, nat, BigSwitchBcfApi.HASH_IGNORE); _bigswitchBcfDao.persist(bigswitchBcfDevice); DetailVO detail = new DetailVO(host.getId(), "bigswitchbcfdeviceid", String.valueOf(bigswitchBcfDevice.getId())); _hostDetailsDao.persist(detail); return bigswitchBcfDevice; } }); } else { throw new CloudRuntimeException("Failed to add BigSwitch BCF Controller Device due to internal error."); } } catch (ConfigurationException e) { throw new CloudRuntimeException(e.getMessage()); } // initial topology sync to newly added BCF controller HostVO bigswitchBcfHost = _hostDao.findById(newBcfDevice.getHostId()); _bcfUtils.syncTopologyToBcfHost(bigswitchBcfHost, nat); return newBcfDevice; } @Override public BigSwitchBcfDeviceResponse createBigSwitchBcfDeviceResponse(BigSwitchBcfDeviceVO bigswitchBcfDeviceVO) { HostVO bigswitchBcfHost = _hostDao.findById(bigswitchBcfDeviceVO.getHostId()); _hostDao.loadDetails(bigswitchBcfHost); BigSwitchBcfDeviceResponse response = new BigSwitchBcfDeviceResponse(); response.setDeviceName(bigswitchBcfDeviceVO.getDeviceName()); PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(bigswitchBcfDeviceVO.getPhysicalNetworkId()); if (pnw != null) { response.setPhysicalNetworkId(pnw.getUuid()); } response.setId(bigswitchBcfDeviceVO.getUuid()); response.setProviderName(bigswitchBcfDeviceVO.getProviderName()); response.setHostName(bigswitchBcfHost.getDetail("hostname")); response.setObjectName("bigswitchbcfdevice"); return response; } @Override public boolean deleteBigSwitchBcfDevice(DeleteBigSwitchBcfDeviceCmd cmd) { Long bigswitchBcfDeviceId = cmd.getBigSwitchBcfDeviceId(); BigSwitchBcfDeviceVO bigswitchBcfDevice = _bigswitchBcfDao.findById(bigswitchBcfDeviceId); if (bigswitchBcfDevice == null) { throw new InvalidParameterValueException("Could not find a BigSwitch Controller with id " + bigswitchBcfDevice); } HostVO bigswitchHost = _hostDao.findById(bigswitchBcfDevice.getHostId()); Long hostId = bigswitchHost.getId(); bigswitchHost.setResourceState(ResourceState.Maintenance); _hostDao.update(hostId, bigswitchHost); _resourceMgr.deleteHost(hostId, false, false); _bigswitchBcfDao.remove(bigswitchBcfDeviceId); return true; } @Override public List<BigSwitchBcfDeviceVO> listBigSwitchBcfDevices(ListBigSwitchBcfDevicesCmd cmd) { Long physicalNetworkId = cmd.getPhysicalNetworkId(); Long bigswitchBcfDeviceId = cmd.getBigSwitchBcfDeviceId(); List<BigSwitchBcfDeviceVO> responseList = new ArrayList<BigSwitchBcfDeviceVO>(); if (physicalNetworkId == null && bigswitchBcfDeviceId == null) { throw new InvalidParameterValueException("Either physical network Id or bigswitch device Id must be specified"); } if (bigswitchBcfDeviceId != null) { BigSwitchBcfDeviceVO bigswitchBcfDevice = _bigswitchBcfDao.findById(bigswitchBcfDeviceId); if (bigswitchBcfDevice == null) { throw new InvalidParameterValueException("Could not find BigSwitch controller with id: " + bigswitchBcfDevice); } responseList.add(bigswitchBcfDevice); } else { PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (physicalNetwork == null) { throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId); } responseList = _bigswitchBcfDao.listByPhysicalNetwork(physicalNetworkId); } return responseList; } @Override public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { return null; } @Override public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details, List<String> hostTags) { if (!(startup[0] instanceof StartupBigSwitchBcfCommand)) { return null; } BigSwitchBcfResource bcfResource = (BigSwitchBcfResource) resource; bcfUtilsInit(); if(_bcfUtils.getTopology()!=null){ bcfResource.setTopology(_bcfUtils.getTopology()); } host.setType(Host.Type.L2Networking); return host; } @Override public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { if (!(host.getType() == Host.Type.L2Networking)) { return null; } return new DeleteHostAnswer(true); } @Override public List<Class<?>> getCommands() { List<Class<?>> cmdList = new ArrayList<Class<?>>(); cmdList.add(AddBigSwitchBcfDeviceCmd.class); cmdList.add(DeleteBigSwitchBcfDeviceCmd.class); cmdList.add(ListBigSwitchBcfDevicesCmd.class); return cmdList; } @Override public IpDeployer getIpDeployer(Network network) { return this; } @Override public boolean applyStaticNats(Network network, List<? extends StaticNat> rules) throws ResourceUnavailableException { bcfUtilsInit(); _bcfUtils.listACLbyNetwork(network); Vpc vpc = null; if(network.getVpcId()!=null){ vpc = _vpcDao.acquireInLockTable(network.getVpcId()); } String tenantId; if (vpc != null) { tenantId = vpc.getUuid(); _vpcDao.releaseFromLockTable(vpc.getId()); } else { // use account in CS as tenant in BSN // use network uuid as tenantId for non-VPC networks tenantId = network.getUuid(); } for (StaticNat rule: rules){ String srcIp = _ipAddressDao.findById(rule.getSourceIpAddressId()).getAddress().addr(); String dstIp = rule.getDestIpAddress(); String mac = rule.getSourceMacAddress(); if(!rule.isForRevoke()) { s_logger.debug("BCF enables static NAT for public IP: " + srcIp + " private IP " + dstIp + " mac " + mac); CreateBcfStaticNatCommand cmd = new CreateBcfStaticNatCommand( tenantId, network.getUuid(), dstIp, srcIp, mac); _bcfUtils.sendBcfCommandWithNetworkSyncCheck(cmd, network); } else { s_logger.debug("BCF removes static NAT for public IP: " + srcIp + " private IP " + dstIp + " mac " + mac); DeleteBcfStaticNatCommand cmd = new DeleteBcfStaticNatCommand(tenantId, srcIp); _bcfUtils.sendBcfCommandWithNetworkSyncCheck(cmd, network); } } return true; } @Override public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> services) throws ResourceUnavailableException { return false; } @Override public boolean applyNetworkACLs(Network network, List<? extends NetworkACLItem> rules) throws ResourceUnavailableException { SubnetUtils utils; String cidr = null; List<String> cidrList; for(NetworkACLItem r: rules){ if(r.getState()==NetworkACLItem.State.Revoke){ continue; } cidrList = r.getSourceCidrList(); if(cidrList != null){ if(cidrList.size()>1 || !r.getSourcePortEnd().equals(r.getSourcePortStart())){ throw new ResourceUnavailableException("One CIDR and one port only please.", Network.class, network.getId()); } else { cidr = cidrList.get(0); } } if (cidr == null || cidr.equalsIgnoreCase("0.0.0.0/0")) { cidr = ""; } else { utils = new SubnetUtils(cidr); if(!utils.getInfo().getNetworkAddress().equals(utils.getInfo().getAddress())){ throw new ResourceUnavailableException("Invalid CIDR in Network ACL rule.", Network.class, network.getId()); } } } updateBcfRouter(network); return true; } @Override public boolean applyFWRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException { SubnetUtils utils; String cidr = null; List<String> cidrList; for(FirewallRule r: rules){ if(r.getState()==FirewallRule.State.Revoke){ continue; } cidrList = r.getSourceCidrList(); if(cidrList != null){ if(cidrList.size()>1 || !r.getSourcePortEnd().equals(r.getSourcePortStart())){ throw new ResourceUnavailableException("One CIDR and one port only please.", Network.class, network.getId()); } else { cidr = cidrList.get(0); } } if (cidr == null || cidr.equalsIgnoreCase("0.0.0.0/0")) { cidr = ""; } else { utils = new SubnetUtils(cidr); if(!utils.getInfo().getNetworkAddress().equals(utils.getInfo().getAddress())){ throw new ResourceUnavailableException("Invalid CIDR in Firewall rule.", Network.class, network.getId()); } } } updateBcfRouter(network); return true; } private void updateBcfRouter(Network network) throws IllegalArgumentException{ bcfUtilsInit(); Vpc vpc = null; if(network.getVpcId()!=null){ vpc = _vpcDao.acquireInLockTable(network.getVpcId()); } String tenantId; if (vpc != null) { tenantId = vpc.getUuid(); _vpcDao.releaseFromLockTable(vpc.getId()); } else { tenantId = network.getUuid(); } UpdateBcfRouterCommand cmd = new UpdateBcfRouterCommand(tenantId); List<AclData> aclList = _bcfUtils.listACLbyNetwork(network); for(AclData acl: aclList){ cmd.addAcl(acl); } if(vpc != null){ cmd.setPublicIp(_bcfUtils.getPublicIpByVpc(vpc)); } else { cmd.setPublicIp(_bcfUtils.getPublicIpByNetwork(network)); } BcfAnswer answer = _bcfUtils.sendBcfCommandWithNetworkSyncCheck(cmd, network); if(answer != null && !answer.getResult()){ throw new IllegalArgumentException("Illegal router update arguments"); } } private void bcfUtilsInit(){ if (_bcfUtils == null) { _bcfUtils = new BigSwitchBcfUtils(_networkDao, _nicDao, _vmDao, _hostDao, _vpcDao, _bigswitchBcfDao, _agentMgr, _vlanDao, _ipAddressDao, _fwRulesDao, _fwCidrsDao, _aclItemDao, _aclItemCidrsDao, _networkModel); } } }