From f794abfdefe2fd4608061b0e2dd371e25092e3f1 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Tue, 7 Dec 2010 08:36:22 -0800 Subject: [PATCH] ip addresses are now separated from domR --- .../api/commands/AssociateIPAddrCmd.java | 34 +- api/src/com/cloud/network/NetworkService.java | 3 + .../cloud/network/element/NetworkElement.java | 6 +- .../src/com/cloud/network/NetworkManager.java | 32 +- .../com/cloud/network/NetworkManagerImpl.java | 324 ++++++------------ .../src/com/cloud/network/dao/NetworkDao.java | 8 +- .../com/cloud/network/dao/NetworkDaoImpl.java | 70 ++-- .../network/element/DomainRouterElement.java | 6 +- setup/db/create-schema.sql | 4 +- 9 files changed, 198 insertions(+), 289 deletions(-) diff --git a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java index 2badfe630f5..dd25bbf7188 100644 --- a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java +++ b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java @@ -17,6 +17,8 @@ */ package com.cloud.api.commands; +import java.util.List; + import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -29,6 +31,8 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.ResourceAllocationException; import com.cloud.network.IpAddress; +import com.cloud.network.Network; +import com.cloud.user.UserContext; @Implementation(description="Acquires and associates a public IP to an account.", responseObject=IPAddressResponse.class) public class AssociateIPAddrCmd extends BaseCmd { @@ -47,6 +51,9 @@ public class AssociateIPAddrCmd extends BaseCmd { @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=true, description="the ID of the availability zone you want to acquire an public IP address from") private Long zoneId; + + @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="The network this ip address should be associated to.") + private Long networkId; ///////////////////////////////////////////////////// @@ -54,16 +61,35 @@ public class AssociateIPAddrCmd extends BaseCmd { ///////////////////////////////////////////////////// public String getAccountName() { - return accountName; + if (accountName != null) { + return accountName; + } + return UserContext.current().getAccount().getAccountName(); } - public Long getDomainId() { - return domainId; + public long getDomainId() { + if (domainId != null) { + return domainId; + } + return UserContext.current().getAccount().getDomainId(); } - public Long getZoneId() { + public long getZoneId() { return zoneId; } + + public Long getNetworkId() { + if (networkId != null) { + return networkId; + } + + List networks = _networkService.getVirtualNetworksOwnedByAccountInZone(getAccountName(), getDomainId(), getZoneId()); + if (networks.size() == 0) { + return null; + } + assert (networks.size() <= 1) : "Too many virtual networks. This logic should be obsolete"; + return networks.get(0).getId(); + } ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 4d7357b4b69..9ac4222f681 100644 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -39,6 +39,9 @@ import com.cloud.offering.NetworkOffering; public interface NetworkService { + + List getVirtualNetworksOwnedByAccountInZone(String accountName, long domainId, long zoneId); + List listNetworkOfferings(); /** * Associates a public IP address for a router. diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java index 7b6763fbdcd..45e9b91ccd9 100644 --- a/api/src/com/cloud/network/element/NetworkElement.java +++ b/api/src/com/cloud/network/element/NetworkElement.java @@ -10,11 +10,11 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IpAddress; import com.cloud.network.Network; import com.cloud.network.rules.FirewallRule; import com.cloud.offering.NetworkOffering; import com.cloud.utils.component.Adapter; -import com.cloud.utils.net.Ip; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachine; @@ -75,7 +75,7 @@ public interface NetworkElement extends Adapter { * @return * @throws ResourceUnavailableException */ - boolean associate(Network network, Ip ipAddress) throws ResourceUnavailableException; + boolean associate(Network network, IpAddress ipAddress) throws ResourceUnavailableException; /** * Disassociate the ip address from this network @@ -84,7 +84,7 @@ public interface NetworkElement extends Adapter { * @return * @throws ResourceUnavailableException */ - boolean disassociate(Network network, Ip ipAddress) throws ResourceUnavailableException; + boolean disassociate(Network network, IpAddress ipAddress) throws ResourceUnavailableException; /** * Apply rules diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index b1b0c3ee36d..06ca4996f37 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -25,7 +25,6 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; -import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.addr.PublicIp; import com.cloud.network.rules.FirewallRule; @@ -81,27 +80,6 @@ public interface NetworkManager extends NetworkService { */ boolean associateIP(DomainRouterVO router, List ipAddrList, boolean add, long vmId) throws ConcurrentOperationException; - /** - * Associates or disassociates a single IP address for a router. - * @param router router object to send the association to - * @param ipAddress public IP addresses - * @param add true if associate, false if disassociate - * @return - */ - boolean associateIP(DomainRouterVO router, String ipAddress, boolean add, long vmId) throws ResourceAllocationException; - - - /** - * Add a DHCP entry on the domr dhcp server - * @param routerHostId - the host id of the domr - * @param routerIp - the private ip address of the domr - * @param vmName - the name of the VM (e.g., i-10-TEST) - * @param vmMac - the mac address of the eth0 interface of the VM - * @param vmIp - the ip address to hand out. - * @return success or failure - */ - public boolean addDhcpEntry(long routerHostId, String routerIp, String vmName, String vmMac, String vmIp); - /** * Lists IP addresses that belong to VirtualNetwork VLANs * @param accountId - account that the IP address should belong to @@ -112,7 +90,7 @@ public interface NetworkManager extends NetworkService { List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat); List setupNetworkConfiguration(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isShared); - List setupNetworkConfiguration(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared); + List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared); List getSystemAccountNetworkOfferings(String... offeringNames); @@ -123,12 +101,12 @@ public interface NetworkManager extends NetworkService { List getNics (VirtualMachine vm); - List getAccountsUsingNetworkConfiguration(long configurationId); - AccountVO getNetworkConfigurationOwner(long configurationId); + List getAccountsUsingNetwork(long configurationId); + AccountVO getNetworkOwner(long configurationId); - List getNetworkConfigurationsforOffering(long offeringId, long dataCenterId, long accountId); + List getNetworksforOffering(long offeringId, long dataCenterId, long accountId); - List setupNetworkConfiguration(Account owner, ServiceOfferingVO offering, DeploymentPlan plan); + List setupNetwork(Account owner, ServiceOfferingVO offering, DeploymentPlan plan); 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 d21d81ee5b7..ced17d5a249 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -36,7 +36,6 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager.OnError; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.routing.DhcpEntryCommand; import com.cloud.agent.api.routing.IPAssocCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.manager.Commands; @@ -52,7 +51,6 @@ import com.cloud.api.commands.DeleteRemoteAccessVpnCmd; import com.cloud.api.commands.DisassociateIPAddrCmd; import com.cloud.api.commands.ListNetworksCmd; import com.cloud.api.commands.RemoveVpnUserCmd; -import com.cloud.async.AsyncJobManager; import com.cloud.capacity.dao.CapacityDao; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -67,7 +65,6 @@ import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.AccountVlanMapDao; 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; @@ -88,17 +85,12 @@ import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.host.dao.HostDao; 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.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.LoadBalancerDao; -import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkRuleConfigDao; import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.VpnUserDao; import com.cloud.network.element.NetworkElement; @@ -115,19 +107,12 @@ import com.cloud.resource.Resource; import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.storage.StorageManager; -import com.cloud.storage.dao.GuestOSDao; -import com.cloud.storage.dao.StoragePoolDao; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; -import com.cloud.storage.dao.VolumeDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.UserContext; import com.cloud.user.UserStatisticsVO; import com.cloud.user.dao.AccountDao; -import com.cloud.user.dao.UserDao; import com.cloud.user.dao.UserStatisticsDao; import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; @@ -167,41 +152,25 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag String _name; @Inject DataCenterDao _dcDao = null; @Inject VlanDao _vlanDao = null; - @Inject FirewallRulesDao _rulesDao = null; - @Inject LoadBalancerDao _loadBalancerDao = null; - @Inject LoadBalancerVMMapDao _loadBalancerVMMapDao = null; @Inject IPAddressDao _ipAddressDao = null; - @Inject VMTemplateDao _templateDao = null; - @Inject UserDao _userDao = null; @Inject AccountDao _accountDao = null; @Inject DomainDao _domainDao = null; @Inject UserStatisticsDao _userStatsDao = null; - @Inject VolumeDao _volsDao = null; - @Inject HostDao _hostDao = null; @Inject EventDao _eventDao = null; @Inject ConfigurationDao _configDao; - @Inject HostPodDao _podDao = null; - @Inject VMTemplateHostDao _vmTemplateHostDao = null; @Inject UserVmDao _vmDao = null; @Inject ResourceLimitDao _limitDao = null; @Inject CapacityDao _capacityDao = null; @Inject AgentManager _agentMgr; - @Inject StorageManager _storageMgr; @Inject AlertManager _alertMgr; @Inject AccountManager _accountMgr; @Inject ConfigurationManager _configMgr; - @Inject AsyncJobManager _asyncMgr; - @Inject StoragePoolDao _storagePoolDao = null; @Inject ServiceOfferingDao _serviceOfferingDao = null; - @Inject UserVmDao _userVmDao; - @Inject FirewallRulesDao _firewallRulesDao; - @Inject NetworkRuleConfigDao _networkRuleConfigDao; @Inject AccountVlanMapDao _accountVlanMapDao; @Inject UserStatisticsDao _statsDao = null; @Inject NetworkOfferingDao _networkOfferingDao = null; - @Inject NetworkDao _networkConfigDao = null; + @Inject NetworkDao _networksDao = null; @Inject NicDao _nicDao = null; - @Inject GuestOSDao _guestOSDao = null; @Inject RemoteAccessVpnDao _remoteAccessVpnDao = null; @Inject VpnUserDao _vpnUsersDao = null; @Inject DomainRouterManager _routerMgr; @@ -217,7 +186,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag ScheduledExecutorService _executor; - SearchBuilder AccountsUsingNetworkConfigurationSearch; + SearchBuilder AccountsUsingNetworkSearch; SearchBuilder AssignIpAddressSearch; SearchBuilder IpAddressSearch; @@ -453,46 +422,50 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } return account; } + + @Override + public List getVirtualNetworksOwnedByAccountInZone(String accountName, long domainId, long zoneId) { + Account owner = _accountDao.findActiveAccount(accountName, domainId); + if (owner == null) { + throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); + } + + return _networksDao.listBy(owner.getId(), zoneId, GuestIpType.Virtual); + } @Override @DB - public IPAddressVO associateIP(AssociateIPAddrCmd cmd) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + public IpAddress associateIP(AssociateIPAddrCmd cmd) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { String accountName = cmd.getAccountName(); - Long domainId = cmd.getDomainId(); + long domainId = cmd.getDomainId(); Long zoneId = cmd.getZoneId(); - Account account = UserContext.current().getAccount(); - Long userId = UserContext.current().getUserId(); + Account caller = UserContext.current().getAccount(); + long userId = UserContext.current().getUserId(); Long accountId = null; - if ((account == null) || isAdmin(account.getType())) { - if (domainId != null) { - if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) { - throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to associate IP address, permission denied"); - } - if (accountName != null) { - Account userAccount = _accountDao.findActiveAccount(accountName, domainId); - if (userAccount != null) { - accountId = userAccount.getId(); - } else { - throw new PermissionDeniedException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); - } - } - } else if (account != null) { - // the admin is acquiring an IP address - accountId = account.getId(); - domainId = account.getDomainId(); - } else { - throw new InvalidParameterValueException("Account information is not specified."); + Account owner = _accountDao.findActiveAccount(accountName, domainId); + if (owner == null) { + throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); + } + + _accountMgr.checkAccess(caller, owner); + + Long networkId = cmd.getNetworkId(); + Network network = null; + if (networkId != null) { + network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Network id is invalid: " + networkId); } - } else { - accountId = account.getId(); - domainId = account.getDomainId(); - } - - if (userId == null) { - userId = Long.valueOf(1); } + EventVO event = new EventVO(); + event.setUserId(userId); + event.setAccountId(accountId); + event.setType(EventTypes.EVENT_NET_IP_ASSIGN); + PublicIp ip = null; + boolean success = false; + Transaction txn = Transaction.currentTxn(); Account accountToLock = null; try { @@ -500,7 +473,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.debug("Associate IP address called for user " + userId + " account " + accountId); } accountToLock = _accountDao.acquireInLockTable(accountId); - if (accountToLock == null) { s_logger.warn("Unable to lock account: " + accountId); throw new ConcurrentOperationException("Unable to acquire account lock"); @@ -513,127 +485,58 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag // Check that the maximum number of public IPs for the given // accountId will not be exceeded if (_accountMgr.resourceLimitExceeded(accountToLock, ResourceType.public_ip)) { - ResourceAllocationException rae = new ResourceAllocationException("Maximum number of public IP addresses for account: " + accountToLock.getAccountName() - + " has been exceeded."); + ResourceAllocationException rae = new ResourceAllocationException("Maximum number of public IP addresses for account: " + accountToLock.getAccountName() + " has been exceeded."); rae.setResourceType("ip"); throw rae; } - DomainRouterVO router = _routerMgr.getRouter(accountId, zoneId); - if (router == null) { - throw new InvalidParameterValueException("No router found for account: " + accountToLock.getAccountName() + ". Please create a VM before acquiring an IP"); - } - txn.start(); - String ipAddress = null; - Pair ipAndVlan = null;//FIXME d_vlanDao.assignIpAddress(zoneId, accountId, domainId, VlanType.VirtualNetwork, false); - - if (ipAndVlan == null) { + ip = fetchNewPublicIp(zoneId, VlanType.VirtualNetwork, owner, false); + if (ip == null) { throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zoneId); - } else { - ipAddress = ipAndVlan.first(); - _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); - } + } + _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); - boolean success = true; - String errorMsg = ""; - - List ipAddrs = new ArrayList(); - ipAddrs.add(ipAddress); - - if (router.getState() == State.Running) { - success = associateIP(router, ipAddress, true, 0L); - if (!success) { - errorMsg = "Unable to assign public IP address."; - } - } - - EventVO event = new EventVO(); - event.setUserId(userId); - event.setAccountId(accountId); - event.setType(EventTypes.EVENT_NET_IP_ASSIGN); + String ipAddress = ip.getAddress(); + event.setParameters("address=" + ipAddress + "\nsourceNat=" + false + "\ndcId=" + zoneId); - - if (!success) { - _ipAddressDao.unassignIpAddress(ipAddress); - ipAddress = null; - _accountMgr.decrementResourceCount(accountId, ResourceType.public_ip); - - event.setLevel(EventVO.LEVEL_ERROR); - event.setDescription(errorMsg); - _eventDao.persist(event); - txn.commit(); - - throw new CloudRuntimeException(errorMsg); - } else { - event.setDescription("Assigned a public IP address: " + ipAddress); - _eventDao.persist(event); - } + event.setDescription("Assigned a public IP address: " + ipAddress); + _eventDao.persist(event); txn.commit(); - IPAddressVO ip = _ipAddressDao.findById(ipAddress); - + if (network != null) { + for (NetworkElement element : _networkElements) { + element.associate(network, ip); + } + } + + success = true; + return ip; - } catch (ResourceAllocationException rae) { - s_logger.error("Associate IP threw a ResourceAllocationException.", rae); - throw rae; - } catch (InsufficientAddressCapacityException iace) { - s_logger.error("Associate IP threw an InsufficientAddressCapacityException.", iace); - throw iace; - } catch (InvalidParameterValueException ipve) { - s_logger.error("Associate IP threw an InvalidParameterValueException.", ipve); - throw ipve; + } catch (ResourceUnavailableException e) { + s_logger.error("Unable to associate ip address due to resource unavailable exception", e); + return null; } finally { - if (account != null) { + if (caller != null) { _accountDao.releaseFromLockTable(accountId); s_logger.debug("Associate IP address lock released"); } - } + + if (!success) { + if (ip != null) { + Transaction.currentTxn(); + txn.start(); + _ipAddressDao.unassignIpAddress(ip.getAddress()); + _accountMgr.decrementResourceCount(accountId, ResourceType.public_ip); - } - - @Override - public boolean associateIP(final DomainRouterVO router, final String ipAddress, final boolean add, long vmId) { - Commands cmds = new Commands(OnError.Continue); - IPAddressVO ip = _ipAddressDao.findById(ipAddress); - VlanVO vlan = _vlanDao.findById(ip.getVlanId()); - boolean sourceNat = ip.isSourceNat(); - boolean firstIP = (!sourceNat && (_ipAddressDao.countIPs(vlan.getDataCenterId(), router.getAccountId(), vlan.getVlanId(), vlan.getVlanGateway(), vlan.getVlanNetmask()) == 1)); - 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]; + event.setLevel(EventVO.LEVEL_ERROR); + event.setDescription(""); + _eventDao.persist(event); + txn.commit(); + } + } } - String vmGuestAddress = null; - if(vmId!=0){ - vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); - } - - IPAssocCommand cmd = new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress); - cmds.addCommand(cmd); - 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 != 1) { - return false; - } - return answers[0].getResult(); } @Override @@ -668,7 +571,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag for (NetworkElement ne : _networkElements) { try { - ne.disassociate(null, new Ip(ipAddress)); + ne.disassociate(null, ip); } catch (ResourceUnavailableException e) { s_logger.warn("Unable to release the ip address " + ip, e); success = false; @@ -763,12 +666,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectPodBasedNetworkOffering); - AccountsUsingNetworkConfigurationSearch = _accountDao.createSearchBuilder(); - SearchBuilder networkAccountSearch = _networkConfigDao.createSearchBuilderForAccount(); - AccountsUsingNetworkConfigurationSearch.join("nc", networkAccountSearch, AccountsUsingNetworkConfigurationSearch.entity().getId(), networkAccountSearch.entity().getAccountId(), JoinType.INNER); + AccountsUsingNetworkSearch = _accountDao.createSearchBuilder(); + SearchBuilder networkAccountSearch = _networksDao.createSearchBuilderForAccount(); + AccountsUsingNetworkSearch.join("nc", networkAccountSearch, AccountsUsingNetworkSearch.entity().getId(), networkAccountSearch.entity().getAccountId(), JoinType.INNER); networkAccountSearch.and("config", networkAccountSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); networkAccountSearch.and("owner", networkAccountSearch.entity().isOwner(), SearchCriteria.Op.EQ); - AccountsUsingNetworkConfigurationSearch.done(); + AccountsUsingNetworkSearch.done(); AssignIpAddressSearch = _ipAddressDao.createSearchBuilder(); SearchBuilder vlanSearch = _vlanDao.createSearchBuilder(); @@ -809,15 +712,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag protected NetworkManagerImpl() { } - @Override - public boolean addDhcpEntry(final long routerHostId, final String routerIp, String vmName, String vmMac, String vmIp) { - final DhcpEntryCommand dhcpEntry = new DhcpEntryCommand(vmMac, vmIp, routerIp, vmName); - - - final Answer answer = _agentMgr.easySend(routerHostId, dhcpEntry); - return (answer != null && answer.getResult()); - } - @Override public List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat) { SearchCriteria sc = IpAddressSearch.create(); @@ -833,7 +727,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public List setupNetworkConfiguration(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isShared) { - return setupNetworkConfiguration(owner, offering, null, plan, name, displayText, isShared); + return setupNetwork(owner, offering, null, plan, name, displayText, isShared); } @Override @@ -863,18 +757,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (config instanceof NetworkVO) { configs.add((NetworkVO)config); } else { - configs.add(_networkConfigDao.findById(config.getId())); + configs.add(_networksDao.findById(config.getId())); } continue; } - long id = _networkConfigDao.getNextInSequence(Long.class, "id"); + long id = _networksDao.getNextInSequence(Long.class, "id"); if (related == -1) { related = id; } NetworkVO vo = new NetworkVO(id, config, offering.getId(), plan.getDataCenterId(), guru.getName(), owner.getDomainId(), owner.getId(), related, name, displayText, isShared); - configs.add(_networkConfigDao.persist(vo)); + configs.add(_networksDao.persist(vo)); } if (configs.size() < 1) { @@ -1027,13 +921,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @DB - protected Pair implementNetworkConfiguration(long configId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientAddressCapacityException { + protected Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientAddressCapacityException { Transaction.currentTxn(); Pair implemented = new Pair(null, null); - NetworkVO config = _networkConfigDao.acquireInLockTable(configId); + NetworkVO config = _networksDao.acquireInLockTable(networkId); if (config == null) { - throw new ConcurrentOperationException("Unable to acquire network configuration: " + configId); + throw new ConcurrentOperationException("Unable to acquire network configuration: " + networkId); } try { @@ -1062,7 +956,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag config.setDns2(result.getDns2()); config.setMode(result.getMode()); config.setState(Network.State.Implemented); - _networkConfigDao.update(configId, config); + _networksDao.update(networkId, config); for (NetworkElement element : _networkElements) { if (s_logger.isDebugEnabled()) { @@ -1081,7 +975,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (implemented.first() == null) { s_logger.debug("Cleaning up because we're unable to implement network " + config); } - _networkConfigDao.releaseFromLockTable(configId); + _networksDao.releaseFromLockTable(networkId); } } @@ -1089,7 +983,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag public void prepare(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientNetworkCapacityException, ConcurrentOperationException, ResourceUnavailableException { List nics = _nicDao.listBy(vmProfile.getId()); for (NicVO nic : nics) { - Pair implemented = implementNetworkConfiguration(nic.getNetworkId(), dest, context); + Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); NetworkGuru concierge = implemented.first(); NetworkVO config = implemented.second(); NicProfile profile = null; @@ -1134,7 +1028,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag public void release(VirtualMachineProfile vmProfile) { List nics = _nicDao.listBy(vmProfile.getId()); for (NicVO nic : nics) { - NetworkVO config = _networkConfigDao.findById(nic.getNetworkId()); + NetworkVO config = _networksDao.findById(nic.getNetworkId()); if (nic.getReservationStrategy() == ReservationStrategy.Start) { NetworkGuru concierge = _networkGurus.get(config.getGuruName()); nic.setState(Resource.State.Releasing); @@ -1264,28 +1158,28 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override - public List getAccountsUsingNetworkConfiguration(long configurationId) { - SearchCriteria sc = AccountsUsingNetworkConfigurationSearch.create(); - sc.setJoinParameters("nc", "config", configurationId); + public List getAccountsUsingNetwork(long networkId) { + SearchCriteria sc = AccountsUsingNetworkSearch.create(); + sc.setJoinParameters("nc", "config", networkId); return _accountDao.search(sc, null); } @Override - public AccountVO getNetworkConfigurationOwner(long configurationId) { - SearchCriteria sc = AccountsUsingNetworkConfigurationSearch.create(); - sc.setJoinParameters("nc", "config", configurationId); + public AccountVO getNetworkOwner(long networkId) { + SearchCriteria sc = AccountsUsingNetworkSearch.create(); + sc.setJoinParameters("nc", "config", networkId); sc.setJoinParameters("nc", "owner", true); List accounts = _accountDao.search(sc, null); return accounts.size() != 0 ? accounts.get(0) : null; } @Override - public List getNetworkConfigurationsforOffering(long offeringId, long dataCenterId, long accountId) { - return _networkConfigDao.getNetworkConfigurationsForOffering(offeringId, dataCenterId, accountId); + public List getNetworksforOffering(long offeringId, long dataCenterId, long accountId) { + return _networksDao.getNetworksForOffering(offeringId, dataCenterId, accountId); } @Override - public List setupNetworkConfiguration(Account owner, ServiceOfferingVO offering, DeploymentPlan plan) { + public List setupNetwork(Account owner, ServiceOfferingVO offering, DeploymentPlan plan) { NetworkOfferingVO networkOffering = _networkOfferingDao.findByServiceOffering(offering); return setupNetworkConfiguration(owner, networkOffering, plan, null, null, false); } @@ -1620,17 +1514,17 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override - public String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException { - String mac = _networkConfigDao.getNextAvailableMacAddress(networkConfigurationId); + public String getNextAvailableMacAddressInNetwork(long networkId) throws InsufficientAddressCapacityException { + String mac = _networksDao.getNextAvailableMacAddress(networkId); if (mac == null) { - throw new InsufficientAddressCapacityException("Unable to create another mac address", Network.class, networkConfigurationId); + throw new InsufficientAddressCapacityException("Unable to create another mac address", Network.class, networkId); } return mac; } @Override @DB public Network getNetwork(long id) { - return _networkConfigDao.findById(id); + return _networksDao.findById(id); } @Override @DB @@ -1687,7 +1581,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag //if VlanId is Direct untagged, verify if there is already network of this type in the zone if (networkOffering.getGuestIpType() == GuestIpType.DirectPodBased && vlanId != null && vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { - SearchBuilder sb = _networkConfigDao.createSearchBuilder(); + SearchBuilder sb = _networksDao.createSearchBuilder(); sb.and("broadcastDomainType", sb.entity().getBroadcastDomainType(), SearchCriteria.Op.EQ); sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); @@ -1700,7 +1594,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag sc.setParameters("dataCenterId", zoneId); sc.setJoinParameters("networkSearch", "guestIpType", GuestIpType.DirectPodBased); - List networks = _networkConfigDao.search(sc, null); + List networks = _networksDao.search(sc, null); if (networks!= null && !networks.isEmpty()) { throw new InvalidParameterValueException("Network with untagged vlan already exists for the zone " + zoneId); } @@ -1739,7 +1633,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - List networks = setupNetworkConfiguration(owner, networkOffering, userNetwork, plan, name, displayText, isShared); + List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared); Long networkId = null; if (networks == null || networks.isEmpty()) { @@ -1810,7 +1704,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } Filter searchFilter = new Filter(NetworkVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchBuilder sb = _networkConfigDao.createSearchBuilder(); + SearchBuilder sb = _networksDao.createSearchBuilder(); //Don't display networks created of system network offerings SearchBuilder networkOfferingSearch = _networkOfferingDao.createSearchBuilder(); @@ -1835,7 +1729,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } if (keyword != null) { - SearchCriteria ssc = _networkConfigDao.createSearchCriteria(); + SearchCriteria ssc = _networksDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } @@ -1852,14 +1746,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag sc.addAnd("guestType", SearchCriteria.Op.EQ, type); } - SearchCriteria ssc = _networkConfigDao.createSearchCriteria(); + SearchCriteria ssc = _networksDao.createSearchCriteria(); ssc.addOr("accountId", SearchCriteria.Op.EQ, accountId); if (accountName == null && domainId == null) { ssc.addOr("accountId", SearchCriteria.Op.EQ, 1L); } sc.addAnd("accountId", SearchCriteria.Op.SC, ssc); - return _networkConfigDao.search(sc, searchFilter); + return _networksDao.search(sc, searchFilter); } @Override @DB @@ -1869,7 +1763,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Account account = UserContext.current().getAccount(); //Verify network id - NetworkVO network = _networkConfigDao.findById(networkId); + NetworkVO network = _networksDao.findById(networkId); if (network == null) { throw new InvalidParameterValueException("unable to find network " + networkId); } @@ -1919,7 +1813,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } //remove networks - _networkConfigDao.remove(networkId); + _networksDao.remove(networkId); txn.commit(); return true; @@ -1941,7 +1835,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } boolean success = true; - Network network = _networkConfigDao.findById(rules.get(0).getNetworkId()); + Network network = _networksDao.findById(rules.get(0).getNetworkId()); for (NetworkElement ne : _networkElements) { try { boolean handled = ne.applyRules(network, rules); diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java index eba82e475b6..14a7c35b2e9 100644 --- a/server/src/com/cloud/network/dao/NetworkDao.java +++ b/server/src/com/cloud/network/dao/NetworkDao.java @@ -21,18 +21,20 @@ import java.util.List; import com.cloud.network.NetworkAccountVO; import com.cloud.network.NetworkVO; +import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.SearchBuilder; public interface NetworkDao extends GenericDao { List listBy(long accountId); List listBy(long accountId, long offeringId, long dataCenterId); + List listBy(long accountId, long dataCenterId, GuestIpType type); @Override NetworkVO persist(NetworkVO network); - void addAccountToNetworkConfiguration(long networkId, long accountId); + void addAccountToNetwork(long networkId, long accountId); SearchBuilder createSearchBuilderForAccount(); - List getNetworkConfigurationsForOffering(long offeringId, long dataCenterId, long accountId); - List getRelatedNetworkConfigurations(long related); + List getNetworksForOffering(long offeringId, long dataCenterId, long accountId); + List getRelatedNetworks(long related); /** * Retrieves the next available mac address in this network configuration. diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index fdb6214dc29..2151ea4a756 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -25,19 +25,20 @@ import java.util.Random; import javax.ejb.Local; import javax.persistence.TableGenerator; -import com.cloud.domain.DomainVO; import com.cloud.network.NetworkAccountDaoImpl; import com.cloud.network.NetworkAccountVO; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; +import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; 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.SequenceFetcher; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @@ -45,11 +46,9 @@ import com.cloud.utils.net.NetUtils; @Local(value=NetworkDao.class) @DB(txn=false) public class NetworkDaoImpl extends GenericDaoBase implements NetworkDao { - final SearchBuilder ProfileSearch; + final SearchBuilder AllFieldsSearch; final SearchBuilder AccountSearch; - final SearchBuilder OfferingSearch; final SearchBuilder RelatedConfigSearch; - final SearchBuilder RelatedConfigsSearch; final SearchBuilder AccountNetworkSearch; NetworkAccountDaoImpl _accountsDao = new NetworkAccountDaoImpl(); @@ -60,51 +59,56 @@ public class NetworkDaoImpl extends GenericDaoBase implements N protected NetworkDaoImpl() { super(); - ProfileSearch = createSearchBuilder(); - ProfileSearch.and("trafficType", ProfileSearch.entity().getTrafficType(), SearchCriteria.Op.EQ); - ProfileSearch.and("cidr", ProfileSearch.entity().getCidr(), SearchCriteria.Op.EQ); - ProfileSearch.and("broadcastType", ProfileSearch.entity().getBroadcastDomainType(), SearchCriteria.Op.EQ); - ProfileSearch.and("offering", ProfileSearch.entity().getNetworkOfferingId(), SearchCriteria.Op.EQ); - ProfileSearch.and("datacenter", ProfileSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - ProfileSearch.done(); + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ); + AllFieldsSearch.and("cidr", AllFieldsSearch.entity().getCidr(), Op.EQ); + AllFieldsSearch.and("broadcastType", AllFieldsSearch.entity().getBroadcastDomainType(), Op.EQ); + AllFieldsSearch.and("offering", AllFieldsSearch.entity().getNetworkOfferingId(), Op.EQ); + AllFieldsSearch.and("datacenter", AllFieldsSearch.entity().getDataCenterId(), Op.EQ); + AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), Op.EQ); + AllFieldsSearch.and("guesttype", AllFieldsSearch.entity().getGuestType(), Op.EQ); + AllFieldsSearch.and("related", AllFieldsSearch.entity().getRelated(), Op.EQ); + AllFieldsSearch.done(); AccountSearch = createSearchBuilder(); - AccountSearch.and("offering", AccountSearch.entity().getNetworkOfferingId(), SearchCriteria.Op.EQ); + AccountSearch.and("offering", AccountSearch.entity().getNetworkOfferingId(), Op.EQ); SearchBuilder join = _accountsDao.createSearchBuilder(); - join.and("account", join.entity().getAccountId(), SearchCriteria.Op.EQ); + join.and("account", join.entity().getAccountId(), Op.EQ); AccountSearch.join("accounts", join, AccountSearch.entity().getId(), join.entity().getNetworkId(), JoinBuilder.JoinType.INNER); - AccountSearch.and("datacenter", AccountSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + AccountSearch.and("datacenter", AccountSearch.entity().getDataCenterId(), Op.EQ); AccountSearch.done(); - OfferingSearch = createSearchBuilder(); - OfferingSearch.and("guesttype", OfferingSearch.entity().getGuestType(), SearchCriteria.Op.EQ); - OfferingSearch.and("datacenter", OfferingSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - RelatedConfigSearch = createSearchBuilder(); - RelatedConfigSearch.and("offering", RelatedConfigSearch.entity().getNetworkOfferingId(), SearchCriteria.Op.EQ); - RelatedConfigSearch.and("datacenter", RelatedConfigSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + RelatedConfigSearch.and("offering", RelatedConfigSearch.entity().getNetworkOfferingId(), Op.EQ); + RelatedConfigSearch.and("datacenter", RelatedConfigSearch.entity().getDataCenterId(), Op.EQ); SearchBuilder join2 = _accountsDao.createSearchBuilder(); - join2.and("account", join2.entity().getAccountId(), SearchCriteria.Op.EQ); + join2.and("account", join2.entity().getAccountId(), Op.EQ); RelatedConfigSearch.join("account", join2, join2.entity().getNetworkId(), RelatedConfigSearch.entity().getId(), JoinType.INNER); RelatedConfigSearch.done(); - RelatedConfigsSearch = createSearchBuilder(); - RelatedConfigsSearch.and("related", RelatedConfigsSearch.entity().getRelated(), SearchCriteria.Op.EQ); - RelatedConfigsSearch.done(); - - AccountNetworkSearch = createSearchBuilder(); - AccountNetworkSearch.and("networkId", AccountNetworkSearch.entity().getId(), SearchCriteria.Op.EQ); + AccountNetworkSearch.and("networkId", AccountNetworkSearch.entity().getId(), Op.EQ); SearchBuilder mapJoin = _accountsDao.createSearchBuilder(); - mapJoin.and("accountId", mapJoin.entity().getAccountId(), SearchCriteria.Op.EQ); + mapJoin.and("accountId", mapJoin.entity().getAccountId(), Op.EQ); AccountNetworkSearch.join("networkSearch", mapJoin, AccountNetworkSearch.entity().getId(), mapJoin.entity().getNetworkId(), JoinBuilder.JoinType.INNER); AccountNetworkSearch.done(); _tgMacAddress = _tgs.get("macAddress"); } + @Override + public List listBy(long accountId, long dataCenterId, GuestIpType type) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("datacenter", dataCenterId); + sc.setParameters("account", accountId); + if (type != null) { + sc.setParameters("guesttype", type); + } + return listBy(sc, null); + } + public List findBy(TrafficType trafficType, Mode mode, BroadcastDomainType broadcastType, long networkOfferingId, long dataCenterId) { - SearchCriteria sc = ProfileSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("trafficType", trafficType); sc.setParameters("broadcastType", broadcastType); sc.setParameters("offering", networkOfferingId); @@ -150,7 +154,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N } @Override - public void addAccountToNetworkConfiguration(long configurationId, long accountId) { + public void addAccountToNetwork(long configurationId, long accountId) { addAccountToNetworkConfiguration(configurationId, accountId, false); } @@ -165,7 +169,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N } @Override - public List getNetworkConfigurationsForOffering(long offeringId, long dataCenterId, long accountId) { + public List getNetworksForOffering(long offeringId, long dataCenterId, long accountId) { SearchCriteria sc = RelatedConfigSearch.create(); sc.setParameters("offering", offeringId); sc.setParameters("dc", dataCenterId); @@ -174,8 +178,8 @@ public class NetworkDaoImpl extends GenericDaoBase implements N } @Override - public List getRelatedNetworkConfigurations(long related) { - SearchCriteria sc = RelatedConfigsSearch.create(); + public List getRelatedNetworks(long related) { + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("related", related); return search(sc, null); } diff --git a/server/src/com/cloud/network/element/DomainRouterElement.java b/server/src/com/cloud/network/element/DomainRouterElement.java index 3f632a184f5..9f7fdc713c9 100644 --- a/server/src/com/cloud/network/element/DomainRouterElement.java +++ b/server/src/com/cloud/network/element/DomainRouterElement.java @@ -29,6 +29,7 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IpAddress; import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.Networks.TrafficType; @@ -43,7 +44,6 @@ import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.uservm.UserVm; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; -import com.cloud.utils.net.Ip; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; @@ -142,13 +142,13 @@ public class DomainRouterElement extends AdapterBase implements NetworkElement { } @Override - public boolean associate(Network network, Ip ipAddress) throws ResourceUnavailableException { + public boolean associate(Network network, IpAddress ipAddress) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @Override - public boolean disassociate(Network network, Ip ipAddress) throws ResourceUnavailableException { + public boolean disassociate(Network network, IpAddress ipAddress) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 11b21c1cd51..0c7aee1ab09 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -626,7 +626,9 @@ CREATE TABLE `cloud`.`user_ip_address` ( `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`) + `network_id` bigint unsigned COMMENT 'network this public ip address is associated with', + PRIMARY KEY (`public_ip_address`), + CONSTRAINT `fk_user_ip_address__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks`(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`user_statistics` (