Support for inline SRX/F5.

This commit is contained in:
keshav 2011-09-07 14:18:42 -07:00
parent 2e87fcb06d
commit 37c74b35ab
25 changed files with 1297 additions and 210 deletions

View File

@ -24,11 +24,15 @@ import com.cloud.agent.api.Command;
public abstract class NetworkElementCommand extends Command {
HashMap<String, String> accessDetails = new HashMap<String, String>(0);
public static final String ACCOUNT_ID = "account.id";
public static final String GUEST_NETWORK_CIDR = "guest.network.cidr";
public static final String GUEST_NETWORK_GATEWAY = "guest.network.gateway";
public static final String GUEST_VLAN_TAG = "guest.vlan.tag";
public static final String ROUTER_NAME = "router.name";
public static final String ROUTER_IP = "router.ip";
public static final String ROUTER_GUEST_IP = "router.guest.ip";
public static final String ZONE_NETWORK_TYPE = "zone.network.type";
protected NetworkElementCommand() {
super();
}

View File

@ -46,6 +46,7 @@ import com.cloud.utils.net.NetUtils;
*/
public class FirewallRuleTO {
long id;
String srcVlanTag;
String srcIp;
String protocol;
int[] srcPortRange;
@ -60,8 +61,9 @@ public class FirewallRuleTO {
protected FirewallRuleTO() {
}
public FirewallRuleTO(long id, String srcIp, String protocol, Integer srcPortStart, Integer srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose, List<String> sourceCidr,Integer icmpType,Integer icmpCode) {
this.srcIp = srcIp;
public FirewallRuleTO(long id, String srcVlanTag, String srcIp, String protocol, Integer srcPortStart, Integer srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose, List<String> sourceCidr,Integer icmpType,Integer icmpCode) {
this.srcVlanTag = srcVlanTag;
this.srcIp = srcIp;
this.protocol = protocol;
if (srcPortStart != null) {
@ -87,13 +89,17 @@ public class FirewallRuleTO {
this.icmpCode = icmpCode;
}
public FirewallRuleTO(FirewallRule rule, String srcIp) {
this(rule.getId(), srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp) {
this(rule.getId(), srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public long getId() {
return id;
}
public String getSrcVlanTag() {
return srcVlanTag;
}
public String getSrcIp() {
return srcIp;

View File

@ -25,6 +25,7 @@ import com.cloud.network.Networks.TrafficType;
public class IpAddressTO {
private long accountId;
private String publicIp;
private boolean sourceNat;
private boolean add;
@ -39,8 +40,9 @@ public class IpAddressTO {
private TrafficType trafficType;
private String[] networkTags;
public IpAddressTO(String ipAddress, boolean add, boolean firstIP, boolean sourceNat, String vlanId, String vlanGateway, String vlanNetmask, String vifMacAddress, String guestIp, Integer networkRate, boolean isOneToOneNat) {
this.publicIp = ipAddress;
public IpAddressTO(long accountId, String ipAddress, boolean add, boolean firstIP, boolean sourceNat, String vlanId, String vlanGateway, String vlanNetmask, String vifMacAddress, String guestIp, Integer networkRate, boolean isOneToOneNat) {
this.accountId = accountId;
this.publicIp = ipAddress;
this.add = add;
this.firstIP = firstIP;
this.sourceNat = sourceNat;
@ -55,6 +57,10 @@ public class IpAddressTO {
protected IpAddressTO() {
}
public long getAccountId() {
return accountId;
}
public String getGuestIp(){
return guestIp;

View File

@ -38,14 +38,14 @@ public class PortForwardingRuleTO extends FirewallRuleTO {
super();
}
public PortForwardingRuleTO(PortForwardingRule rule, String srcIp) {
super(rule, srcIp);
public PortForwardingRuleTO(PortForwardingRule rule, String srcVlanTag, String srcIp) {
super(rule, srcVlanTag, srcIp);
this.dstIp = rule.getDestinationIpAddress().addr();
this.dstPortRange = new int[] { rule.getDestinationPortStart(), rule.getDestinationPortEnd() };
}
protected PortForwardingRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) {
super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.PortForwarding, null,0,0);
protected PortForwardingRuleTO(long id, String srcVlanTag, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) {
super(id, srcVlanTag, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.PortForwarding, null,0,0);
this.dstIp = dstIp;
this.dstPortRange = new int[] { dstPortStart, dstPortEnd };
}

View File

@ -35,14 +35,14 @@ public class StaticNatRuleTO extends FirewallRuleTO{
protected StaticNatRuleTO() {
}
public StaticNatRuleTO(StaticNatRule rule, String scrIp, String dstIp) {
super(rule.getId(), scrIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(),rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(), null,0,0);
public StaticNatRuleTO(StaticNatRule rule, String srcVlanTag, String srcIp, String dstIp) {
super(rule.getId(), srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(),rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(), null,0,0);
this.dstIp = dstIp;
}
public StaticNatRuleTO(long id, String srcIp, Integer srcPortStart, Integer srcPortEnd, String dstIp, Integer dstPortStart, Integer dstPortEnd, String protocol, boolean revoked, boolean alreadyAdded) {
super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, alreadyAdded, FirewallRule.Purpose.StaticNat, null,0,0);
public StaticNatRuleTO(long id, String srcVlanTag, String srcIp, Integer srcPortStart, Integer srcPortEnd, String dstIp, Integer dstPortStart, Integer dstPortEnd, String protocol, boolean revoked, boolean alreadyAdded) {
super(id, srcVlanTag, srcIp, protocol, srcPortStart, srcPortEnd, revoked, alreadyAdded, FirewallRule.Purpose.StaticNat, null,0,0);
this.dstIp = dstIp;
}

View File

@ -75,6 +75,7 @@ public class ApiConstants {
public static final String HA_ENABLE = "haenable";
public static final String HOST_ID = "hostid";
public static final String HYPERVISOR = "hypervisor";
public static final String INLINE = "inline";
public static final String INSTANCE = "instance";
public static final String ICMP_CODE = "icmpcode";
public static final String ICMP_TYPE = "icmptype";

View File

@ -218,6 +218,11 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
public Ip getDestinationIpAddress() {
return null;
}
@Override
public void setDestinationIpAddress(Ip destinationIpAddress) {
return;
}
@Override
public int getDestinationPortStart() {

View File

@ -28,6 +28,12 @@ public interface PortForwardingRule extends FirewallRule {
*/
Ip getDestinationIpAddress();
/**
* updates the destination ip address.
*/
void setDestinationIpAddress(Ip destinationIpAddress);
/**
* @return start of destination port.
*/

View File

@ -1,5 +1,20 @@
/**
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
*
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.resource;
@ -23,6 +38,7 @@ import iControl.LocalLBVirtualServerVirtualServerStatistics;
import iControl.LocalLBVirtualServerVirtualServerType;
import iControl.NetworkingMemberTagType;
import iControl.NetworkingMemberType;
import iControl.NetworkingRouteDomainBindingStub;
import iControl.NetworkingSelfIPBindingStub;
import iControl.NetworkingVLANBindingStub;
import iControl.NetworkingVLANMemberEntry;
@ -53,6 +69,7 @@ import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO;
@ -99,6 +116,7 @@ public class F5BigIpResource implements ServerResource {
private String _privateInterface;
private Integer _numRetries;
private String _guid;
private boolean _inline;
private Interfaces _interfaces;
private LocalLBVirtualServerBindingStub _virtualServerApi;
@ -106,8 +124,10 @@ public class F5BigIpResource implements ServerResource {
private LocalLBNodeAddressBindingStub _nodeApi;
private NetworkingVLANBindingStub _vlanApi;
private NetworkingSelfIPBindingStub _selfIpApi;
private NetworkingRouteDomainBindingStub _routeDomainApi;
private SystemConfigSyncBindingStub _configSyncApi;
private String _objectNamePathSep = "-";
private String _routeDomainIdentifier = "%";
private static final Logger s_logger = Logger.getLogger(F5BigIpResource.class);
@ -157,6 +177,8 @@ public class F5BigIpResource implements ServerResource {
if (_guid == null) {
throw new ConfigurationException("Unable to find the guid");
}
_inline = Boolean.parseBoolean((String) params.get("inline"));
if (!login()) {
throw new ExecutionException("Failed to login to the F5 BigIp.");
@ -268,7 +290,7 @@ public class F5BigIpResource implements ServerResource {
IpAddressTO[] ips = cmd.getIpAddresses();
for (IpAddressTO ip : ips) {
long guestVlanTag = Long.valueOf(ip.getVlanId());
String vlanSelfIp = ip.getVlanGateway();
String vlanSelfIp = _inline ? tagAddressWithRouteDomain(ip.getVlanGateway(), guestVlanTag) : ip.getVlanGateway();
String vlanNetmask = ip.getVlanNetmask();
// Delete any existing guest VLAN with this tag, self IP, and netmask
@ -298,6 +320,7 @@ public class F5BigIpResource implements ServerResource {
private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) {
try {
long guestVlanTag = Long.parseLong(cmd.getAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG));
LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
for (LoadBalancerTO loadBalancer : loadBalancers) {
LbProtocol lbProtocol;
@ -320,7 +343,7 @@ public class F5BigIpResource implements ServerResource {
throw new ExecutionException("Got invalid algorithm: " + loadBalancer.getAlgorithm());
}
String srcIp = loadBalancer.getSrcIp();
String srcIp = _inline ? tagAddressWithRouteDomain(loadBalancer.getSrcIp(), guestVlanTag) : loadBalancer.getSrcIp();
int srcPort = loadBalancer.getSrcPort();
String virtualServerName = genVirtualServerName(lbProtocol, srcIp, srcPort);
@ -340,8 +363,9 @@ public class F5BigIpResource implements ServerResource {
List<String> activePoolMembers = new ArrayList<String>();
for (DestinationTO destination : loadBalancer.getDestinations()) {
if (!destination.isRevoked()) {
addPoolMember(virtualServerName, destination.getDestIp(), destination.getDestPort());
activePoolMembers.add(destination.getDestIp() + "-" + destination.getDestPort());
String destIp = _inline ? tagAddressWithRouteDomain(destination.getDestIp(), guestVlanTag) : destination.getDestIp();
addPoolMember(virtualServerName, destIp, destination.getDestPort());
activePoolMembers.add(destIp + "-" + destination.getDestPort());
}
}
@ -372,7 +396,7 @@ public class F5BigIpResource implements ServerResource {
private synchronized ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) {
try {
return getPublicIpBytesSentAndReceived(cmd);
return getIpBytesSentAndReceived(cmd);
} catch (ExecutionException e) {
return new ExternalNetworkResourceUsageAnswer(cmd, e);
}
@ -412,6 +436,21 @@ public class F5BigIpResource implements ServerResource {
}
}
if (_inline) {
List<Long> allRouteDomains = getRouteDomains();
if (!allRouteDomains.contains(vlanTag)) {
long[] routeDomainIds = genLongArray(vlanTag);
String[][] vlanNames = new String[][]{genStringArray(genVlanName(vlanTag))};
s_logger.debug("Creating route domain " + vlanTag);
_routeDomainApi.create(routeDomainIds, vlanNames);
if (!getRouteDomains().contains(vlanTag)) {
throw new ExecutionException("Failed to create route domain " + vlanTag);
}
}
}
List<String> allSelfIps = getSelfIps();
if (!allSelfIps.contains(vlanSelfIp)) {
String[] selfIpsToCreate = genStringArray(vlanSelfIp);
@ -439,8 +478,8 @@ public class F5BigIpResource implements ServerResource {
// Delete all virtual servers and pools that use this guest VLAN
deleteVirtualServersInGuestVlan(vlanSelfIp, vlanNetmask);
List<String> selfIps = getSelfIps();
if (selfIps.contains(vlanSelfIp)) {
List<String> allSelfIps = getSelfIps();
if (allSelfIps.contains(vlanSelfIp)) {
s_logger.debug("Deleting self IP " + vlanSelfIp);
_selfIpApi.delete_self_ip(genStringArray(vlanSelfIp));
@ -448,6 +487,18 @@ public class F5BigIpResource implements ServerResource {
throw new ExecutionException("Failed to delete self IP " + vlanSelfIp);
}
}
if (_inline) {
List<Long> allRouteDomains = getRouteDomains();
if (allRouteDomains.contains(vlanTag)) {
s_logger.debug("Deleting route domain " + vlanTag);
_routeDomainApi.delete_route_domain(genLongArray(vlanTag));
if (getRouteDomains().contains(vlanTag)) {
throw new ExecutionException("Failed to delete route domain " + vlanTag);
}
}
}
String vlanName = genVlanName(vlanTag);
List<String> allVlans = getVlans();
@ -464,6 +515,7 @@ public class F5BigIpResource implements ServerResource {
}
private void deleteVirtualServersInGuestVlan(String vlanSelfIp, String vlanNetmask) throws ExecutionException {
vlanSelfIp = stripRouteDomainFromAddress(vlanSelfIp);
List<String> virtualServersToDelete = new ArrayList<String>();
List<String> allVirtualServers = getVirtualServers();
@ -471,7 +523,7 @@ public class F5BigIpResource implements ServerResource {
// Check if the virtual server's default pool has members in this guest VLAN
List<String> poolMembers = getMembers(virtualServerName);
for (String poolMemberName : poolMembers) {
String poolMemberIp = getIpAndPort(poolMemberName)[0];
String poolMemberIp = stripRouteDomainFromAddress(getIpAndPort(poolMemberName)[0]);
if (NetUtils.sameSubnet(vlanSelfIp, poolMemberIp, vlanNetmask)) {
virtualServersToDelete.add(virtualServerName);
break;
@ -489,6 +541,21 @@ public class F5BigIpResource implements ServerResource {
return "vlan-" + String.valueOf(vlanTag);
}
private List<Long> getRouteDomains() throws ExecutionException {
try {
List<Long> routeDomains = new ArrayList<Long>();
long[] routeDomainsArray = _routeDomainApi.get_list();
for (long routeDomainName : routeDomainsArray) {
routeDomains.add(routeDomainName);
}
return routeDomains;
} catch (RemoteException e) {
throw new ExecutionException(e.getMessage());
}
}
private List<String> getSelfIps() throws ExecutionException {
try {
List<String> selfIps = new ArrayList<String>();
@ -534,6 +601,7 @@ public class F5BigIpResource implements ServerResource {
_nodeApi = _interfaces.getLocalLBNodeAddress();
_vlanApi = _interfaces.getNetworkingVLAN();
_selfIpApi = _interfaces.getNetworkingSelfIP();
_routeDomainApi = _interfaces.getNetworkingRouteDomain();
_configSyncApi = _interfaces.getSystemConfigSync();
return true;
@ -587,6 +655,7 @@ public class F5BigIpResource implements ServerResource {
}
private String genVirtualServerName(LbProtocol protocol, String srcIp, long srcPort) {
srcIp = stripRouteDomainFromAddress(srcIp);
return genObjectName("vs", protocol, srcIp, srcPort);
}
@ -834,14 +903,19 @@ public class F5BigIpResource implements ServerResource {
// Stats methods
private ExternalNetworkResourceUsageAnswer getPublicIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
private ExternalNetworkResourceUsageAnswer getIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd);
try {
LocalLBVirtualServerVirtualServerStatistics stats = _virtualServerApi.get_all_statistics();
for (LocalLBVirtualServerVirtualServerStatisticEntry entry : stats.getStatistics()) {
String publicIp = entry.getVirtual_server().getAddress();
long[] bytesSentAndReceived = answer.ipBytes.get(publicIp);
String virtualServerIp = entry.getVirtual_server().getAddress();
if (_inline) {
virtualServerIp = stripRouteDomainFromAddress(virtualServerIp);
}
long[] bytesSentAndReceived = answer.ipBytes.get(virtualServerIp);
if (bytesSentAndReceived == null) {
bytesSentAndReceived = new long[]{0, 0};
@ -858,7 +932,7 @@ public class F5BigIpResource implements ServerResource {
}
if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) {
answer.ipBytes.put(publicIp, bytesSentAndReceived);
answer.ipBytes.put(virtualServerIp, bytesSentAndReceived);
}
}
} catch (Exception e) {
@ -869,7 +943,21 @@ public class F5BigIpResource implements ServerResource {
return answer;
}
// Array util methods
// Misc methods
private String tagAddressWithRouteDomain(String address, long vlanTag) {
return address + _routeDomainIdentifier + vlanTag;
}
private String stripRouteDomainFromAddress(String address) {
int i = address.indexOf(_routeDomainIdentifier);
if (i > 0) {
address = address.substring(0, i);
}
return address;
}
private String genObjectName(Object... args) {
String objectName = "";

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@
</match>
<then>
<permit>
%tunnel%
</permit>
<count>
</count>

View File

@ -73,6 +73,7 @@ import com.cloud.maint.dao.AgentUpgradeDaoImpl;
import com.cloud.network.NetworkManagerImpl;
import com.cloud.network.dao.FirewallRulesCidrsDaoImpl;
import com.cloud.network.dao.FirewallRulesDaoImpl;
import com.cloud.network.dao.InlineLoadBalancerNicMapDaoImpl;
import com.cloud.network.dao.IPAddressDaoImpl;
import com.cloud.network.dao.LoadBalancerDaoImpl;
import com.cloud.network.dao.LoadBalancerVMMapDaoImpl;
@ -270,8 +271,9 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
addDao("DcDetailsDao", DcDetailsDaoImpl.class);
addDao("SwiftDao", SwiftDaoImpl.class);
addDao("AgentTransferMapDao", HostTransferMapDaoImpl.class);
addDao("InlineLoadBalancerNicMapDao", InlineLoadBalancerNicMapDaoImpl.class);
addDao("ElasticLbVmMap", ElasticLbVmMapDaoImpl.class);
}
@Override

View File

@ -9,6 +9,7 @@ import java.util.List;
import com.cloud.api.commands.AddExternalFirewallCmd;
import com.cloud.api.commands.DeleteExternalFirewallCmd;
import com.cloud.api.commands.ListExternalFirewallsCmd;
import com.cloud.dc.DataCenterVO;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
@ -29,6 +30,8 @@ public interface ExternalFirewallManager extends ExternalNetworkManager {
public boolean manageGuestNetwork(boolean add, Network network, NetworkOffering offering) throws ResourceUnavailableException;
public boolean applyFirewallRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException;
public void applyStaticNatRuleForInlineLBRule(DataCenterVO zone, Network network, HostVO externalFirewall, boolean revoked, String publicIp, String privateIp) throws ResourceUnavailableException;
public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddresses) throws ResourceUnavailableException;

View File

@ -18,5 +18,6 @@ import com.cloud.utils.net.NetUtils;
import com.cloud.vm.NicVO;
public interface ExternalNetworkManager extends Manager {
public int getVlanOffset(DataCenter zone, int vlanTag);
public int getGloballyConfiguredCidrSize();
}

View File

@ -24,13 +24,16 @@ import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
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.HostDetailsDao;
import com.cloud.host.dao.HostDao;
import com.cloud.network.Network.GuestIpType;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.InlineLoadBalancerNicMapDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.rules.PortForwardingRuleVO;
@ -49,7 +52,11 @@ import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicVO;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.Nic.State;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
@Local(value = {ExternalNetworkManager.class})
public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
@ -65,13 +72,16 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
@Inject AccountDao _accountDao;
@Inject DomainRouterDao _routerDao;
@Inject IPAddressDao _ipAddressDao;
@Inject VlanDao _vlanDao;
@Inject UserStatisticsDao _userStatsDao;
@Inject NetworkDao _networkDao;
@Inject PortForwardingRulesDao _portForwardingRulesDao;
@Inject LoadBalancerDao _loadBalancerDao;
@Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao;
@Inject ConfigurationDao _configDao;
@Inject HostDetailsDao _detailsDao;
@Inject NetworkOfferingDao _networkOfferingDao;
@Inject NicDao _nicDao;
ScheduledExecutorService _executor;
int _externalNetworkStatsInterval;
@ -126,7 +136,39 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
}
}
protected class ExternalNetworkUsageTask implements Runnable {
public NicVO savePlaceholderNic(Network network, String ipAddress) {
NicVO nic = new NicVO(null, null, network.getId(), null);
nic.setIp4Address(ipAddress);
nic.setReservationStrategy(ReservationStrategy.PlaceHolder);
nic.setState(State.Reserved);
return _nicDao.persist(nic);
}
protected boolean externalLoadBalancerIsInline(HostVO externalLoadBalancer) {
DetailVO detail = _detailsDao.findDetail(externalLoadBalancer.getId(), "inline");
return (detail != null && detail.getValue().equals("true"));
}
public int getGloballyConfiguredCidrSize() {
try {
String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key());
return 8 + Integer.parseInt(globalVlanBits);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size.");
}
}
public int getVlanOffset(DataCenter zone, int vlanTag) {
if (zone.getVnet() == null) {
throw new CloudRuntimeException("Could not find vlan range for zone " + zone.getName() + ".");
}
String vlanRange[] = zone.getVnet().split("-");
int lowestVlanTag = Integer.valueOf(vlanRange[0]);
return vlanTag - lowestVlanTag;
}
protected class ExternalNetworkUsageTask implements Runnable {
public ExternalNetworkUsageTask() {
}
@ -180,15 +222,28 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
long newCurrentBytesReceived = 0;
if (publicIp != null) {
long[] bytesSentAndReceived = answer.ipBytes.get(publicIp);
statsEntryIdentifier += ", public IP: " + publicIp;
if (bytesSentAndReceived == null) {
s_logger.debug("Didn't get an external network usage answer for public IP " + publicIp);
} else {
newCurrentBytesSent += bytesSentAndReceived[0];
newCurrentBytesReceived += bytesSentAndReceived[1];
}
long[] bytesSentAndReceived = null;
statsEntryIdentifier += ", public IP: " + publicIp;
if (host.getType().equals(Host.Type.ExternalLoadBalancer) && externalLoadBalancerIsInline(host)) {
// Look up stats for the guest IP address that's mapped to the public IP address
InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByPublicIpAddress(publicIp);
if (mapping != null) {
NicVO nic = _nicDao.findById(mapping.getNicId());
String loadBalancingIpAddress = nic.getIp4Address();
bytesSentAndReceived = answer.ipBytes.get(loadBalancingIpAddress);
}
} else {
bytesSentAndReceived = answer.ipBytes.get(publicIp);
}
if (bytesSentAndReceived == null) {
s_logger.debug("Didn't get an external network usage answer for public IP " + publicIp);
} else {
newCurrentBytesSent += bytesSentAndReceived[0];
newCurrentBytesReceived += bytesSentAndReceived[1];
}
} else {
URI broadcastURI = network.getBroadcastUri();
if (broadcastURI == null) {

View File

@ -18,6 +18,7 @@ import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.api.commands.AddExternalLoadBalancerCmd;
@ -31,9 +32,11 @@ import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.AgentUnavailableException;
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.network.Networks.TrafficType;
import com.cloud.network.dao.InlineLoadBalancerNicMapDao;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.resource.F5BigIpResource;
@ -72,6 +75,8 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
ConfigurationManager _configMgr;
@Inject
AccountManager _accountMgr;
@Inject
ExternalFirewallManager _externalFirewallMgr;
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(F5BigIpManagerImpl.class);
@ -108,6 +113,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
String publicInterface = params.get("publicinterface");
String privateInterface = params.get("privateinterface");
String numRetries = params.get("numretries");
boolean inline = Boolean.parseBoolean(params.get("inline"));
if (publicInterface == null) {
throw new InvalidParameterValueException("Please specify a public interface.");
@ -134,6 +140,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
hostDetails.put("numRetries", numRetries);
hostDetails.put("guid", guid);
hostDetails.put("name", guid);
hostDetails.put("inline", String.valueOf(inline));
try {
resource.configure(guid, hostDetails);
@ -196,6 +203,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
response.setPublicInterface(lbDetails.get("publicInterface"));
response.setPrivateInterface(lbDetails.get("privateInterface"));
response.setNumRetries(lbDetails.get("numRetries"));
response.setInline(lbDetails.get("inline"));
return response;
}
@ -221,7 +229,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
String guestVlanNetmask = NetUtils.cidr2Netmask(guestConfig.getCidr());
Integer networkRate = _networkMgr.getNetworkRate(guestConfig.getId(), null);
IpAddressTO ip = new IpAddressTO(null, add, false, true, String.valueOf(guestVlanTag), selfIp, guestVlanNetmask, null, null, networkRate, false);
IpAddressTO ip = new IpAddressTO(guestConfig.getAccountId(), null, add, false, true, String.valueOf(guestVlanTag), selfIp, guestVlanNetmask, null, null, networkRate, false);
IpAddressTO[] ips = new IpAddressTO[1];
ips[0] = ip;
IpAssocCommand cmd = new IpAssocCommand(ips);
@ -238,11 +246,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
List<String> reservedIpAddressesForGuestNetwork = _nicDao.listIpAddressInNetwork(guestConfig.getId());
if (add && (!reservedIpAddressesForGuestNetwork.contains(selfIp))) {
// Insert a new NIC for this guest network to reserve the self IP
NicVO nic = new NicVO(null, null, guestConfig.getId(), null);
nic.setIp4Address(selfIp);
nic.setReservationStrategy(ReservationStrategy.PlaceHolder);
nic.setState(Nic.State.Reserved);
_nicDao.persist(nic);
savePlaceholderNic(guestConfig, selfIp);
}
Account account = _accountDao.findByIdIncludingRemoved(guestConfig.getAccountId());
@ -262,6 +266,18 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
if (externalLoadBalancer == null) {
return false;
}
// If the load balancer is inline, find the external firewall in this zone
boolean externalLoadBalancerIsInline = externalLoadBalancerIsInline(externalLoadBalancer);
HostVO externalFirewall = null;
if (externalLoadBalancerIsInline) {
externalFirewall = getExternalNetworkAppliance(zoneId, Host.Type.ExternalFirewall);
if (externalFirewall == null) {
String msg = "External load balancer in zone " + zone.getName() + " is inline, but no external firewall in this zone.";
s_logger.error(msg);
throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
}
}
if (network.getState() == Network.State.Allocated) {
s_logger.debug("F5BigIpManager was asked to apply LB rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands.");
@ -276,7 +292,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
}
}
LoadBalancerTO[] loadBalancers = new LoadBalancerTO[loadBalancingRules.size()];
List<LoadBalancerTO> loadBalancersToApply = new ArrayList<LoadBalancerTO>();
for (int i = 0; i < loadBalancingRules.size(); i++) {
LoadBalancingRule rule = loadBalancingRules.get(i);
@ -287,13 +303,73 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
int srcPort = rule.getSourcePortStart();
List<LbDestination> destinations = rule.getDestinations();
LoadBalancerTO loadBalancer = new LoadBalancerTO(srcIp, srcPort, protocol, algorithm, revoked, false, destinations);
loadBalancers[i] = loadBalancer;
if (externalLoadBalancerIsInline) {
InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByPublicIpAddress(srcIp);
NicVO loadBalancingIpNic = null;
if (!revoked) {
if (mapping == null) {
// Acquire a new guest IP address and save it as the load balancing IP address
String loadBalancingIpAddress = _networkMgr.acquireGuestIpAddress(network, null);
if (loadBalancingIpAddress == null) {
String msg = "Ran out of guest IP addresses.";
s_logger.error(msg);
throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
}
// If a NIC doesn't exist for the load balancing IP address, create one
loadBalancingIpNic = _nicDao.findByIp4Address(loadBalancingIpAddress);
if (loadBalancingIpNic == null) {
loadBalancingIpNic = savePlaceholderNic(network, loadBalancingIpAddress);
}
// Save a mapping between the source IP address and the load balancing IP address NIC
mapping = new InlineLoadBalancerNicMapVO(rule.getId(), srcIp, loadBalancingIpNic.getId());
_inlineLoadBalancerNicMapDao.persist(mapping);
// On the external firewall, create a static NAT rule between the source IP address and the load balancing IP address
_externalFirewallMgr.applyStaticNatRuleForInlineLBRule(zone, network, externalFirewall, revoked, srcIp, loadBalancingIpNic.getIp4Address());
} else {
loadBalancingIpNic = _nicDao.findById(mapping.getNicId());
}
} else {
if (mapping != null) {
// Find the NIC that the mapping refers to
loadBalancingIpNic = _nicDao.findById(mapping.getNicId());
// On the external firewall, delete the static NAT rule between the source IP address and the load balancing IP address
_externalFirewallMgr.applyStaticNatRuleForInlineLBRule(zone, network, externalFirewall, revoked, srcIp, loadBalancingIpNic.getIp4Address());
// Delete the mapping between the source IP address and the load balancing IP address
_inlineLoadBalancerNicMapDao.expunge(mapping.getId());
// Delete the NIC
_nicDao.expunge(loadBalancingIpNic.getId());
} else {
s_logger.debug("Revoking a rule for an inline load balancer that has not been programmed yet.");
continue;
}
}
// Change the source IP address for the load balancing rule to be the load balancing IP address
srcIp = loadBalancingIpNic.getIp4Address();
}
if (destinations != null && !destinations.isEmpty()) {
LoadBalancerTO loadBalancer = new LoadBalancerTO(srcIp, srcPort, protocol, algorithm, revoked, false, destinations);
loadBalancersToApply.add(loadBalancer);
}
}
if (loadBalancers.length > 0) {
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(loadBalancers);
Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd);
if (loadBalancersToApply.size() > 0) {
int numLoadBalancersForCommand = loadBalancersToApply.size();
LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply.toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(loadBalancersForCommand);
long guestVlanTag = Integer.parseInt(network.getBroadcastUri().getHost());
cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag));
Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd);
if (answer == null || !answer.getResult()) {
String details = (answer != null) ? answer.getDetails() : "details unavailable";
String msg = "Unable to apply load balancer rules to the F5 BigIp appliance in zone " + zone.getName() + " due to: " + details + ".";
@ -304,4 +380,5 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
return true;
}
}

View File

@ -17,6 +17,7 @@ import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
import com.cloud.agent.api.to.IpAddressTO;
@ -28,20 +29,27 @@ import com.cloud.api.commands.ListExternalFirewallsCmd;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.exception.AgentUnavailableException;
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.network.Networks.TrafficType;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.InlineLoadBalancerNicMapDao;
import com.cloud.network.resource.JuniperSrxResource;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.StaticNatRuleImpl;
import com.cloud.offering.NetworkOffering;
import com.cloud.server.api.response.ExternalFirewallResponse;
import com.cloud.user.Account;
@ -75,6 +83,8 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
@Inject
UserStatisticsDao _userStatsDao;
@Inject
VlanDao _vlanDao;
@Inject
ConfigurationManager _configMgr;
@Inject
AccountManager _accountMgr;
@ -119,11 +129,7 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
String numRetries = params.get("numretries");
String timeout = params.get("timeout");
if (publicInterface != null) {
if (!publicInterface.contains(".")) {
publicInterface += ".0";
}
} else {
if (publicInterface == null) {
throw new InvalidParameterValueException("Please specify a public interface.");
}
@ -300,31 +306,39 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
Account account = _accountDao.findByIdIncludingRemoved(network.getAccountId());
boolean sharedSourceNat = offering.isSharedSourceNatService();
String sourceNatIp = null;
IPAddressVO sourceNatIp = null;
if (!sharedSourceNat) {
// Get the source NAT IP address for this network
List<IPAddressVO> sourceNatIps = _networkMgr.listPublicIpAddressesInVirtualNetwork(network.getAccountId(), zoneId, true, null);
if (sourceNatIps.size() != 1) {
String errorMsg = "JuniperSrxManager was unable to find the source NAT IP address for account " + account.getAccountName();
s_logger.error(errorMsg);
return true;
} else {
sourceNatIp = sourceNatIps.get(0).getAddress().addr();
sourceNatIp = sourceNatIps.get(0);
}
}
// Send a command to the external firewall to implement or shutdown the guest network
long guestVlanTag = Long.parseLong(network.getBroadcastUri().getHost());
String guestVlanGateway = network.getGateway();
String guestVlanNetmask = NetUtils.cidr2Netmask(network.getCidr());
String guestVlanCidr = network.getCidr();
String sourceNatIpAddress = sourceNatIp.getAddress().addr();
VlanVO publicVlan = _vlanDao.findById(sourceNatIp.getVlanId());
String publicVlanTag = publicVlan.getVlanTag();
// Get network rate
Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null);
IpAddressTO ip = new IpAddressTO(sourceNatIp, add, false, !sharedSourceNat, String.valueOf(guestVlanTag), guestVlanGateway, guestVlanNetmask, null, null, networkRate, false);
IpAddressTO ip = new IpAddressTO(account.getId(), sourceNatIpAddress, add, false, !sharedSourceNat, publicVlanTag, null, null, null, null, networkRate, sourceNatIp.isOneToOneNat());
IpAddressTO[] ips = new IpAddressTO[1];
ips[0] = ip;
IpAssocCommand cmd = new IpAssocCommand(ips);
cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY, guestVlanGateway);
cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, guestVlanCidr);
cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag));
Answer answer = _agentMgr.easySend(externalFirewall.getId(), cmd);
if (answer == null || !answer.getResult()) {
@ -338,11 +352,17 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
List<String> reservedIpAddressesForGuestNetwork = _nicDao.listIpAddressInNetwork(network.getId());
if (add && (!reservedIpAddressesForGuestNetwork.contains(network.getGateway()))) {
// Insert a new NIC for this guest network to reserve the gateway address
NicVO nic = new NicVO(null, null, network.getId(), null);
nic.setIp4Address(network.getGateway());
nic.setReservationStrategy(ReservationStrategy.PlaceHolder);
nic.setState(State.Reserved);
_nicDao.persist(nic);
savePlaceholderNic(network, network.getGateway());
}
// Delete any mappings used for inline external load balancers in this network
List<NicVO> nicsInNetwork = _nicDao.listByNetworkId(network.getId());
for (NicVO nic : nicsInNetwork) {
InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByNicId(nic.getId());
if (mapping != null) {
_nicDao.expunge(mapping.getNicId());
_inlineLoadBalancerNicMapDao.expunge(mapping.getId());
}
}
String action = add ? "implemented" : "shut down";
@ -350,6 +370,20 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
return true;
}
public void applyStaticNatRuleForInlineLBRule(DataCenterVO zone, Network network, HostVO externalFirewall, boolean revoked, String publicIp, String privateIp) throws ResourceUnavailableException {
List<StaticNatRuleTO> staticNatRules = new ArrayList<StaticNatRuleTO>();
IPAddressVO ipVO = _ipAddressDao.listByDcIdIpAddress(zone.getId(), publicIp).get(0);
VlanVO vlan = _vlanDao.findById(ipVO.getVlanId());
FirewallRuleVO fwRule = new FirewallRuleVO(null, ipVO.getId(), -1, -1, "any", network.getId(), network.getAccountId(), network.getDomainId(), Purpose.StaticNat, null, null, null, null);
FirewallRule.State state = !revoked ? FirewallRule.State.Add : FirewallRule.State.Revoke;
fwRule.setState(state);
StaticNatRule rule = new StaticNatRuleImpl(fwRule, privateIp);
StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, vlan.getVlanTag(), publicIp, privateIp);
staticNatRules.add(ruleTO);
applyStaticNatRules(staticNatRules, zone, externalFirewall.getId());
}
@Override
public boolean applyFirewallRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException {
@ -372,12 +406,14 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
for (FirewallRule rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
Vlan vlan = _vlanDao.findById(sourceIp.getVlanId());
if (rule.getPurpose() == Purpose.StaticNat) {
StaticNatRule staticNatRule = (StaticNatRule) rule;
StaticNatRuleTO ruleTO = new StaticNatRuleTO(staticNatRule, sourceIp.getAddress().addr(), staticNatRule.getDestIpAddress());
StaticNatRuleTO ruleTO = new StaticNatRuleTO(staticNatRule, vlan.getVlanTag(), sourceIp.getAddress().addr(), staticNatRule.getDestIpAddress());
staticNatRules.add(ruleTO);
} else if (rule.getPurpose() == Purpose.PortForwarding) {
PortForwardingRuleTO ruleTO = new PortForwardingRuleTO((PortForwardingRule) rule, sourceIp.getAddress().addr());
PortForwardingRuleTO ruleTO = new PortForwardingRuleTO((PortForwardingRule) rule, vlan.getVlanTag(), sourceIp.getAddress().addr());
portForwardingRules.add(ruleTO);
}
}

View File

@ -1,5 +1,20 @@
/**
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
*
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.guru;
@ -8,7 +23,6 @@ import java.util.List;
import javax.ejb.Local;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.dao.DataCenterDao;
@ -19,6 +33,7 @@ import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.ExternalNetworkManager;
import com.cloud.network.Network;
import com.cloud.network.Network.State;
import com.cloud.network.NetworkManager;
@ -27,11 +42,14 @@ import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.ovs.OvsNetworkManager;
import com.cloud.network.ovs.OvsTunnelManager;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.NicProfile;
@ -46,12 +64,16 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
@Inject
NetworkManager _networkMgr;
@Inject
ExternalNetworkManager _externalNetworkMgr;
@Inject
NetworkDao _networkDao;
@Inject
DataCenterDao _zoneDao;
@Inject
ConfigurationDao _configDao;
@Inject
PortForwardingRulesDao _pfRulesDao;
@Inject
OvsNetworkManager _ovsNetworkMgr;
@Inject
OvsTunnelManager _tunnelMgr;
@ -108,12 +130,12 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
}
// Determine the offset from the lowest vlan tag
int offset = getVlanOffset(zone, vlanTag);
int offset = _externalNetworkMgr.getVlanOffset(zone, vlanTag);
// Determine the new gateway and CIDR
String[] oldCidr = config.getCidr().split("/");
String oldCidrAddress = oldCidr[0];
int cidrSize = getGloballyConfiguredCidrSize();
int cidrSize = _externalNetworkMgr.getGloballyConfiguredCidrSize();
// If the offset has more bits than there is room for, return null
long bitsInOffset = 32 - Integer.numberOfLeadingZeros(offset);
@ -130,10 +152,21 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
List<NicVO> nicsInNetwork = _nicDao.listByNetworkId(config.getId());
for (NicVO nic : nicsInNetwork) {
if (nic.getIp4Address() != null) {
long ipMask = NetUtils.ip2Long(nic.getIp4Address()) & ~(0xffffffffffffffffl << (32 - cidrSize));
long ipMask = getIpMask(nic.getIp4Address(), cidrSize);
nic.setIp4Address(NetUtils.long2Ip(newCidrAddress | ipMask));
_nicDao.persist(nic);
}
}
// Mask the destination address of all port forwarding rules in this network with the new guest VLAN offset
List<PortForwardingRuleVO> pfRulesInNetwork = _pfRulesDao.listByNetwork(config.getId());
for (PortForwardingRuleVO pfRule : pfRulesInNetwork) {
if (pfRule.getDestinationIpAddress() != null) {
long ipMask = getIpMask(pfRule.getDestinationIpAddress().addr(), cidrSize);
String maskedDestinationIpAddress = NetUtils.long2Ip(newCidrAddress | ipMask);
pfRule.setDestinationIpAddress(new Ip(maskedDestinationIpAddress));
_pfRulesDao.update(pfRule.getId(), pfRule);
}
}
return implemented;
@ -195,7 +228,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
nic.setDns2(dc.getDns2());
nic.setNetmask(NetUtils.cidr2Netmask(config.getCidr()));
long cidrAddress = NetUtils.ip2Long(config.getCidr().split("/")[0]);
int cidrSize = getGloballyConfiguredCidrSize();
int cidrSize = _externalNetworkMgr.getGloballyConfiguredCidrSize();
nic.setGateway(config.getGateway());
if (nic.getIp4Address() == null) {
@ -229,23 +262,9 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
return super.release(nic, vm, reservationId);
}
}
private int getGloballyConfiguredCidrSize() {
try {
String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key());
return 8 + Integer.parseInt(globalVlanBits);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size.");
}
private long getIpMask(String ipAddress, long cidrSize) {
return NetUtils.ip2Long(ipAddress) & ~(0xffffffffffffffffl << (32 - cidrSize));
}
private int getVlanOffset(DataCenter zone, int vlanTag) {
if (zone.getVnet() == null) {
throw new CloudRuntimeException("Could not find vlan range for zone " + zone.getName() + ".");
}
String vlanRange[] = zone.getVnet().split("-");
int lowestVlanTag = Integer.valueOf(vlanRange[0]);
return vlanTag - lowestVlanTag;
}
}

View File

@ -454,13 +454,17 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
throw new CloudRuntimeException("Unable to add rule for ip address id=" + newRule.getSourceIpAddressId(), e);
} finally {
if (!success) {
txn.start();
//no need to apply the rule as it wasn't programmed on the backend yet
_firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false);
_firewallDao.remove(_firewallDao.findByRelatedId(newRule.getId()).getId());
_lbDao.remove(newRule.getId());
txn.commit();
_lbDao.remove(newRule.getId());
}
}
}
@Override
@ -488,10 +492,8 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
for (LoadBalancerVO lb : lbs) {
List<LbDestination> dstList = getExistingDestinations(lb.getId());
if (dstList != null && !dstList.isEmpty()) {
LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList);
rules.add(loadBalancing);
}
LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList);
rules.add(loadBalancing);
}
if (!_networkMgr.applyRules(rules, false)) {

View File

@ -1506,8 +1506,11 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
for (LoadBalancerVO lb : lbs) {
List<LbDestination> dstList = _lbMgr.getExistingDestinations(lb.getId());
LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList);
lbRules.add(loadBalancing);
if (dstList != null && !dstList.isEmpty()) {
LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList);
lbRules.add(loadBalancing);
}
}
s_logger.debug("Found " + lbRules.size() + " load balancing rule(s) to apply as a part of domR " + router + " start.");
@ -1968,7 +1971,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
String vmGuestAddress = null;
IpAddressTO ip = new IpAddressTO(ipAddr.getAddress().addr(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress, networkRate, ipAddr.isOneToOneNat());
IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress, networkRate, ipAddr.isOneToOneNat());
ip.setTrafficType(network.getTrafficType());
ip.setNetworkTags(network.getTags());
ipsToSend[i++] = ip;
@ -1991,7 +1994,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
rulesTO = new ArrayList<PortForwardingRuleTO>();
for (PortForwardingRule rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, sourceIp.getAddress().addr());
PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, null, sourceIp.getAddress().addr());
rulesTO.add(ruleTO);
}
}
@ -2012,7 +2015,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
rulesTO = new ArrayList<StaticNatRuleTO>();
for (StaticNatRule rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, sourceIp.getAddress().addr(), rule.getDestIpAddress());
StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, null, sourceIp.getAddress().addr(), rule.getDestIpAddress());
rulesTO.add(ruleTO);
}
}
@ -2354,7 +2357,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
rulesTO = new ArrayList<FirewallRuleTO>();
for (FirewallRule rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
FirewallRuleTO ruleTO = new FirewallRuleTO(rule, sourceIp.getAddress().addr());
FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr());
rulesTO.add(ruleTO);
}
}
@ -2446,7 +2449,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
rulesTO = new ArrayList<StaticNatRuleTO>();
for (StaticNat rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, null, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
rulesTO.add(ruleTO);
}
}

View File

@ -51,7 +51,7 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi
public PortForwardingRuleVO() {
}
public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, long networkId, long accountId, long domainId, long instanceId) {
super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding, null, null, null, null);
this.destinationIpAddress = dstIp;
@ -67,6 +67,11 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi
@Override
public Ip getDestinationIpAddress() {
return destinationIpAddress;
}
@Override
public void setDestinationIpAddress(Ip destinationIpAddress) {
this.destinationIpAddress = destinationIpAddress;
}
@Override
@ -88,5 +93,6 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi
public Long getRelated() {
return null;
}
}

View File

@ -31,6 +31,9 @@ public class ExternalLoadBalancerResponse extends BaseResponse {
@SerializedName(ApiConstants.NUM_RETRIES) @Param(description="the number of times to retry requests to the external load balancer")
private String numRetries;
@SerializedName(ApiConstants.INLINE) @Param(description="configures the external load balancer to be inline with an external firewall")
private String inline;
public Long getId() {
return id;
@ -88,4 +91,11 @@ public class ExternalLoadBalancerResponse extends BaseResponse {
this.numRetries = numRetries;
}
public String getInline() {
return inline;
}
public void setInline(String inline) {
this.inline = inline;
}
}

View File

@ -42,4 +42,6 @@ public interface NicDao extends GenericDao<NicVO, Long> {
void removeNicsForInstance(long instanceId);
NicVO findByNetworkIdAndType(long networkId, VirtualMachine.Type vmType);
NicVO findByIp4Address(String ip4Address);
}

View File

@ -46,6 +46,7 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
AllFieldsSearch.and("instance", AllFieldsSearch.entity().getInstanceId(), Op.EQ);
AllFieldsSearch.and("network", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
AllFieldsSearch.and("vmType", AllFieldsSearch.entity().getVmType(), Op.EQ);
AllFieldsSearch.and("address", AllFieldsSearch.entity().getIp4Address(), Op.EQ);
AllFieldsSearch.done();
IpSearch = createSearchBuilder(String.class);
@ -114,4 +115,11 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
sc.setParameters("vmType", vmType);
return findOneBy(sc);
}
@Override
public NicVO findByIp4Address(String ip4Address) {
SearchCriteria<NicVO> sc = AllFieldsSearch.create();
sc.setParameters("address", ip4Address);
return findOneBy(sc);
}
}

View File

@ -61,6 +61,7 @@ DROP TABLE IF EXISTS `cloud`.`sync_queue`;
DROP TABLE IF EXISTS `cloud`.`sync_queue_item`;
DROP TABLE IF EXISTS `cloud`.`security_group_vm_map`;
DROP TABLE IF EXISTS `cloud`.`load_balancer_vm_map`;
DROP TABLE IF EXISTS `cloud`.`load_balancer_inline_ip_map`;
DROP TABLE IF EXISTS `cloud`.`storage_pool`;
DROP TABLE IF EXISTS `cloud`.`storage_pool_host_ref`;
DROP TABLE IF EXISTS `cloud`.`template_spool_ref`;
@ -630,6 +631,17 @@ CREATE TABLE `cloud`.`load_balancer_vm_map` (
CONSTRAINT `fk_load_balancer_vm_map__instance_id` FOREIGN KEY(`instance_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`inline_load_balancer_nic_map` (
`id` bigint unsigned NOT NULL auto_increment,
`load_balancer_id` bigint unsigned NOT NULL,
`public_ip_address` char(40) NOT NULL,
`nic_id` bigint unsigned NULL COMMENT 'nic id',
PRIMARY KEY (`id`),
UNIQUE KEY (`nic_id`),
CONSTRAINT `fk_inline_load_balancer_nic_map__load_balancer_id` FOREIGN KEY(`load_balancer_id`) REFERENCES `load_balancing_rules`(`id`) ON DELETE CASCADE,
CONSTRAINT `fk_inline_load_balancer_nic_map__nic_id` FOREIGN KEY(`nic_id`) REFERENCES `nics`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`port_forwarding_rules` (
`id` bigint unsigned NOT NULL COMMENT 'id',
`instance_id` bigint unsigned NOT NULL COMMENT 'vm instance id',