diff --git a/api/src/com/cloud/agent/api/routing/SetPortForwardingRulesCommand.java b/api/src/com/cloud/agent/api/routing/SetPortForwardingRulesCommand.java index 17b9f11c74b..6ba10555342 100644 --- a/api/src/com/cloud/agent/api/routing/SetPortForwardingRulesCommand.java +++ b/api/src/com/cloud/agent/api/routing/SetPortForwardingRulesCommand.java @@ -20,6 +20,7 @@ package com.cloud.agent.api.routing; import java.util.List; import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.network.rules.PortForwardingRule; public class SetPortForwardingRulesCommand extends RoutingCommand { PortForwardingRuleTO[] rules; @@ -27,8 +28,12 @@ public class SetPortForwardingRulesCommand extends RoutingCommand { protected SetPortForwardingRulesCommand() { } - public SetPortForwardingRulesCommand(List rules) { - this.rules = rules.toArray(new PortForwardingRuleTO[rules.size()]); + public SetPortForwardingRulesCommand(List pfRules) { + rules = new PortForwardingRuleTO[pfRules.size()]; + int i = 0; + for (PortForwardingRule rule : pfRules) { + rules[i++] = new PortForwardingRuleTO(rule); + } } public PortForwardingRuleTO[] getRules() { diff --git a/api/src/com/cloud/agent/api/to/FirewallRuleTO.java b/api/src/com/cloud/agent/api/to/FirewallRuleTO.java index e26be6afb0f..37d6ee4fad3 100644 --- a/api/src/com/cloud/agent/api/to/FirewallRuleTO.java +++ b/api/src/com/cloud/agent/api/to/FirewallRuleTO.java @@ -22,16 +22,18 @@ public class FirewallRuleTO { String protocol; int[] srcPortRange; boolean revoked; + boolean brandNew; String vlanNetmask; // FIXME: Get rid of this! protected FirewallRuleTO() { } - public FirewallRuleTO(String srcIp, String protocol, int srcPortStart, int srcPortEnd, boolean revoked) { + public FirewallRuleTO(String srcIp, String protocol, int srcPortStart, int srcPortEnd, boolean revoked, boolean brandNew) { this.srcIp = srcIp; this.protocol = protocol; this.srcPortRange = new int[] {srcPortStart, srcPortEnd}; this.revoked = revoked; + this.brandNew = brandNew; } public String getSrcIp() { @@ -53,4 +55,8 @@ public class FirewallRuleTO { public String getVlanNetmask() { return vlanNetmask; } + + public boolean isBrandNew() { + return brandNew; + } } diff --git a/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java b/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java index 6ca81d84844..d4ffdf31d01 100644 --- a/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java +++ b/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java @@ -17,6 +17,9 @@ */ package com.cloud.agent.api.to; +import com.cloud.network.rules.FirewallRule.State; +import com.cloud.network.rules.PortForwardingRule; + public class PortForwardingRuleTO extends FirewallRuleTO { String dstIp; int[] dstPortRange; @@ -25,8 +28,12 @@ public class PortForwardingRuleTO extends FirewallRuleTO { super(); } - public PortForwardingRuleTO(String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked) { - super(srcIp, protocol, srcPortStart, srcPortEnd, revoked); + public PortForwardingRuleTO(PortForwardingRule rule) { + this(rule.getSourceIpAddress().addr(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getDestinationIpAddress().addr(), rule.getDestinationPortStart(), rule.getDestinationPortEnd(), rule.getProtocol(), rule.getState() == State.Revoke, rule.getState() == State.Add); + } + + protected PortForwardingRuleTO(String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) { + super(srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew); this.dstIp = dstIp; this.dstPortRange = new int[] { dstPortStart, dstPortEnd }; } diff --git a/api/src/com/cloud/dc/DataCenter.java b/api/src/com/cloud/dc/DataCenter.java index a8b74b378c3..5feee19828e 100644 --- a/api/src/com/cloud/dc/DataCenter.java +++ b/api/src/com/cloud/dc/DataCenter.java @@ -26,4 +26,10 @@ public interface DataCenter extends Grouping { DataCenterNetworkType getNetworkType(); String getInternalDns1(); String getInternalDns2(); + String getDnsProvider(); + String getGatewayProvider(); + String getFirewallProvider(); + String getDhcpProvider(); + String getLoadBalancerProvider(); + } diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java index b5a20a94330..2b9829eec52 100644 --- a/api/src/com/cloud/network/Networks.java +++ b/api/src/com/cloud/network/Networks.java @@ -27,6 +27,15 @@ import com.cloud.utils.exception.CloudRuntimeException; * */ public class Networks { + + public enum Service { + Dhcp, + Dns, + Gateway, + LoadBalancer, + Firewall + } + /** * Different ways to assign ip address to this network. */ diff --git a/api/src/com/cloud/network/configuration/NetworkGuru.java b/api/src/com/cloud/network/configuration/NetworkGuru.java index 5db35d4fdea..4af532e152e 100644 --- a/api/src/com/cloud/network/configuration/NetworkGuru.java +++ b/api/src/com/cloud/network/configuration/NetworkGuru.java @@ -36,48 +36,48 @@ public interface NetworkGuru extends Adapter { /** * allocate a nic in this network. This method implementation cannot take a long time as * it is meant to allocate for the DB. - * @param config configuration to allocate the nic in. + * @param network configuration to allocate the nic in. * @param nic user specified * @param vm virtual machine the network configuraiton will be in. * @return NicProfile. * @throws InsufficientVirtualNetworkCapcityException * @throws InsufficientAddressCapacityException */ - NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException; + NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException; /** * Fully implement the network configuration as specified. - * @param config network configuration + * @param network network configuration * @param offering offering that the network configuration was based on. * @param destination where were deploying to. * @return a fully implemented NetworkConfiguration. */ - Network implement(Network config, NetworkOffering offering, DeployDestination destination, ReservationContext context); + Network implement(Network network, NetworkOffering offering, DeployDestination destination, ReservationContext context); /** * reserve a nic for this VM in this network. * @param nic - * @param config + * @param network * @param vm * @param dest * @return * @throws InsufficientVirtualNetworkCapcityException * @throws InsufficientAddressCapacityException */ - void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException; + void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException; boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId); - void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm); + void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm); - void destroy(Network config, NetworkOffering offering); + void destroy(Network network, NetworkOffering offering); /** * Throw away the design. - * @param config + * @param network * @param offering * @param owner * @return */ - boolean trash(Network config, NetworkOffering offering, Account owner); + boolean trash(Network network, NetworkOffering offering, Account owner); } diff --git a/api/src/com/cloud/network/rules/FirewallRule.java b/api/src/com/cloud/network/rules/FirewallRule.java index 71420ff9235..f73d7b9cedc 100644 --- a/api/src/com/cloud/network/rules/FirewallRule.java +++ b/api/src/com/cloud/network/rules/FirewallRule.java @@ -31,6 +31,7 @@ public interface FirewallRule extends ControlledEntity { enum State { Staged, // Rule been created but has never got through network rule conflict detection. Rules in this state can not be sent to network elements. Add, // Add means the rule has been created and has gone through network rule conflict detection. + Active, // Rule has been sent to the network elements and reported to be active. Revoke // Revoke means this rule has been revoked. If this rule has been sent to the network elements, the rule will be deleted from database. } diff --git a/api/src/com/cloud/user/UserContext.java b/api/src/com/cloud/user/UserContext.java index 7eb2a403c54..d0f0c1498d5 100644 --- a/api/src/com/cloud/user/UserContext.java +++ b/api/src/com/cloud/user/UserContext.java @@ -30,7 +30,7 @@ public class UserContext { private long userId; private String sessionId; - private Account accountObject; + private Account account; private boolean apiServer; @@ -41,7 +41,7 @@ public class UserContext { public UserContext(long userId, Account accountObject, String sessionId, boolean apiServer) { this.userId = userId; - this.accountObject = accountObject; + this.account = accountObject; this.sessionId = sessionId; this.apiServer = apiServer; } @@ -59,11 +59,11 @@ public class UserContext { } public Account getAccount() { - return accountObject; + return account; } public void setAccount(Account accountObject) { - this.accountObject = accountObject; + this.account = accountObject; } public void setSessionKey(String sessionId) { diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index b1ba2a8b619..4c6e99ccb7e 100644 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -164,7 +164,9 @@ public class DefaultComponentLibrary implements ComponentLibrary { info.addParameter("cache.size", "50"); info.addParameter("cache.time.to.live", "600"); addDao("IPAddressDao", IPAddressDaoImpl.class); - addDao("VlanDao", VlanDaoImpl.class); + info = addDao("VlanDao", VlanDaoImpl.class); + info.addParameter("cache.size", "30"); + info.addParameter("cache.time.to.live", "3600"); addDao("PodVlanMapDao", PodVlanMapDaoImpl.class); addDao("AccountVlanMapDao", AccountVlanMapDaoImpl.class); addDao("VolumeDao", VolumeDaoImpl.class); diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index c1a13dd90e3..4bccc3194de 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -77,14 +77,11 @@ import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; -import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; -import com.cloud.domain.DomainVO; import com.cloud.event.Event; import com.cloud.event.EventTypes; import com.cloud.event.EventUtils; @@ -1174,21 +1171,21 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx return net; } - Pair ipAndVlan = _vlanDao.assignIpAddress(dcId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN, VlanType.VirtualNetwork, - true); - - if (ipAndVlan == null) { - s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center : " + dcId); - ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN); - if (ipAndVlan == null) { - s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center : " + dcId); - } - } - if (ipAndVlan != null) { - VlanVO vlan = ipAndVlan.second(); - networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId()); - return net; - } +// Pair ipAndVlan = _vlanDao.assignIpAddress(dcId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN, VlanType.VirtualNetwork, +// true); +// +// if (ipAndVlan == null) { +// s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center : " + dcId); +// ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN); +// if (ipAndVlan == null) { +// s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center : " + dcId); +// } +// } +// if (ipAndVlan != null) { +// VlanVO vlan = ipAndVlan.second(); +// networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId()); +// return net; +// } return null; } diff --git a/server/src/com/cloud/dc/DataCenterVO.java b/server/src/com/cloud/dc/DataCenterVO.java index 77385c8ca6e..0b8f4fe507c 100644 --- a/server/src/com/cloud/dc/DataCenterVO.java +++ b/server/src/com/cloud/dc/DataCenterVO.java @@ -73,6 +73,66 @@ public class DataCenterVO implements DataCenter { @Column(name="networktype") @Enumerated(EnumType.STRING) DataCenterNetworkType networkType; + + @Column(name="dns_provider") + private String dnsProvider; + + @Column(name="dhcp_provider") + private String dhcpProvider; + + @Column(name="gateway_provider") + private String gatewayProvider; + + @Override + public String getDnsProvider() { + return dnsProvider; + } + + public void setDnsProvider(String dnsProvider) { + this.dnsProvider = dnsProvider; + } + + @Override + public String getDhcpProvider() { + return dhcpProvider; + } + + public void setDhcpProvider(String dhcpProvider) { + this.dhcpProvider = dhcpProvider; + } + + @Override + public String getGatewayProvider() { + return gatewayProvider; + } + + public void setGatewayProvider(String gatewayProvider) { + this.gatewayProvider = gatewayProvider; + } + + @Override + public String getLoadBalancerProvider() { + return loadBalancerProvider; + } + + public void setLoadBalancerProvider(String loadBalancerProvider) { + this.loadBalancerProvider = loadBalancerProvider; + } + + @Override + public String getFirewallProvider() { + return firewallProvider; + } + + public void setFirewallProvider(String firewallProvider) { + this.firewallProvider = firewallProvider; + } + + @Column(name="lb_provider") + private String loadBalancerProvider; + + @Column(name="firewall_provider") + private String firewallProvider; @Column(name="mac_address", updatable = false, nullable=false) @TableGenerator(name="mac_address_sq", table="data_center", pkColumnName="id", valueColumnName="mac_address", allocationSize=1) @@ -97,6 +157,7 @@ public class DataCenterVO implements DataCenter { this.networkType = zoneType; } + @Override public Long getDomainId() { return domainId; } @@ -105,6 +166,7 @@ public class DataCenterVO implements DataCenter { this.domainId = domainId; } + @Override public String getDescription() { return description; } @@ -117,22 +179,27 @@ public class DataCenterVO implements DataCenter { this.vnet = vnet; } + @Override public String getDns1() { return dns1; } + @Override public String getVnet() { return vnet; } + @Override public String getDns2() { return dns2; } + @Override public String getInternalDns1() { return internalDns1; } + @Override public String getInternalDns2() { return internalDns2; } @@ -145,7 +212,8 @@ public class DataCenterVO implements DataCenter { return id; } - public String getName() { + @Override + public String getName() { return name; } @@ -173,6 +241,7 @@ public class DataCenterVO implements DataCenter { this.routerMacAddress = routerMacAddress; } + @Override public String getGuestNetworkCidr() { return guestNetworkCidr; @@ -183,6 +252,7 @@ public class DataCenterVO implements DataCenter { this.guestNetworkCidr = guestNetworkCidr; } + @Override public String getDomain() { return domain; } @@ -195,6 +265,7 @@ public class DataCenterVO implements DataCenter { this.networkType = zoneNetworkType; } + @Override public DataCenterNetworkType getNetworkType() { return networkType; } diff --git a/server/src/com/cloud/dc/dao/VlanDao.java b/server/src/com/cloud/dc/dao/VlanDao.java index 047cfc263c7..a3f39f464ab 100644 --- a/server/src/com/cloud/dc/dao/VlanDao.java +++ b/server/src/com/cloud/dc/dao/VlanDao.java @@ -23,7 +23,6 @@ import java.util.List; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; -import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; public interface VlanDao extends GenericDao { @@ -40,11 +39,11 @@ public interface VlanDao extends GenericDao { void addToPod(long podId, long vlanDbId); - Pair assignIpAddress(long zoneId, long accountId, long domainId, VlanType vlanType, boolean sourceNat); +// Pair assignIpAddress(long zoneId, long accountId, long domainId, VlanType vlanType, boolean sourceNat); List listVlansForAccountByType(Long zoneId, long accountId, VlanType vlanType); - Pair assignPodDirectAttachIpAddress(long zoneId, long podId, long accountId, long domainId); +// Pair assignPodDirectAttachIpAddress(long zoneId, long podId, long accountId, long domainId); boolean zoneHasDirectAttachUntaggedVlans(long zoneId); diff --git a/server/src/com/cloud/dc/dao/VlanDaoImpl.java b/server/src/com/cloud/dc/dao/VlanDaoImpl.java index 14d1419a06c..03f463aa0f5 100644 --- a/server/src/com/cloud/dc/dao/VlanDaoImpl.java +++ b/server/src/com/cloud/dc/dao/VlanDaoImpl.java @@ -234,19 +234,6 @@ public class VlanDaoImpl extends GenericDaoBase implements VlanDao return emptyVlans.get(0); } - @Override - public Pair assignIpAddress(long zoneId, long accountId, long domainId, VlanType vlanType, boolean sourceNat) { - VlanVO vlan = findNextVlan(zoneId, vlanType); - if (vlan == null) { - return null; - } - String ipAddress = _ipAddressDao.assignIpAddress(accountId, domainId, vlan.getId(), sourceNat).getAddress(); - if (ipAddress == null) { - return null; - } - return new Pair(ipAddress, vlan); - } - @Override public boolean zoneHasDirectAttachUntaggedVlans(long zoneId) { SearchCriteria sc = ZoneTypeAllPodsSearch.create(); @@ -257,7 +244,6 @@ public class VlanDaoImpl extends GenericDaoBase implements VlanDao } - @Override public Pair assignPodDirectAttachIpAddress(long zoneId, long podId, long accountId, long domainId) { SearchCriteria sc = ZoneTypePodSearch.create(); @@ -270,11 +256,12 @@ public class VlanDaoImpl extends GenericDaoBase implements VlanDao return null; } - String ipAddress = _ipAddressDao.assignIpAddress(accountId, domainId, vlan.getId(), false).getAddress(); - if (ipAddress == null) { - return null; - } - return new Pair(ipAddress, vlan); + return null; +// String ipAddress = _ipAddressDao.assignIpAddress(accountId, domainId, vlan.getId(), false).getAddress(); +// if (ipAddress == null) { +// return null; +// } +// return new Pair(ipAddress, vlan); } diff --git a/server/src/com/cloud/network/IPAddressVO.java b/server/src/com/cloud/network/IPAddressVO.java index 0ea5fa11d59..3b7be26d536 100644 --- a/server/src/com/cloud/network/IPAddressVO.java +++ b/server/src/com/cloud/network/IPAddressVO.java @@ -62,6 +62,9 @@ public class IPAddressVO implements IpAddress { @Column(name="state") private State state; + + @Column(name="mac_address") + private long macAddress; protected IPAddressVO() { } @@ -71,7 +74,7 @@ public class IPAddressVO implements IpAddress { return state == State.Allocated; } - public IPAddressVO(String address, long dataCenterId, long vlanDbId, boolean sourceNat) { + public IPAddressVO(String address, long dataCenterId, long macAddress, long vlanDbId, boolean sourceNat) { this.address = address; this.dataCenterId = dataCenterId; this.vlanId = vlanDbId; @@ -80,6 +83,11 @@ public class IPAddressVO implements IpAddress { this.allocatedToAccountId = null; this.allocatedTime = null; this.state = State.Free; + this.macAddress = macAddress; + } + + public long getMacAddress() { + return macAddress; } @Override diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index cc1bceb376c..6dd205afcc4 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -19,8 +19,6 @@ package com.cloud.network; import java.util.List; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.exception.ConcurrentOperationException; @@ -29,7 +27,7 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.addr.PublicIp; import com.cloud.network.rules.FirewallRule; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.service.ServiceOfferingVO; @@ -50,8 +48,20 @@ import com.cloud.vm.VirtualMachineProfile; * */ public interface NetworkManager extends NetworkService { - public static final int DEFAULT_ROUTER_VM_RAMSIZE = 128; // 128M public static final boolean USE_POD_VLAN = false; + + /** + * assigns a source nat ip address to an account within a network. + * + * @param owner + * @param network + * @param callerId + * @return + * @throws ConcurrentOperationException + * @throws InsufficientAddressCapacityException + */ + PublicIp assignSourceNatIpAddress(Account owner, Network network, long callerId) throws ConcurrentOperationException, InsufficientAddressCapacityException; + /** * Do all of the work of releasing public ip addresses. Note that * if this method fails, there can be side effects. @@ -59,19 +69,7 @@ public interface NetworkManager extends NetworkService { * @param ipAddress * @return true if it did; false if it didn't */ - public boolean releasePublicIpAddress(long userId, String ipAddress); - - /** - * Find or create the source nat ip address a user uses within the - * data center. - * - * @param account account - * @param dc data center - * @param domain domain used for user's network. - * @param so service offering associated with this request - * @return public ip address. - */ - public String assignSourceNatIpAddress(Account account, DataCenterVO dc, String domain, ServiceOfferingVO so, long startEventId, HypervisorType hyperType) throws ResourceAllocationException; + public boolean releasePublicIpAddress(String ipAddress, long ownerId, long userId); /** * Associates or disassociates a list of public IP address for a router. @@ -132,7 +130,6 @@ public interface NetworkManager extends NetworkService { List setupNetworkConfiguration(Account owner, ServiceOfferingVO offering, DeploymentPlan plan); - String assignSourceNatIpAddress(Account account, DataCenter dc) throws InsufficientAddressCapacityException; Network getNetwork(long id); String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 6778bb37330..a5539e7098f 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,7 +60,6 @@ import com.cloud.configuration.ResourceCount.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceLimitDao; import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; @@ -88,10 +88,10 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.dao.HostDao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Networks.AddressFormat; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.addr.PublicIp; import com.cloud.network.configuration.NetworkGuru; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; @@ -139,6 +139,7 @@ import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.JoinBuilder.JoinType; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Ip; @@ -216,253 +217,133 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag ScheduledExecutorService _executor; SearchBuilder AccountsUsingNetworkConfigurationSearch; + SearchBuilder AssignIpAddressSearch; + SearchBuilder IpAddressSearch; private Map _configs; + + @DB + protected PublicIp fetchNewPublicIp(long dcId, VlanType vlanUse, Account owner, boolean sourceNat) throws InsufficientAddressCapacityException { + Transaction txn = Transaction.currentTxn(); + txn.start(); + SearchCriteria sc = AssignIpAddressSearch.create(); + sc.setParameters("dc", dcId); + sc.setJoinParameters("vlan", "vlanType", vlanUse); + + Filter filter = new Filter(IPAddressVO.class, "vlanId", true, 0l, 1l); + + List addrs = _ipAddressDao.lockRows(sc, filter, true); + assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size(); + + if (addrs.size() == 0) { + throw new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId); + } + + IPAddressVO addr = addrs.get(0); + addr.setSourceNat(sourceNat); + addr.setAllocatedTime(new Date()); + addr.setAllocatedInDomainId(owner.getDomainId()); + addr.setAllocatedToAccountId(owner.getId()); + + if (!_ipAddressDao.update(addr.getAddress(), addr)) { + throw new CloudRuntimeException("Found address to allocate but unable to update: " + addr); + } + + txn.commit(); + return new PublicIp(addr, _vlanDao.findById(addr.getVlanId())); + } + @Override + public PublicIp assignSourceNatIpAddress(Account owner, Network network, long callerId) throws ConcurrentOperationException, InsufficientAddressCapacityException { + assert ((network.getTrafficType() == TrafficType.Public) || (network.getTrafficType() == TrafficType.Guest && network.getGuestType() == GuestIpType.Direct)) : "You're asking for a source nat but your network can't participate in source nat. What do you have to say for yourself?"; + + long dcId = network.getDataCenterId(); + long ownerId = owner.getId(); - @Override @DB - public String assignSourceNatIpAddress(Account account, final DataCenterVO dc, final String domain, final ServiceOfferingVO serviceOffering, long startEventId, HypervisorType hyperType) throws ResourceAllocationException { - if (serviceOffering.getGuestIpType() == NetworkOffering.GuestIpType.Direct) { - return null; - } - final long dcId = dc.getId(); - String sourceNat = null; - - final long accountId = account.getId(); + final EventVO event = new EventVO(); + event.setUserId(callerId); // system user performed the action... + event.setAccountId(ownerId); + event.setType(EventTypes.EVENT_NET_IP_ASSIGN); + PublicIp ip = null; + Transaction txn = Transaction.currentTxn(); try { - final EventVO event = new EventVO(); - event.setUserId(1L); // system user performed the action... - event.setAccountId(account.getId()); - event.setType(EventTypes.EVENT_NET_IP_ASSIGN); - txn.start(); - account = _accountDao.acquireInLockTable(accountId); - if (account == null) { - s_logger.warn("Unable to lock account " + accountId); - return null; + owner = _accountDao.acquireInLockTable(ownerId); + if (owner == null) { + throw new ConcurrentOperationException("Unable to lock account " + ownerId); } - if(s_logger.isDebugEnabled()) { - s_logger.debug("lock account " + accountId + " is acquired"); - } - - boolean isAccountIP = false; - List addrs = listPublicIpAddressesInVirtualNetwork(account.getId(), dcId, true); - if (addrs.size() == 0) { - - // Check that the maximum number of public IPs for the given accountId will not be exceeded - if (_accountMgr.resourceLimitExceeded(account, ResourceType.public_ip)) { - ResourceAllocationException rae = new ResourceAllocationException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded."); - rae.setResourceType("ip"); - throw rae; - } - - //check for account specific IP pool. - addrs = listPublicIpAddressesInVirtualNetwork(account.getId(), dcId, null); - if (addrs.size() == 0){ - - if (s_logger.isDebugEnabled()) { - s_logger.debug("assigning a new ip address"); - } - Pair ipAndVlan = _vlanDao.assignIpAddress(dc.getId(), accountId, account.getDomainId(), VlanType.VirtualNetwork, true); - - if (ipAndVlan != null) { - sourceNat = ipAndVlan.first(); - - // Increment the number of public IPs for this accountId in the database - _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); - event.setParameters("address=" + sourceNat + "\nsourceNat=true\ndcId="+dcId); - event.setDescription("Acquired a public ip: " + sourceNat); - _eventDao.persist(event); - } - }else{ - isAccountIP = true; - sourceNat = addrs.get(0).getAddress(); - _ipAddressDao.setIpAsSourceNat(sourceNat); - s_logger.debug("assigning a new ip address " +sourceNat); - - // Increment the number of public IPs for this accountId in the database - _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); - event.setParameters("address=" + sourceNat + "\nsourceNat=true\ndcId="+dcId); - event.setDescription("Acquired a public ip: " + sourceNat); - _eventDao.persist(event); - } - - } else { - sourceNat = addrs.get(0).getAddress(); - } - - if (sourceNat == null) { - txn.rollback(); - event.setLevel(EventVO.LEVEL_ERROR); - event.setParameters("dcId=" + dcId); - event.setDescription("Failed to acquire a public ip."); - _eventDao.persist(event); - s_logger.error("Unable to get source nat ip address for account " + account.getId()); - return null; - } - - UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dcId); - if (stats == null) { - stats = new UserStatisticsVO(account.getId(), dcId); - _userStatsDao.persist(stats); - } - - txn.commit(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Source Nat is " + sourceNat); + s_logger.debug("lock account " + ownerId + " is acquired"); } - DomainRouterVO router = null; - try { - router = _routerMgr.createRouter(account.getId(), sourceNat, dcId, domain, serviceOffering, startEventId); - } catch (final Exception e) { - s_logger.error("Unable to create router for " + account.getAccountName(), e); - } - - if (router != null) { + IPAddressVO sourceNat = null; + List addrs = listPublicIpAddressesInVirtualNetwork(ownerId, dcId, null); + if (addrs.size() == 0) { + // Check that the maximum number of public IPs for the given accountId will not be exceeded + if (_accountMgr.resourceLimitExceeded(owner, ResourceType.public_ip)) { + throw new AccountLimitException("Maximum number of public IP addresses for account: " + owner.getAccountName() + " has been exceeded."); + } + if (s_logger.isDebugEnabled()) { - s_logger.debug("Router is " + router.getHostName()); - } - return sourceNat; - } - - s_logger.warn("releasing the source nat because router was not created: " + sourceNat); - txn.start(); - if(isAccountIP){ - _ipAddressDao.unassignIpAsSourceNat(sourceNat); - }else{ - _ipAddressDao.unassignIpAddress(sourceNat); - } - - _accountMgr.decrementResourceCount(accountId, ResourceType.public_ip); - EventVO event2 = new EventVO(); - event2.setUserId(1L); - event2.setAccountId(account.getId()); - event2.setType(EventTypes.EVENT_NET_IP_RELEASE); - event2.setParameters("address=" + sourceNat + "\nsourceNat=true"); - event2.setDescription("released source nat ip " + sourceNat + " since router could not be started"); - _eventDao.persist(event2); - txn.commit(); - return null; - } finally { - if (account != null) { - if(s_logger.isDebugEnabled()) { - s_logger.debug("Releasing lock account " + accountId); - } - - _accountDao.releaseFromLockTable(accountId); - } - } - } - - @Override @DB - public String assignSourceNatIpAddress(Account account, DataCenter dc) throws InsufficientAddressCapacityException { - final long dcId = dc.getId(); - final long accountId = account.getId(); - String sourceNat = null; - - - Transaction txn = Transaction.currentTxn(); - try { - final EventVO event = new EventVO(); - event.setUserId(1L); // system user performed the action... - event.setAccountId(account.getId()); - event.setType(EventTypes.EVENT_NET_IP_ASSIGN); - - txn.start(); - - account = _accountDao.acquireInLockTable(accountId); - if (account == null) { - s_logger.warn("Unable to lock account " + accountId); - return null; - } - if(s_logger.isDebugEnabled()) { - s_logger.debug("lock account " + accountId + " is acquired"); - } - - boolean isAccountIP = false; - List addrs = listPublicIpAddressesInVirtualNetwork(account.getId(), dcId, true); - if (addrs.size() == 0) { - - // Check that the maximum number of public IPs for the given accountId will not be exceeded - if (_accountMgr.resourceLimitExceeded(account, ResourceType.public_ip)) { - throw new AccountLimitException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded."); - } - - //check for account specific IP pool. - addrs = listPublicIpAddressesInVirtualNetwork(account.getId(), dcId, null); - if (addrs.size() == 0){ - - if (s_logger.isDebugEnabled()) { - s_logger.debug("assigning a new ip address"); - } - Pair ipAndVlan = _vlanDao.assignIpAddress(dc.getId(), accountId, account.getDomainId(), VlanType.VirtualNetwork, true); - - if (ipAndVlan != null) { - sourceNat = ipAndVlan.first(); - - // Increment the number of public IPs for this accountId in the database - _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); - event.setParameters("address=" + sourceNat + "\nsourceNat=true\ndcId="+dcId); - event.setDescription("Acquired a public ip: " + sourceNat); - _eventDao.persist(event); - } - }else{ - isAccountIP = true; - sourceNat = addrs.get(0).getAddress(); - _ipAddressDao.setIpAsSourceNat(sourceNat); - s_logger.debug("assigning a new ip address " +sourceNat); - - // Increment the number of public IPs for this accountId in the database - _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); - event.setParameters("address=" + sourceNat + "\nsourceNat=true\ndcId="+dcId); - event.setDescription("Acquired a public ip: " + sourceNat); - _eventDao.persist(event); - } + s_logger.debug("assigning a new ip address in " + dcId + " to " + owner); + } + + ip = fetchNewPublicIp(dcId, VlanType.VirtualNetwork, owner, true); + sourceNat = ip.ip(); + sourceNat.setState(IpAddress.State.Allocated); + _ipAddressDao.update(sourceNat.getAddress(), sourceNat); + // Increment the number of public IPs for this accountId in the database + _accountMgr.incrementResourceCount(ownerId, ResourceType.public_ip); + event.setParameters("address=" + ip.getAddress() + "\nsourceNat=true\ndcId="+dcId); + event.setDescription("Acquired a public ip: " + ip.getAddress()); + _eventDao.persist(event); } else { - sourceNat = addrs.get(0).getAddress(); + // Account already has ip addresses + + for (IPAddressVO addr : addrs) { + if (addr.isSourceNat()) { + sourceNat = addr; + break; + } + } + + assert(sourceNat != null) : "How do we get a bunch of ip addresses but none of them are source nat? account=" + ownerId + "; dc=" + dcId; + ip = new PublicIp(sourceNat, _vlanDao.findById(sourceNat.getVlanId())); } + + UserStatisticsVO stats = _userStatsDao.findBy(ownerId, dcId); + if (stats == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating statistics for the owner: " + ownerId); + } + stats = new UserStatisticsVO(ownerId, dcId); + _userStatsDao.persist(stats); + } + txn.commit(); + return ip; + } finally { + if (owner != null) { + if(s_logger.isDebugEnabled()) { + s_logger.debug("Releasing lock account " + ownerId); + } - if (sourceNat == null) { + _accountDao.releaseFromLockTable(ownerId); + } + if (ip == null) { txn.rollback(); event.setLevel(EventVO.LEVEL_ERROR); event.setParameters("dcId=" + dcId); event.setDescription("Failed to acquire a public ip."); _eventDao.persist(event); - s_logger.error("Unable to get source nat ip address for account " + account.getId()); - return null; - } - - UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dcId); - if (stats == null) { - stats = new UserStatisticsVO(account.getId(), dcId); - _userStatsDao.persist(stats); - } - - txn.commit(); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Source Nat is " + sourceNat); - } - - return sourceNat; - - } finally { - if (account != null) { - if(s_logger.isDebugEnabled()) { - s_logger.debug("Releasing lock account " + accountId); - } - - _accountDao.releaseFromLockTable(accountId); + s_logger.error("Unable to get source nat ip address for account " + ownerId); } } } - + @Override public boolean associateIP(final DomainRouterVO router, final List ipAddrList, final boolean add, long vmId) { Commands cmds = new Commands(OnError.Continue); @@ -645,7 +526,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag txn.start(); String ipAddress = null; - Pair ipAndVlan = _vlanDao.assignIpAddress(zoneId, accountId, domainId, VlanType.VirtualNetwork, false); + Pair ipAndVlan = null;//FIXME d_vlanDao.assignIpAddress(zoneId, accountId, domainId, VlanType.VirtualNetwork, false); if (ipAndVlan == null) { throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zoneId); @@ -754,40 +635,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return answers[0].getResult(); } - @DB - protected IPAddressVO releaseOwnershipOfIpAddress(String ipAddress) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - IPAddressVO ip = _ipAddressDao.lockRow(ipAddress, true); - if (ip == null) { - s_logger.warn("Unable to find allocated ip: " + ipAddress); - return null; - } - - if (ip.getAllocatedTime() == null) { - s_logger.debug("Ip Address is already rleeased: " + ipAddress); - return null; - } - - ip.setAllocatedToAccountId(null); - ip.setAllocatedInDomainId(null); - _ipAddressDao.update(ip.getAddress(), ip); - txn.commit(); - return ip; - } - @Override - public boolean releasePublicIpAddress(long userId, final String ipAddress) { - IPAddressVO ip = releaseOwnershipOfIpAddress(ipAddress); + public boolean releasePublicIpAddress(String ipAddress, long ownerId, long userId) { + IPAddressVO ip = _ipAddressDao.markAsUnavailable(ipAddress, ownerId); + assert (ip != null) : "Unable to mark the ip address " + ipAddress + " owned by " + ownerId + " as unavailable."; if (ip == null) { return true; } - Ip addr = new Ip(ipAddress); - if (s_logger.isDebugEnabled()) { s_logger.debug("Releasing ip " + ipAddress + "; sourceNat = " + ip.isSourceNat()); } + + Ip addr = new Ip(ip.getAddress()); boolean success = true; try { @@ -828,47 +688,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag _eventDao.persist(event); return success; - -// List loadBalancers = _loadBalancerDao.listByIpAddress(ipAddress); -// for (LoadBalancerVO loadBalancer : loadBalancers) { -// _loadBalancerDao.remove(loadBalancer.getId()); -// -// // save off an event for removing the load balancer -// EventVO event = new EventVO(); -// event.setUserId(userId); -// event.setAccountId(ip.getAccountId()); -// event.setType(EventTypes.EVENT_LOAD_BALANCER_DELETE); -// String params = "id="+loadBalancer.getId(); -// event.setParameters(params); -// event.setDescription("Successfully deleted load balancer " + loadBalancer.getId()); -// event.setLevel(EventVO.LEVEL_INFO); -// _eventDao.persist(event); -// } - -// if ((router != null) && (router.getState() == State.Running)) { -// if (s_logger.isDebugEnabled()) { -// s_logger.debug("Disassociate ip " + router.getHostName()); -// } -// -// if (associateIP(router, ip.getAddress(), false, 0)) { -// _ipAddressDao.unassignIpAddress(ipAddress); -// } else { -// if (s_logger.isDebugEnabled()) { -// s_logger.debug("Unable to dissociate IP : " + ipAddress + " due to failing to dissociate with router: " + router.getHostName()); -// } -// -// final EventVO event = new EventVO(); -// event.setUserId(userId); -// event.setAccountId(ip.getAccountId()); -// event.setType(EventTypes.EVENT_NET_IP_RELEASE); -// event.setLevel(EventVO.LEVEL_ERROR); -// event.setParameters("address=" + ipAddress + "\nsourceNat="+ip.isSourceNat()); -// event.setDescription("failed to released a public ip: " + ipAddress + " due to failure to disassociate with router " + router.getHostName()); -// _eventDao.persist(event); -// -// return false; -// } -// } else { } private Integer getIntegerConfigValue(String configKey, Integer dflt) { @@ -946,12 +765,28 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag networkAccountSearch.and("config", networkAccountSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); networkAccountSearch.and("owner", networkAccountSearch.entity().isOwner(), SearchCriteria.Op.EQ); AccountsUsingNetworkConfigurationSearch.done(); + + AssignIpAddressSearch = _ipAddressDao.createSearchBuilder(); + SearchBuilder vlanSearch = _vlanDao.createSearchBuilder(); + AssignIpAddressSearch.and("dc", AssignIpAddressSearch.entity().getDataCenterId(), Op.EQ); + AssignIpAddressSearch.and("allocated", AssignIpAddressSearch.entity().getAllocatedTime(), Op.NULL); + AssignIpAddressSearch.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER); + vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); + AssignIpAddressSearch.done(); + + IpAddressSearch = _ipAddressDao.createSearchBuilder(); + IpAddressSearch.and("accountId", IpAddressSearch.entity().getAllocatedToAccountId(), Op.EQ); + IpAddressSearch.and("dataCenterId", IpAddressSearch.entity().getDataCenterId(), Op.EQ); + SearchBuilder virtualNetworkVlanSB = _vlanDao.createSearchBuilder(); + virtualNetworkVlanSB.and("vlanType", virtualNetworkVlanSB.entity().getVlanType(), Op.EQ); + IpAddressSearch.join("virtualNetworkVlanSB", virtualNetworkVlanSB, IpAddressSearch.entity().getVlanId(), virtualNetworkVlanSB.entity().getId(), JoinBuilder.JoinType.INNER); + IpAddressSearch.done(); s_logger.info("Network Manager is configured."); return true; } - + @Override public String getName() { return _name; @@ -981,26 +816,15 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat) { - SearchBuilder ipAddressSB = _ipAddressDao.createSearchBuilder(); - ipAddressSB.and("accountId", ipAddressSB.entity().getAllocatedToAccountId(), SearchCriteria.Op.EQ); - ipAddressSB.and("dataCenterId", ipAddressSB.entity().getDataCenterId(), SearchCriteria.Op.EQ); + SearchCriteria sc = IpAddressSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("dataCenterId", dcId); if (sourceNat != null) { - ipAddressSB.and("sourceNat", ipAddressSB.entity().isSourceNat(), SearchCriteria.Op.EQ); + sc.addAnd("sourceNat", SearchCriteria.Op.EQ, sourceNat); } + sc.setJoinParameters("virtualNetworkVlanSB", "vlanType", VlanType.VirtualNetwork); - SearchBuilder virtualNetworkVlanSB = _vlanDao.createSearchBuilder(); - virtualNetworkVlanSB.and("vlanType", virtualNetworkVlanSB.entity().getVlanType(), SearchCriteria.Op.EQ); - ipAddressSB.join("virtualNetworkVlanSB", virtualNetworkVlanSB, ipAddressSB.entity().getVlanId(), virtualNetworkVlanSB.entity().getId(), JoinBuilder.JoinType.INNER); - - SearchCriteria ipAddressSC = ipAddressSB.create(); - ipAddressSC.setParameters("accountId", accountId); - ipAddressSC.setParameters("dataCenterId", dcId); - if (sourceNat != null) { - ipAddressSC.setParameters("sourceNat", sourceNat); - } - ipAddressSC.setJoinParameters("virtualNetworkVlanSB", "vlanType", VlanType.VirtualNetwork); - - return _ipAddressDao.search(ipAddressSC, null); + return _ipAddressDao.search(sc, null); } @Override @@ -1409,7 +1233,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } txn.start(); - boolean success = releasePublicIpAddress(userId, ipAddress); + boolean success = releasePublicIpAddress(ipAddress, accountId, userId); if (success) { _accountMgr.decrementResourceCount(accountId, ResourceType.public_ip); } diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index a83d54816c1..2ed12346c43 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -118,6 +118,9 @@ public class NetworkVO implements Network { @Column(name="shared") boolean isShared; + @Column(name="network_domain") + String networkDomain; + public NetworkVO() { } @@ -250,6 +253,14 @@ public class NetworkVO implements Network { public void setBroadcastDomainType(BroadcastDomainType broadcastDomainType) { this.broadcastDomainType = broadcastDomainType; } + + public String getNetworkDomain() { + return networkDomain; + } + + public void setNetworkDomain(String networkDomain) { + this.networkDomain = networkDomain; + } @Override public TrafficType getTrafficType() { diff --git a/server/src/com/cloud/network/configuration/PublicNetworkGuru.java b/server/src/com/cloud/network/configuration/PublicNetworkGuru.java index a83a03af718..1d1b432e599 100644 --- a/server/src/com/cloud/network/configuration/PublicNetworkGuru.java +++ b/server/src/com/cloud/network/configuration/PublicNetworkGuru.java @@ -25,10 +25,12 @@ import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.NetworkOffering; import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; +import com.cloud.user.UserContext; import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; @@ -63,9 +65,10 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { super(); } - protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException { + protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException { if (nic.getIp4Address() == null) { - Pair ipAndVlan = _vlanDao.assignIpAddress(dc.getId(), vm.getVirtualMachine().getAccountId(), vm.getVirtualMachine().getDomainId(), VlanType.VirtualNetwork, true); + PublicIp ip = _networkMgr.assignSourceNatIpAddress(dc, vm.getOwner(), network, UserContext.current().getUserId()); + Pair ipAndVlan = __vlanDao.assignIpAddress(dc.getId(), vm.getVirtualMachine().getAccountId(), vm.getVirtualMachine().getDomainId(), VlanType.VirtualNetwork, true); if (ipAndVlan == null) { throw new InsufficientVirtualNetworkCapcityException("Unable to get public ip address in " + dc.getId(), DataCenter.class, dc.getId()); } diff --git a/server/src/com/cloud/network/dao/IPAddressDao.java b/server/src/com/cloud/network/dao/IPAddressDao.java index 73b1d45327c..4b9d57f7ecf 100644 --- a/server/src/com/cloud/network/dao/IPAddressDao.java +++ b/server/src/com/cloud/network/dao/IPAddressDao.java @@ -24,31 +24,26 @@ import com.cloud.network.IPAddressVO; import com.cloud.utils.db.GenericDao; public interface IPAddressDao extends GenericDao { - - /** - * @param accountId account id - * @param domainId id of the account's domain - * @param dcId data center id - * @param sourceNat is it for source nat? - * @return public ip address - */ - public IPAddressVO assignIpAddress(long accountId, long domainId, long vlanDbId, boolean sourceNat); - - public void unassignIpAddress(String ipAddress); + + IPAddressVO markAsUnavailable(String ipAddress, long ownerId); + + void unassignIpAddress(String ipAddress); - public List listByAccount(long accountId); + List listByAccount(long accountId); - public List listByDcIdIpAddress(long dcId, String ipAddress); + List listByDcIdIpAddress(long dcId, String ipAddress); - public int countIPs(long dcId, long vlanDbId, boolean onlyCountAllocated); + int countIPs(long dcId, long vlanDbId, boolean onlyCountAllocated); - public int countIPs(long dcId, Long accountId, String vlanId, String vlanGateway, String vlanNetmask); + int countIPs(long dcId, Long accountId, String vlanId, String vlanGateway, String vlanNetmask); - public boolean mark(long dcId, String ip); + boolean mark(long dcId, String ip); - public List assignAcccountSpecificIps(long accountId, long longValue, Long vlanDbId, boolean sourceNat); + List assignAcccountSpecificIps(long accountId, long longValue, Long vlanDbId, boolean sourceNat); - public void setIpAsSourceNat(String ipAddr); + void setIpAsSourceNat(String ipAddr); - void unassignIpAsSourceNat(String ipAddress); + void unassignIpAsSourceNat(String ipAddress); + + } diff --git a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java index 2560eb36d99..0f9c277581c 100644 --- a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java +++ b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java @@ -54,16 +54,16 @@ public class IPAddressDaoImpl extends GenericDaoBase implem // make it public for JUnit test public IPAddressDaoImpl() { AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("dataCenterId", AllFieldsSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getAddress(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("dataCenterId", AllFieldsSearch.entity().getDataCenterId(), Op.EQ); + AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getAddress(), Op.EQ); AllFieldsSearch.and("vlan", AllFieldsSearch.entity().getVlanId(), Op.EQ); AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAllocatedToAccountId(), Op.EQ); - AllFieldsSearch.and("sourceNat", AllFieldsSearch.entity().isSourceNat(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("sourceNat", AllFieldsSearch.entity().isSourceNat(), Op.EQ); AllFieldsSearch.done(); VlanDbIdSearchUnallocated = createSearchBuilder(); - VlanDbIdSearchUnallocated.and("allocated", VlanDbIdSearchUnallocated.entity().getAllocatedTime(), SearchCriteria.Op.NULL); - VlanDbIdSearchUnallocated.and("vlanDbId", VlanDbIdSearchUnallocated.entity().getVlanId(), SearchCriteria.Op.EQ); + VlanDbIdSearchUnallocated.and("allocated", VlanDbIdSearchUnallocated.entity().getAllocatedTime(), Op.NULL); + VlanDbIdSearchUnallocated.and("vlanDbId", VlanDbIdSearchUnallocated.entity().getVlanId(), Op.EQ); VlanDbIdSearchUnallocated.done(); AllIpCount = createSearchBuilder(Integer.class); @@ -131,8 +131,6 @@ public class IPAddressDaoImpl extends GenericDaoBase implem update(ipAddr, ip); } - @Override - @DB public IPAddressVO assignIpAddress(long accountId, long domainId, long vlanDbId, boolean sourceNat) { Transaction txn = Transaction.currentTxn(); txn.start(); @@ -232,4 +230,19 @@ public class IPAddressDaoImpl extends GenericDaoBase implem return ipCount; } + + @Override @DB + public IPAddressVO markAsUnavailable(String ipAddress, long ownerId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("accountId", ownerId); + sc.setParameters("ipAddress", ipAddress); + + IPAddressVO ip = createForUpdate(); + ip.setState(State.Releasing); + if (update(ip, sc) != 1) { + return null; + } + + return findOneBy(sc); + } } diff --git a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java index 3bc81f488f3..2a8e502999f 100644 --- a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java +++ b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java @@ -18,6 +18,9 @@ package com.cloud.network.router; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -52,8 +55,10 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.IPAssocCommand; import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; import com.cloud.agent.api.routing.SavePasswordCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.manager.Commands; @@ -106,6 +111,7 @@ import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.DomainRouterService; import com.cloud.network.IPAddressVO; +import com.cloud.network.IpAddress; import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; @@ -122,7 +128,9 @@ import com.cloud.network.dao.NetworkRuleConfigDao; import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.VpnUserDao; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.PortForwardingRuleVO; +import com.cloud.network.rules.RulesManager; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; @@ -228,6 +236,7 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute @Inject VmManager _itMgr; @Inject VpnUserDao _vpnUsersDao; @Inject RemoteAccessVpnDao _remoteAccessVpnDao; + @Inject RulesManager _rulesMgr; long _routerTemplateId = -1; int _routerRamSize; @@ -316,7 +325,7 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute return rtrs.get(0); } String mgmtNetmask = NetUtils.getCidrNetmask(pod.getCidrSize()); - final String guestIp = _ipAddressDao.assignIpAddress(accountIdForDHCPServer, domainIdForDHCPServer, guestVlan.getId(), false).getAddress(); + final String guestIp = null;//_ipAddressDao.assignIpAddress(accountIdForDHCPServer, domainIdForDHCPServer, guestVlan.getId(), false).getAddress(); router = new DomainRouterVO(id, @@ -2425,8 +2434,108 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute return router; } - private boolean resendRouterState(Network config, DomainRouterVO router, Commands cmds) { + private void reconstructRouterPortForwardingRules(Commands cmds, List ipAddrs) { + List rules = _rulesMgr.gatherPortForwardingRulesForApplication(ipAddrs); + if (rules.size() == 0) { + s_logger.debug("There are not port forwarding rules to send. "); + return; + } + SetPortForwardingRulesCommand pfrCmd = new SetPortForwardingRulesCommand(rules); + cmds.addCommand(pfrCmd); + } + /* + private List reconstructRouterIpAssocations(Commands cmds, VirtualRouter router) { + List ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(router.getAccountId(), router.getDataCenterId(), null); + + } + */ + + public boolean associateIP(final DomainRouterVO router, final List ipAddrList, final boolean add, long vmId) { + Commands cmds = new Commands(OnError.Continue); + boolean sourceNat = false; + Map> vlanIpMap = new HashMap>(); + for (final String ipAddress: ipAddrList) { + IPAddressVO ip = _ipAddressDao.findById(ipAddress); + + VlanVO vlan = _vlanDao.findById(ip.getVlanId()); + ArrayList ipList = vlanIpMap.get(vlan.getId()); + if (ipList == null) { + ipList = new ArrayList(); + } + ipList.add(ip); + vlanIpMap.put(vlan, ipList); + } + for (Map.Entry> vlanAndIp: vlanIpMap.entrySet()) { + boolean firstIP = true; + ArrayList ipList = vlanAndIp.getValue(); + Collections.sort(ipList, new Comparator() { + @Override + public int compare(IPAddressVO o1, IPAddressVO o2) { + return o1.getAddress().compareTo(o2.getAddress()); + } }); + + for (final IPAddressVO ip: ipList) { + sourceNat = ip.isSourceNat(); + VlanVO vlan = vlanAndIp.getKey(); + String vlanId = vlan.getVlanId(); + String vlanGateway = vlan.getVlanGateway(); + String vlanNetmask = vlan.getVlanNetmask(); + + String vifMacAddress = null; + if (firstIP && add) { + String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(ip.getDataCenterId()); + vifMacAddress = macAddresses[1]; + } + String vmGuestAddress = null; + if(vmId!=0){ + vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); + } + + cmds.addCommand(new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress)); + + firstIP = false; + } + } + + Answer[] answers = null; + try { + answers = _agentMgr.send(router.getHostId(), cmds); + } catch (final AgentUnavailableException e) { + s_logger.warn("Agent unavailable", e); + return false; + } catch (final OperationTimedoutException e) { + s_logger.warn("Timed Out", e); + return false; + } + + if (answers == null) { + return false; + } + + if (answers.length != ipAddrList.size()) { + return false; + } + + // FIXME: this used to be a loop for all answers, but then we always returned the + // first one in the array, so what should really be done here? + if (answers.length > 0) { + Answer ans = answers[0]; + return ans.getResult(); + } + + return true; + } + /* + + private boolean reconstructRouterState(Network config, DomainRouterVO router, Commands cmds) { if (router.getRole() == Role.DHCP_FIREWALL_LB_PASSWD_USERDATA) { + List ipAddrs = reconstructRouterIpAssocations(cmds, router); + reconstructRouterPortForwardingRules(cmds, ipAddrs); + } + + reconstructDhcpEntries(router); + reconstructVpnServerData(router); + } //source NAT address is stored in /proc/cmdline of the domR and gets //reassigned upon powerup. Source NAT rule gets configured in StartRouter command List ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(router.getAccountId(), router.getDataCenterId(), null); @@ -2434,6 +2543,7 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute for (final IPAddressVO ipVO : ipAddrs) { ipAddrList.add(ipVO.getAddress()); } + if (!ipAddrList.isEmpty()) { try { final boolean success = _networkMgr.associateIP(router, ipAddrList, true, 0); @@ -2445,19 +2555,12 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute return false; } } -// FIXME final List fwRules = new ArrayList(); -// for (final IPAddressVO ipVO : ipAddrs) { -// fwRules.addAll(_rulesDao.listIPForwarding(ipVO.getAddress())); -// } -// final List result = _networkMgr.updateFirewallRules(router -// .getPublicIpAddress(), fwRules, router); -// if (result.size() != fwRules.size()) { -// return false; -// } - } + + return resendDhcpEntries(router) && resendVpnServerData(router); } + */ private boolean resendDhcpEntries(Network config, DomainRouterVO router, Commands cmd){ final List vms = _vmDao.listBy(router.getId(), State.Creating, State.Starting, State.Running, State.Stopping, State.Stopped, State.Migrating); @@ -2494,4 +2597,6 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute } return true; } + + } diff --git a/server/src/com/cloud/network/rules/RulesManager.java b/server/src/com/cloud/network/rules/RulesManager.java index f275e7ffe4b..953bc0b25d6 100644 --- a/server/src/com/cloud/network/rules/RulesManager.java +++ b/server/src/com/cloud/network/rules/RulesManager.java @@ -17,6 +17,8 @@ */ package com.cloud.network.rules; +import java.util.List; + import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.PermissionDeniedException; @@ -57,4 +59,16 @@ public interface RulesManager extends RulesService { void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) throws InvalidParameterValueException, PermissionDeniedException; boolean revokeAllRules(Ip ip, long userId) throws ResourceUnavailableException; + + List listFirewallRulesByIp(Ip ip); + + /** + * Returns a list of port forwarding rules that are ready for application + * to the network elements for this ip. + * @param ip + * @return List of PortForwardingRule + */ + List listPortForwardingRulesForApplication(Ip ip); + + List gatherPortForwardingRulesForApplication(List addrs); } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index a0be9c2e827..68bbe4209b6 100644 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -17,6 +17,7 @@ */ package com.cloud.network.rules; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -336,14 +337,23 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return null; } + public List listFirewallRules(Ip ip) { + return _firewallDao.listByIpAndNotRevoked(ip); + } + + @Override + public List listPortForwardingRulesForApplication(Ip ip) { + return _forwardingDao.listForApplication(ip); + } + @Override public List listPortForwardingRules(ListPortForwardingRulesCmd cmd) { Ip ipAddress = new Ip(cmd.getIpAddress()); Account caller = UserContext.current().getAccount(); IPAddressVO ipAddressVO = _ipAddressDao.findById(ipAddress.addr()); - if (ipAddressVO == null || ipAddressVO.getAllocatedTime() == null) { - throw new InvalidParameterValueException("Unable to find IP address " + ipAddress); + if (ipAddressVO == null || !ipAddressVO.readyToUse()) { + throw new InvalidParameterValueException("Ip address not ready for port forwarding rules yet: " + ipAddress); } List rules = _forwardingDao.listByIpAndNotRevoked(ipAddress); @@ -381,6 +391,9 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { for (PortForwardingRuleVO rule : rules) { if (rule.getState() == FirewallRule.State.Revoke) { _forwardingDao.remove(rule.getId()); + } else if (rule.getState() == FirewallRule.State.Add) { + rule.setState(FirewallRule.State.Active); + _forwardingDao.update(rule.getId(), rule); } } @@ -419,7 +432,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return rules.size() == 0; } - + @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; @@ -1098,5 +1111,31 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { // return _firewallRulesDao.findById(ruleId); // } + @Override + public List listFirewallRulesByIp(Ip ip) { + return null; + } + + @Override + public List gatherPortForwardingRulesForApplication(List addrs) { + List allRules = new ArrayList(); + + for (IpAddress addr : addrs) { + if (!addr.readyToUse()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Skipping " + addr + " because it is not ready for propation yet."); + } + continue; + } + allRules.addAll(_forwardingDao.listForApplication(new Ip(addr.getAddress()))); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found " + allRules.size() + " rules to apply for the addresses."); + } + + return allRules; + } + } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 6918426f1da..2ee7dbd7b80 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -178,7 +178,6 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.info.ConsoleProxyInfo; import com.cloud.network.IPAddressVO; -import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.RemoteAccessVpnVO; import com.cloud.network.VpnUserVO; @@ -186,6 +185,7 @@ import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.VpnUserDao; +import com.cloud.network.router.DomainRouterManager; import com.cloud.network.security.NetworkGroupVO; import com.cloud.network.security.dao.NetworkGroupDao; import com.cloud.offering.NetworkOffering; @@ -434,7 +434,7 @@ public class ManagementServerImpl implements ManagementServer { // Parse the max number of UserVMs and public IPs from server-setup.xml, // and set them in the right places - _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE); + _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),DomainRouterManager.DEFAULT_ROUTER_VM_RAMSIZE); _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE); _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE); diff --git a/server/src/com/cloud/test/IPRangeConfig.java b/server/src/com/cloud/test/IPRangeConfig.java index 774bac5797b..5abadbe916f 100644 --- a/server/src/com/cloud/test/IPRangeConfig.java +++ b/server/src/com/cloud/test/IPRangeConfig.java @@ -45,35 +45,49 @@ public class IPRangeConfig { } public void run(String[] args) { - if (args.length < 2) printError(usage()); + if (args.length < 2) { + printError(usage()); + } String op = args[0]; String type = args[1]; if (type.equals("public")) { - if (args.length != 4 && args.length != 5) printError(usage()); + if (args.length != 4 && args.length != 5) { + printError(usage()); + } String zone = args[2]; String startIP = args[3]; String endIP = null; - if (args.length == 5) endIP = args[4]; + if (args.length == 5) { + endIP = args[4]; + } String result = checkErrors(type, op, null, zone, startIP, endIP); - if (!result.equals("success")) printError(result); + if (!result.equals("success")) { + printError(result); + } long zoneId = PodZoneConfig.getZoneId(zone); result = changeRange(op, "public", -1, zoneId, startIP, endIP); result.replaceAll("
", "/n"); System.out.println(result); } else if (type.equals("private")) { - if (args.length != 5 && args.length != 6) printError(usage()); + if (args.length != 5 && args.length != 6) { + printError(usage()); + } String pod = args[2]; String zone = args[3];; String startIP = args[4]; String endIP = null; - if (args.length == 6) endIP = args[5]; + if (args.length == 6) { + endIP = args[5]; + } String result = checkErrors(type, op, pod, zone, startIP, endIP); - if (!result.equals("success")) printError(result); + if (!result.equals("success")) { + printError(result); + } long podId = PodZoneConfig.getPodId(pod, zone); long zoneId = PodZoneConfig.getZoneId(zone); @@ -87,7 +101,9 @@ public class IPRangeConfig { public List changePublicIPRangeGUI(String op, String zone, String startIP, String endIP) { String result = checkErrors("public", op, null, zone, startIP, endIP); - if (!result.equals("success")) return DatabaseConfig.genReturnList("false", result); + if (!result.equals("success")) { + return DatabaseConfig.genReturnList("false", result); + } long zoneId = PodZoneConfig.getZoneId(zone); result = changeRange(op, "public", -1, zoneId, startIP, endIP); @@ -97,7 +113,9 @@ public class IPRangeConfig { public List changePrivateIPRangeGUI(String op, String pod, String zone, String startIP, String endIP) { String result = checkErrors("private", op, pod, zone, startIP, endIP); - if (!result.equals("success")) return DatabaseConfig.genReturnList("false", result); + if (!result.equals("success")) { + return DatabaseConfig.genReturnList("false", result); + } long podId = PodZoneConfig.getPodId(pod, zone); long zoneId = PodZoneConfig.getZoneId(zone); @@ -107,20 +125,32 @@ public class IPRangeConfig { } private String checkErrors(String type, String op, String pod, String zone, String startIP, String endIP) { - if (!op.equals("add") && !op.equals("delete")) return usage(); + if (!op.equals("add") && !op.equals("delete")) { + return usage(); + } if (type.equals("public")) { // Check that the zone is valid - if (!PodZoneConfig.validZone(zone)) return "Please specify a valid zone."; + if (!PodZoneConfig.validZone(zone)) { + return "Please specify a valid zone."; + } } else if (type.equals("private")) { // Check that the pod and zone are valid - if (!PodZoneConfig.validZone(zone)) return "Please specify a valid zone."; - if (!PodZoneConfig.validPod(pod, zone)) return "Please specify a valid pod."; + if (!PodZoneConfig.validZone(zone)) { + return "Please specify a valid zone."; + } + if (!PodZoneConfig.validPod(pod, zone)) { + return "Please specify a valid pod."; + } } - if (!validIP(startIP)) return "Please specify a valid start IP"; + if (!validIP(startIP)) { + return "Please specify a valid start IP"; + } - if (!validOrBlankIP(endIP)) return "Please specify a valid end IP"; + if (!validOrBlankIP(endIP)) { + return "Please specify a valid end IP"; + } // Check that the IPs that are being added are compatible with either the zone's public netmask, or the pod's CIDR if (type.equals("public")) { @@ -135,37 +165,59 @@ public class IPRangeConfig { String cidrAddress = getCidrAddress(pod, zone); long cidrSize = getCidrSize(pod, zone); - if (!sameSubnetCIDR(startIP, endIP, cidrSize)) return "Please ensure that your start IP and end IP are in the same subnet, as per the pod's CIDR size."; - if (!sameSubnetCIDR(startIP, cidrAddress, cidrSize)) return "Please ensure that your start IP is in the same subnet as the pod's CIDR address."; - if (!sameSubnetCIDR(endIP, cidrAddress, cidrSize)) return "Please ensure that your end IP is in the same subnet as the pod's CIDR address."; + if (!sameSubnetCIDR(startIP, endIP, cidrSize)) { + return "Please ensure that your start IP and end IP are in the same subnet, as per the pod's CIDR size."; + } + if (!sameSubnetCIDR(startIP, cidrAddress, cidrSize)) { + return "Please ensure that your start IP is in the same subnet as the pod's CIDR address."; + } + if (!sameSubnetCIDR(endIP, cidrAddress, cidrSize)) { + return "Please ensure that your end IP is in the same subnet as the pod's CIDR address."; + } } - if (!validIPRange(startIP, endIP)) return "Please specify a valid IP range."; + if (!validIPRange(startIP, endIP)) { + return "Please specify a valid IP range."; + } return "success"; } private String genChangeRangeSuccessString(Vector problemIPs, String op) { - if (problemIPs == null) return ""; + if (problemIPs == null) { + return ""; + } if (problemIPs.size() == 0) { - if (op.equals("add")) return "Successfully added all IPs in the specified range."; - else if (op.equals("delete")) return "Successfully deleted all IPs in the specified range."; - else return ""; + if (op.equals("add")) { + return "Successfully added all IPs in the specified range."; + } else if (op.equals("delete")) { + return "Successfully deleted all IPs in the specified range."; + } else { + return ""; + } } else { String successString = ""; - if (op.equals("add")) successString += "Failed to add the following IPs, because they are already in the database:

"; - else if (op.equals("delete")) successString += "Failed to delete the following IPs, because they are in use:

"; + if (op.equals("add")) { + successString += "Failed to add the following IPs, because they are already in the database:

"; + } else if (op.equals("delete")) { + successString += "Failed to delete the following IPs, because they are in use:

"; + } for (int i = 0; i < problemIPs.size(); i++) { successString += problemIPs.elementAt(i); - if (i != (problemIPs.size() - 1)) successString += ", "; + if (i != (problemIPs.size() - 1)) { + successString += ", "; + } } successString += "

"; - if (op.equals("add")) successString += "Successfully added all other IPs in the specified range."; - else if (op.equals("delete")) successString += "Successfully deleted all other IPs in the specified range."; + if (op.equals("add")) { + successString += "Successfully added all other IPs in the specified range."; + } else if (op.equals("delete")) { + successString += "Successfully deleted all other IPs in the specified range."; + } return successString; } @@ -181,31 +233,48 @@ public class IPRangeConfig { problemIPs = deleteIPRange(type, podId, zoneId, 1, startIP, endIP); } - if (problemIPs == null) return null; - else return genChangeRangeSuccessString(problemIPs, op); + if (problemIPs == null) { + return null; + } else { + return genChangeRangeSuccessString(problemIPs, op); + } } private String genSuccessString(Vector problemIPs, String op) { - if (problemIPs == null) return ""; + if (problemIPs == null) { + return ""; + } if (problemIPs.size() == 0) { - if (op.equals("add")) return "Successfully added all IPs in the specified range."; - else if (op.equals("delete")) return "Successfully deleted all IPs in the specified range."; - else return ""; + if (op.equals("add")) { + return "Successfully added all IPs in the specified range."; + } else if (op.equals("delete")) { + return "Successfully deleted all IPs in the specified range."; + } else { + return ""; + } } else { String successString = ""; - if (op.equals("add")) successString += "Failed to add the following IPs, because they are already in the database:

"; - else if (op.equals("delete")) successString += "Failed to delete the following IPs, because they are in use:

"; + if (op.equals("add")) { + successString += "Failed to add the following IPs, because they are already in the database:

"; + } else if (op.equals("delete")) { + successString += "Failed to delete the following IPs, because they are in use:

"; + } for (int i = 0; i < problemIPs.size(); i++) { successString += problemIPs.elementAt(i); - if (i != (problemIPs.size() - 1)) successString += ", "; + if (i != (problemIPs.size() - 1)) { + successString += ", "; + } } successString += "

"; - if (op.equals("add")) successString += "Successfully added all other IPs in the specified range."; - else if (op.equals("delete")) successString += "Successfully deleted all other IPs in the specified range."; + if (op.equals("add")) { + successString += "Successfully added all other IPs in the specified range."; + } else if (op.equals("delete")) { + successString += "Successfully deleted all other IPs in the specified range."; + } return successString; } @@ -229,12 +298,17 @@ public class IPRangeConfig { protected Vector deleteIPRange(String type, long podId, long zoneId, long vlanDbId, String startIP, String endIP) { long startIPLong = NetUtils.ip2Long(startIP); long endIPLong = startIPLong; - if (endIP != null) endIPLong = NetUtils.ip2Long(endIP); + if (endIP != null) { + endIPLong = NetUtils.ip2Long(endIP); + } Transaction txn = Transaction.currentTxn(); Vector problemIPs = null; - if (type.equals("public")) problemIPs = deletePublicIPRange(txn, startIPLong, endIPLong, vlanDbId); - else if (type.equals("private")) problemIPs = deletePrivateIPRange(txn, startIPLong, endIPLong, podId, zoneId); + if (type.equals("public")) { + problemIPs = deletePublicIPRange(txn, startIPLong, endIPLong, vlanDbId); + } else if (type.equals("private")) { + problemIPs = deletePrivateIPRange(txn, startIPLong, endIPLong, podId, zoneId); + } return problemIPs; } @@ -317,8 +391,11 @@ public class IPRangeConfig { stmt.setString(1, ip); stmt.setLong(2, vlanDbId); ResultSet rs = stmt.executeQuery(); - if (rs.next()) return (rs.getString("allocated") != null); - else return false; + if (rs.next()) { + return (rs.getString("allocated") != null); + } else { + return false; + } } catch (SQLException ex) { System.out.println(ex.getMessage()); return true; @@ -332,8 +409,11 @@ public class IPRangeConfig { stmt.setLong(2, zoneId); stmt.setLong(3, podId); ResultSet rs = stmt.executeQuery(); - if (rs.next()) return (rs.getString("taken") != null); - else return false; + if (rs.next()) { + return (rs.getString("taken") != null); + } else { + return false; + } } catch (SQLException ex) { System.out.println(ex.getMessage()); return true; @@ -344,13 +424,18 @@ public class IPRangeConfig { public Vector saveIPRange(String type, long podId, long zoneId, long vlanDbId, String startIP, String endIP) { long startIPLong = NetUtils.ip2Long(startIP); long endIPLong = startIPLong; - if (endIP != null) endIPLong = NetUtils.ip2Long(endIP); + if (endIP != null) { + endIPLong = NetUtils.ip2Long(endIP); + } Transaction txn = Transaction.currentTxn(); Vector problemIPs = null; - if (type.equals("public")) problemIPs = savePublicIPRange(txn, startIPLong, endIPLong, zoneId, vlanDbId); - else if (type.equals("private")) problemIPs = savePrivateIPRange(txn, startIPLong, endIPLong, podId, zoneId); + if (type.equals("public")) { + problemIPs = savePublicIPRange(txn, startIPLong, endIPLong, zoneId, vlanDbId); + } else if (type.equals("private")) { + problemIPs = savePrivateIPRange(txn, startIPLong, endIPLong, podId, zoneId); + } String[] linkLocalIps = NetUtils.getLinkLocalIPRange(10); long startLinkLocalIp = NetUtils.ip2Long(linkLocalIps[0]); @@ -362,7 +447,8 @@ public class IPRangeConfig { } private Vector savePublicIPRange(Transaction txn, long startIP, long endIP, long zoneId, long vlanDbId) { - String insertSql = "INSERT INTO `cloud`.`user_ip_address` (public_ip_address, data_center_id, vlan_db_id) VALUES (?, ?, ?)"; + String insertSql = "INSERT INTO `cloud`.`user_ip_address` (public_ip_address, data_center_id, vlan_db_id, mac_address) VALUES (?, ?, ?, (select mac_address from `cloud`.`data_center` where id=?))"; + String updateSql = "UPDATE `cloud`.`data_center` set mac_address = mac_address+1 where id=?"; Vector problemIPs = new Vector(); PreparedStatement stmt = null; @@ -379,6 +465,11 @@ public class IPRangeConfig { stmt.setString(1, NetUtils.long2Ip(startIP)); stmt.setLong(2, zoneId); stmt.setLong(3, vlanDbId); + stmt.setLong(4, zoneId); + stmt.executeUpdate(); + stmt.close(); + stmt = conn.prepareStatement(updateSql); + stmt.setLong(1, zoneId); stmt.executeUpdate(); stmt.close(); } catch (Exception ex) { @@ -492,12 +583,18 @@ public class IPRangeConfig { // } public static boolean validCIDR(final String cidr) { - if (cidr == null || cidr.isEmpty()) return false; + if (cidr == null || cidr.isEmpty()) { + return false; + } String[] cidrPair = cidr.split("\\/"); - if (cidrPair.length != 2) return false; + if (cidrPair.length != 2) { + return false; + } String cidrAddress = cidrPair[0]; String cidrSize = cidrPair[1]; - if (!validIP(cidrAddress)) return false; + if (!validIP(cidrAddress)) { + return false; + } int cidrSizeNum = -1; try { @@ -506,13 +603,17 @@ public class IPRangeConfig { return false; } - if (cidrSizeNum < 1 || cidrSizeNum > 32) return false; + if (cidrSizeNum < 1 || cidrSizeNum > 32) { + return false; + } return true; } public static boolean validOrBlankIP(final String ip) { - if (ip == null || ip.isEmpty()) return true; + if (ip == null || ip.isEmpty()) { + return true; + } return validIP(ip); } @@ -534,10 +635,14 @@ public class IPRangeConfig { return false; } // Each octet must be between 0 and 255, inclusive - if (octet < 0 || octet > 255) return false; + if (octet < 0 || octet > 255) { + return false; + } // Each octetString must have between 1 and 3 characters - if (octetString.length() < 1 || octetString.length() > 3) return false; + if (octetString.length() < 1 || octetString.length() > 3) { + return false; + } } @@ -546,7 +651,9 @@ public class IPRangeConfig { } public static boolean validIPRange(String startIP, String endIP) { - if (endIP == null || endIP.isEmpty()) return true; + if (endIP == null || endIP.isEmpty()) { + return true; + } long startIPLong = NetUtils.ip2Long(startIP); long endIPLong = NetUtils.ip2Long(endIP); @@ -554,7 +661,9 @@ public class IPRangeConfig { } public static boolean sameSubnet(final String ip1, final String ip2, final String netmask) { - if (ip1 == null || ip1.isEmpty() || ip2 == null || ip2.isEmpty()) return true; + if (ip1 == null || ip1.isEmpty() || ip2 == null || ip2.isEmpty()) { + return true; + } String subnet1 = NetUtils.getSubNet(ip1, netmask); String subnet2 = NetUtils.getSubNet(ip2, netmask); @@ -562,7 +671,9 @@ public class IPRangeConfig { } public static boolean sameSubnetCIDR(final String ip1, final String ip2, final long cidrSize) { - if (ip1 == null || ip1.isEmpty() || ip2 == null || ip2.isEmpty()) return true; + if (ip1 == null || ip1.isEmpty() || ip2 == null || ip2.isEmpty()) { + return true; + } String subnet1 = NetUtils.getCidrSubNet(ip1, cidrSize); String subnet2 = NetUtils.getCidrSubNet(ip2, cidrSize); diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 1bc40aa3508..2d9feb708cd 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -668,9 +668,14 @@ public class AccountManagerImpl implements AccountManager, AccountService { HashMap> domains = new HashMap>(); for (ControlledEntity entity : entities) { + if (entity.getAccountId() == -1 && entity.getDomainId() == -1) { + s_logger.debug("Free entity: " + entity); + continue; + } List toBeChecked = domains.get(entity.getDomainId()); if (toBeChecked == null) { toBeChecked = new ArrayList(); + domains.put(entity.getDomainId(), toBeChecked); } toBeChecked.add(entity); boolean granted = false; @@ -880,7 +885,7 @@ public class AccountManagerImpl implements AccountManager, AccountService { } } - if (!_networkMgr.releasePublicIpAddress(User.UID_SYSTEM, ip.getAddress())) { + if (!_networkMgr.releasePublicIpAddress(ip.getAddress(), account.getId(), User.UID_SYSTEM)) { s_logger.error("Unable to release IP: " + ip.getAddress()); accountCleanupNeeded = true; } else { diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index b0d8432bcd8..3f9d835d60c 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2821,7 +2821,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM { for(VlanVO vlanForAcc : vlansForAccount) { - guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForAcc.getId(), false).getAddress(); + guestIp = null;//_ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForAcc.getId(), false).getAddress(); if(guestIp!=null) { break; //got an ip } @@ -2832,7 +2832,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM //i.e. for pod for(VlanVO vlanForPod : vlansForPod) { - guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForPod.getId(), false).getAddress(); + guestIp = null; // _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForPod.getId(), false).getAddress(); if(guestIp!=null) { break;//got an ip } @@ -2843,7 +2843,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM //for zone for(VlanVO vlanForZone : zoneWideVlans) { - guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForZone.getId(), false).getAddress(); + guestIp = null;// _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForZone.getId(), false).getAddress(); if(guestIp!=null) { break;//found an ip } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 5e6cb7b0c3f..ccca9f43564 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -387,6 +387,12 @@ CREATE TABLE `cloud`.`data_center` ( `domain` varchar(100) COMMENT 'Network domain name of the Vms of the zone', `domain_id` bigint unsigned COMMENT 'domain id for the parent domain to this zone (null signifies public zone)', `networktype` varchar(255) NOT NULL DEFAULT 'Basic' COMMENT 'Network type of the zone', + `dns_provider` char(64) NOT NULL DEFAULT 'VirtualRouter', + `gateway_provider` char(64) NOT NULL DEFAULT 'VirtualRouter', + `firewall_provider` char(64) NOT NULL DEFAULT 'VirtualRouter', + `dhcp_provider` char(64) NOT NULL DEFAULT 'VirtualRouter', + `lb_provider` char(64) NOT NULL DEFAULT 'VirtualRouter', + `vpn_provider` char(64) NOT NULL DEFAULT 'VirtualRouter', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -613,6 +619,7 @@ CREATE TABLE `cloud`.`user_ip_address` ( `vlan_db_id` bigint unsigned NOT NULL, `one_to_one_nat` int(1) unsigned NOT NULL default '0', `state` char(32) NOT NULL default 'Free' COMMENT 'state of the ip address', + `mac_address` bigint unsigned NOT NULL COMMENT 'mac address of this ip', PRIMARY KEY (`public_ip_address`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;