blob: 776f76fabca0fac91c5b784e96a7c4bbf27eeab8 [file] [log] [blame]
//
// 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);
}
}
}