From 14f80f2e1376329216c5250d3ecd8b3665754da1 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Fri, 29 Oct 2010 11:57:15 -0700 Subject: [PATCH] domain router up and running...now on to patching through the network between the domain router and the vm --- api/src/com/cloud/dc/DataCenter.java | 1 + .../exception/AccountLimitException.java | 41 +++++ .../exception/PermissionDeniedException.java | 5 +- .../cloud/network/NetworkConfiguration.java | 7 +- .../cloud/network/element/NetworkElement.java | 9 +- client/tomcatconf/commands.properties.in | 2 +- .../consoleproxy/ConsoleProxyManagerImpl.java | 22 +-- .../cloud/network/NetworkConfigurationVO.java | 61 +++++-- .../src/com/cloud/network/NetworkManager.java | 3 + .../com/cloud/network/NetworkManagerImpl.java | 159 ++++++++++++++++-- .../configuration/GuestNetworkGuru.java | 147 ++++++++++++++-- .../network/dao/NetworkConfigurationDao.java | 7 + .../dao/NetworkConfigurationDaoImpl.java | 28 +++ .../network/element/DomainRouterElement.java | 56 ++---- .../network/router/DomainRouterManager.java | 3 +- .../router/DomainRouterManagerImpl.java | 46 +++-- .../com/cloud/user/AccountManagerImpl.java | 3 + .../src/com/cloud/vm/UserVmManagerImpl.java | 8 +- server/src/com/cloud/vm/dao/NicDao.java | 2 + server/src/com/cloud/vm/dao/NicDaoImpl.java | 15 ++ setup/db/create-index-fk.sql | 1 + setup/db/create-schema.sql | 25 ++- utils/src/com/cloud/utils/Pair.java | 5 + .../src/com/cloud/utils/SerialVersionUID.java | 3 +- .../utils/component/ComponentLocator.java | 3 + utils/src/com/cloud/utils/db/GenericDao.java | 2 + .../com/cloud/utils/db/GenericDaoBase.java | 10 ++ .../cloud/utils/db/GenericSearchBuilder.java | 11 +- .../com/cloud/utils/db/SequenceFetcher.java | 21 ++- .../src/com/cloud/utils/db/SqlGenerator.java | 10 +- .../exception/CloudRuntimeException.java | 4 + utils/src/com/cloud/utils/net/NetUtils.java | 5 + 32 files changed, 576 insertions(+), 149 deletions(-) create mode 100644 api/src/com/cloud/exception/AccountLimitException.java diff --git a/api/src/com/cloud/dc/DataCenter.java b/api/src/com/cloud/dc/DataCenter.java index de4cca038e5..8b2e976c6bf 100644 --- a/api/src/com/cloud/dc/DataCenter.java +++ b/api/src/com/cloud/dc/DataCenter.java @@ -12,4 +12,5 @@ public interface DataCenter extends Grouping { long getId(); String getDns1(); String getDns2(); + String getGuestNetworkCidr(); } diff --git a/api/src/com/cloud/exception/AccountLimitException.java b/api/src/com/cloud/exception/AccountLimitException.java new file mode 100644 index 00000000000..85be5023558 --- /dev/null +++ b/api/src/com/cloud/exception/AccountLimitException.java @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.exception; + +import com.cloud.utils.SerialVersionUID; +import com.cloud.utils.exception.CloudRuntimeException; + +public class AccountLimitException extends CloudRuntimeException { + + private static final long serialVersionUID = SerialVersionUID.AccountLimitException; + + protected AccountLimitException() { + super(); + } + + public AccountLimitException(String msg) { + super(msg); + } + + public AccountLimitException(String msg, Throwable cause) { + super(msg, cause); + } + + // TODO: Add the actual thing that causes the exception. Is it ip address, vm, etc? + +} diff --git a/api/src/com/cloud/exception/PermissionDeniedException.java b/api/src/com/cloud/exception/PermissionDeniedException.java index bb304011aad..0dba3039654 100644 --- a/api/src/com/cloud/exception/PermissionDeniedException.java +++ b/api/src/com/cloud/exception/PermissionDeniedException.java @@ -30,7 +30,10 @@ public class PermissionDeniedException extends CloudRuntimeException { public PermissionDeniedException(String message) { super(message); - // TODO Auto-generated constructor stub + } + + protected PermissionDeniedException() { + super(); } } diff --git a/api/src/com/cloud/network/NetworkConfiguration.java b/api/src/com/cloud/network/NetworkConfiguration.java index afb1a437ba6..8ef4de71b5a 100644 --- a/api/src/com/cloud/network/NetworkConfiguration.java +++ b/api/src/com/cloud/network/NetworkConfiguration.java @@ -3,6 +3,7 @@ */ package com.cloud.network; +import java.net.URI; import java.util.List; import java.util.Set; @@ -92,7 +93,9 @@ public interface NetworkConfiguration extends ControlledEntity { long getRelated(); - String getBroadcastUri(); + URI getBroadcastUri(); - String getDns(); + String getDns1(); + + String getDns2(); } diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java index bb76304658b..bccde7339b7 100644 --- a/api/src/com/cloud/network/element/NetworkElement.java +++ b/api/src/com/cloud/network/element/NetworkElement.java @@ -3,6 +3,7 @@ */ package com.cloud.network.element; +import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; @@ -23,11 +24,11 @@ public interface NetworkElement extends Adapter { * @param offering network offering that originated the network configuration. * @return true if network configuration is now usable; false if not; null if not handled by this element. */ - Boolean implement(NetworkConfiguration config, NetworkOffering offering, Account user) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException; + boolean implement(NetworkConfiguration config, NetworkOffering offering, DeployDestination dest, Account user) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException; - Boolean prepare(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm, NetworkOffering offering, Account user) throws ConcurrentOperationException, ResourceUnavailableException; + boolean prepare(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm, NetworkOffering offering, DeployDestination dest, Account user) throws ConcurrentOperationException, ResourceUnavailableException; - Boolean release(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm, NetworkOffering offering, Account user) throws ConcurrentOperationException, ResourceUnavailableException; + boolean release(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm, NetworkOffering offering, Account user) throws ConcurrentOperationException, ResourceUnavailableException; - Boolean shutdown(NetworkConfiguration config, NetworkOffering offering, Account user) throws ConcurrentOperationException, ResourceUnavailableException; + boolean shutdown(NetworkConfiguration config, NetworkOffering offering, Account user) throws ConcurrentOperationException, ResourceUnavailableException; } diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 7e831e13054..b1d8a7cdf85 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -33,7 +33,7 @@ updateResourceLimit=com.cloud.api.commands.UpdateResourceLimitCmd;3 listResourceLimits=com.cloud.api.commands.ListResourceLimitsCmd;15 #### VM commands -deployVirtualMachine=com.cloud.api.commands.DeployVMCmd;11 +deployVirtualMachine=com.cloud.api.commands.DeployVm2Cmd;11 destroyVirtualMachine=com.cloud.api.commands.DestroyVMCmd;15 rebootVirtualMachine=com.cloud.api.commands.RebootVMCmd;15 startVirtualMachine=com.cloud.api.commands.StartVMCmd;15 diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 7e1156652ae..d883c8822ff 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -79,8 +79,8 @@ 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.VlanVO; 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; @@ -101,8 +101,8 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.ha.HighAvailabilityManager; import com.cloud.host.Host; -import com.cloud.host.HostVO; import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.info.ConsoleProxyConnectionInfo; import com.cloud.info.ConsoleProxyInfo; @@ -113,10 +113,10 @@ import com.cloud.info.RunningHostInfoAgregator; import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.maid.StackMaid; import com.cloud.network.IpAddrAllocator; -import com.cloud.network.NetworkConfigurationVO; -import com.cloud.network.NetworkManager; import com.cloud.network.IpAddrAllocator.networkInfo; import com.cloud.network.Network.TrafficType; +import com.cloud.network.NetworkConfigurationVO; +import com.cloud.network.NetworkManager; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; @@ -128,9 +128,9 @@ import com.cloud.storage.GuestOSVO; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolVO; import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeVO; -import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; @@ -159,12 +159,12 @@ import com.cloud.vm.NicProfile; import com.cloud.vm.State; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachineGuru; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VmManager; -import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.VMInstanceDao; import com.google.gson.Gson; @@ -529,7 +529,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach @Override public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { try { - return start(proxyVmId, startEventId); + return start2(proxyVmId, startEventId); } catch (StorageUnavailableException e) { s_logger.warn("Exception while trying to start console proxy", e); return null; @@ -885,7 +885,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if (s_logger.isDebugEnabled()) s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - Map context = createProxyInstance(dataCenterId); + Map context = createProxyInstance2(dataCenterId); long proxyVmId = (Long) context.get("proxyVmId"); if (proxyVmId == 0) { @@ -925,7 +925,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if (s_logger.isDebugEnabled()) s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - Map context = createProxyInstance(dataCenterId); + Map context = createProxyInstance2(dataCenterId); long proxyVmId = (Long) context.get("proxyVmId"); if (proxyVmId == 0) { @@ -1467,7 +1467,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach try { if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { try { - readyProxy = start(readyProxy.getId(), 0); + readyProxy = start2(readyProxy.getId(), 0); } finally { proxyLock.unlock(); } @@ -2451,7 +2451,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if(certList.size()>0){ CertificateVO cert = certList.get(0);//there will only be 1 cert in db for now String certStr = cert.getCertificate(); - long proxyVmId = ((StartupProxyCommand)cmd).getProxyVmId(); + long proxyVmId = (cmd).getProxyVmId(); ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId); //find corresponding host if(consoleProxy!=null){ diff --git a/server/src/com/cloud/network/NetworkConfigurationVO.java b/server/src/com/cloud/network/NetworkConfigurationVO.java index d7b97eb22dd..d6b411f69e2 100644 --- a/server/src/com/cloud/network/NetworkConfigurationVO.java +++ b/server/src/com/cloud/network/NetworkConfigurationVO.java @@ -17,6 +17,8 @@ */ package com.cloud.network; +import java.net.URI; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -24,6 +26,7 @@ import javax.persistence.Enumerated; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.TableGenerator; +import javax.persistence.Transient; import com.cloud.network.Network.BroadcastDomainType; import com.cloud.network.Network.Mode; @@ -56,7 +59,7 @@ public class NetworkConfigurationVO implements NetworkConfiguration { TrafficType trafficType; @Column(name="broadcast_uri") - String broadcastUri; + URI broadcastUri; @Column(name="gateway") String gateway; @@ -80,8 +83,8 @@ public class NetworkConfigurationVO implements NetworkConfiguration { @Enumerated(value=EnumType.STRING) State state; - @Column(name="dns") - String dns; + @Column(name="dns1") + String dns1; @Column(name="domain_id") long domainId; @@ -89,10 +92,19 @@ public class NetworkConfigurationVO implements NetworkConfiguration { @Column(name="account_id") long accountId; - @Column(name="mac_address_seq", updatable=false, nullable=false) - @TableGenerator(name="mac_address_seq", table="network_configuration", pkColumnName="id", valueColumnName="mac_address_seq", allocationSize=1) + @Column(name="set_fields") + long setFields; + + @TableGenerator(name="mac_address_seq", table="op_network_configurations", pkColumnName="id", valueColumnName="mac_address_seq", allocationSize=1) + @Transient long macAddress = 1; + @Column(name="guru_data") + String guruData; + + @Column(name="dns2") + String dns2; + public NetworkConfigurationVO() { } @@ -116,6 +128,10 @@ public class NetworkConfigurationVO implements NetworkConfiguration { public NetworkConfigurationVO(long id, NetworkConfiguration that, long offeringId, long dataCenterId, String guruName, long domainId, long accountId, long related) { this(id, that.getTrafficType(), that.getMode(), that.getBroadcastDomainType(), offeringId, dataCenterId, domainId, accountId, related); + this.gateway = that.getGateway(); + this.dns1 = that.getDns1(); + this.dns2 = that.getDns2(); + this.cidr = that.getCidr(); this.guruName = guruName; this.state = that.getState(); if (state == null) { @@ -189,6 +205,14 @@ public class NetworkConfigurationVO implements NetworkConfiguration { return broadcastDomainType; } + public String getGuruData() { + return guruData; + } + + public void setGuruData(String guruData) { + this.guruData = guruData; + } + public String getGuruName() { return guruName; } @@ -229,11 +253,11 @@ public class NetworkConfigurationVO implements NetworkConfiguration { } @Override - public String getBroadcastUri() { + public URI getBroadcastUri() { return broadcastUri; } - public void setBroadcastUri(String broadcastUri) { + public void setBroadcastUri(URI broadcastUri) { this.broadcastUri = broadcastUri; } @@ -248,14 +272,25 @@ public class NetworkConfigurationVO implements NetworkConfiguration { } @Override - public String getDns() { - return dns; + public String getDns1() { + return dns1; } - public void setDns(String dns) { - this.dns = dns; + public void setDns1(String dns) { + this.dns1 = dns; } + @Override + public String getDns2() { + return dns2; + } + + public void setDns2(String dns) { + this.dns2 = dns; + } + + + @Override public boolean equals(Object obj) { if (!(obj instanceof NetworkConfigurationVO)) { @@ -276,4 +311,8 @@ public class NetworkConfigurationVO implements NetworkConfiguration { return NetUtils.isNetworkAWithinNetworkB(this.cidr, that.cidr); } + + public boolean isImplemented() { + return broadcastUri != null && cidr != null && gateway != null && mode != null && broadcastDomainType != null; + } } diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 24fb515a524..c94e460d442 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -36,6 +36,7 @@ import com.cloud.api.commands.StartRouterCmd; import com.cloud.api.commands.StopRouterCmd; import com.cloud.api.commands.UpdateLoadBalancerRuleCmd; import com.cloud.api.commands.UpgradeRouterCmd; +import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.VlanVO; @@ -318,4 +319,6 @@ public interface NetworkManager extends Manager { List getNetworkConfigurationsforOffering(long offeringId, long dataCenterId, long accountId); List setupNetworkConfiguration(Account owner, ServiceOfferingVO offering, DeploymentPlan plan); + + String assignSourceNatIpAddress(Account account, DataCenter dc) throws InsufficientAddressCapacityException; } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 74cd58de7e2..701d2a11993 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -64,6 +64,7 @@ import com.cloud.configuration.ConfigurationManager; 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.HostPodVO; import com.cloud.dc.Vlan.VlanType; @@ -79,6 +80,7 @@ import com.cloud.event.EventTypes; import com.cloud.event.EventUtils; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; +import com.cloud.exception.AccountLimitException; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; @@ -358,6 +360,108 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService { } } + @Override @DB + public String assignSourceNatIpAddress(Account account, DataCenter dc) throws InsufficientAddressCapacityException { + final long dcId = dc.getId(); + String sourceNat = null; + + final long accountId = account.getId(); + + 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.acquire(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); + } + + } 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); + } + + return sourceNat; + + } finally { + if (account != null) { + if(s_logger.isDebugEnabled()) + s_logger.debug("Releasing lock account " + accountId); + + _accountDao.release(accountId); + } + } + } + @Override @DB public DomainRouterVO createDhcpServerForDirectlyAttachedGuests(long userId, long accountId, DataCenterVO dc, HostPodVO pod, Long candidateHost, VlanVO guestVlan) throws ConcurrentOperationException{ @@ -1766,12 +1870,11 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService { to.setIp(nic.getIp4Address()); to.setNetmask(nic.getNetmask()); to.setMac(nic.getMacAddress()); - if (config.getDns() != null) { - String[] tokens = config.getDns().split(","); - to.setDns1(tokens[0]); - if (tokens.length > 2) { - to.setDns2(tokens[1]); - } + if (config.getDns1() != null) { + to.setDns1(config.getDns1()); + } + if (config.getDns2() != null) { + to.setDns2(config.getDns2()); } if (nic.getGateway() != null) { to.setGateway(nic.getGateway()); @@ -1790,8 +1893,10 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService { } @DB - protected Pair implementNetworkConfiguration(long configId, DeployDestination dest) throws ConcurrentOperationException { - Transaction txn = Transaction.currentTxn(); + protected Pair implementNetworkConfiguration(long configId, DeployDestination dest, Account user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientAddressCapacityException { + Transaction.currentTxn(); + Pair implemented = new Pair(null, null); + NetworkConfigurationVO config = _networkConfigDao.acquire(configId); if (config == null) { throw new ConcurrentOperationException("Unable to acquire network configuration: " + configId); @@ -1800,21 +1905,43 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService { try { NetworkGuru guru = _networkGurus.get(config.getGuruName()); if (config.getState() == NetworkConfiguration.State.Implemented || config.getState() == NetworkConfiguration.State.Setup) { - return new Pair(guru, config); + implemented.set(guru, config); + return implemented; } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Asking " + guru + " to implement " + config); + } - NetworkConfiguration result = guru.implement(config, _networkOfferingDao.findById(config.getNetworkOfferingId()), dest); + NetworkOfferingVO offering = _networkOfferingDao.findById(config.getNetworkOfferingId()); + + NetworkConfiguration result = guru.implement(config, offering, dest); config.setCidr(result.getCidr()); config.setBroadcastUri(result.getBroadcastUri()); config.setGateway(result.getGateway()); - config.setDns(result.getDns()); + config.setDns1(result.getDns1()); + config.setDns2(result.getDns2()); config.setMode(result.getMode()); config.setState(NetworkConfiguration.State.Implemented); _networkConfigDao.update(configId, config); - return new Pair(guru, config); + for (NetworkElement element : _networkElements) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Asking " + element.getName() + " to implmenet " + config); + } + try { + element.implement(config, offering, dest, user); + } catch (InsufficientCapacityException e) { + throw new ResourceUnavailableException("Unable to start domain router for this VM", e); + } + } + + implemented.set(guru, config); + return implemented; } finally { + if (implemented.first() == null) { + s_logger.debug("Cleaning up because we're unable to implement network " + config); + } _networkConfigDao.release(configId); } } @@ -1825,7 +1952,7 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService { NicTO[] nicTos = new NicTO[nics.size()]; int i = 0; for (NicVO nic : nics) { - Pair implemented = implementNetworkConfiguration(nic.getNetworkConfigurationId(), dest); + Pair implemented = implementNetworkConfiguration(nic.getNetworkConfigurationId(), dest, user); NetworkGuru concierge = implemented.first(); NetworkConfigurationVO config = implemented.second(); NicProfile profile = null; @@ -1847,10 +1974,10 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService { nic.setAddressFormat(profile.getFormat()); _nicDao.update(nic.getId(), nic); for (NetworkElement element : _networkElements) { - if (!element.prepare(config, profile, vmProfile, null, user)) { - s_logger.warn("Unable to prepare " + nic + " for element " + element.getName()); - return null; + if (s_logger.isDebugEnabled()) { + s_logger.debug("Asking " + element.getName() + " to prepare for " + nic); } + element.prepare(config, profile, vmProfile, null, dest, user); } } diff --git a/server/src/com/cloud/network/configuration/GuestNetworkGuru.java b/server/src/com/cloud/network/configuration/GuestNetworkGuru.java index e15f3d8cc68..9e93fdcd600 100644 --- a/server/src/com/cloud/network/configuration/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/configuration/GuestNetworkGuru.java @@ -3,6 +3,11 @@ */ package com.cloud.network.configuration; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; + import javax.ejb.Local; import com.cloud.dc.DataCenterVO; @@ -12,25 +17,36 @@ import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapcityException; +import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network.BroadcastDomainType; import com.cloud.network.Network.Mode; import com.cloud.network.Network.TrafficType; import com.cloud.network.NetworkConfiguration; +import com.cloud.network.NetworkConfiguration.State; import com.cloud.network.NetworkConfigurationVO; import com.cloud.network.dao.NetworkConfigurationDao; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; +import com.cloud.utils.db.DB; +import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicProfile; import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.dao.NicDao; @Local(value=NetworkGuru.class) public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { - @Inject protected NetworkConfigurationDao _profileDao; + @Inject protected NetworkConfigurationDao _networkConfigDao; @Inject protected DataCenterDao _dcDao; - @Inject protected VlanDao _vlanDao; + @Inject protected VlanDao _vlanDao; + @Inject protected NicDao _nicDao; + + String _defaultGateway; + String _defaultCidr; + Random _rand = new Random(System.currentTimeMillis()); protected GuestNetworkGuru() { super(); @@ -52,43 +68,140 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { broadcastType = BroadcastDomainType.Native; mode = Mode.Dhcp; } - - NetworkConfigurationVO profile = new NetworkConfigurationVO(offering.getTrafficType(), mode, broadcastType, offering.getId(), plan.getDataCenterId()); DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); - return profile; + NetworkConfigurationVO config = new NetworkConfigurationVO(offering.getTrafficType(), mode, broadcastType, offering.getId(), plan.getDataCenterId()); + if (userSpecified != null) { + if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || + (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) { + throw new InvalidParameterValueException("cidr and gateway must be specified together."); + } + + if (userSpecified.getCidr() != null) { + config.setCidr(userSpecified.getCidr()); + config.setGateway(userSpecified.getGateway()); + } else { + String guestNetworkCidr = dc.getGuestNetworkCidr(); + String[] cidrTuple = guestNetworkCidr.split("\\/"); + config.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); + config.setCidr(guestNetworkCidr); + config.setDns1(dc.getDns1()); + config.setDns2(dc.getDns2()); + } + + if (userSpecified.getBroadcastUri() != null) { + config.setBroadcastUri(userSpecified.getBroadcastUri()); + config.setState(State.Setup); + } + } else { + String guestNetworkCidr = dc.getGuestNetworkCidr(); + String[] cidrTuple = guestNetworkCidr.split("\\/"); + config.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); + config.setCidr(guestNetworkCidr); + config.setDns1(dc.getDns1()); + config.setDns2(dc.getDns2()); + } + + return config; } @Override - public NetworkConfiguration implement(NetworkConfiguration config, NetworkOffering offering, DeployDestination destination) { - // TODO Auto-generated method stub - return null; + public NetworkConfiguration implement(NetworkConfiguration config, NetworkOffering offering, DeployDestination dest) { + assert (config.getState() == State.Allocated) : "Why implement are we implementing " + config; + + long dcId = dest.getDataCenter().getId(); + NetworkConfigurationVO implemented = new NetworkConfigurationVO(config.getTrafficType(), config.getMode(), config.getBroadcastDomainType(), config.getNetworkOfferingId(), config.getDataCenterId()); + + if (config.getBroadcastUri() == null) { + String vnet = _dcDao.allocateVnet(dcId, config.getAccountId()); + implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vnet)); + } else { + implemented.setBroadcastUri(config.getBroadcastUri()); + } + + if (config.getGateway() != null) { + implemented.setGateway(config.getGateway()); + } + + if (config.getCidr() != null) { + implemented.setCidr(config.getCidr()); + } + + if (config.getDns1() != null) { + implemented.setDns1(config.getDns1()); + } + + if (config.getDns2() != null) { + implemented.setDns2(config.getDns2()); + } + + return implemented; } @Override public NicProfile allocate(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; + if (config.getTrafficType() != TrafficType.Guest) { + return null; + } + + if (nic == null) { + nic = new NicProfile(ReservationStrategy.Start, null, null, null, null); + } else { + nic.setStrategy(ReservationStrategy.Create); + } + + if (nic.getMacAddress() == null) { + nic.setMacAddress(_networkConfigDao.getNextAvailableMacAddress(config.getId())); + if (nic.getMacAddress() == null) { + throw new InsufficientAddressCapacityException("Unable to allocate more mac addresses"); + } + } + + return nic; } + + @DB + protected String acquireGuestIpAddress(NetworkConfiguration config) { + List ips = _nicDao.listIpAddressInNetworkConfiguration(config.getId()); + String[] cidr = config.getCidr().split("/"); + Set allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1])); + Set usedIps = new TreeSet (); + for (String ip : ips) { + usedIps.add(NetUtils.ip2Long(ip)); + } + if (usedIps.size() != 0) { + allPossibleIps.removeAll(usedIps); + } + if (allPossibleIps.isEmpty()) { + return null; + } + Long[] array = allPossibleIps.toArray(new Long[allPossibleIps.size()]); + return NetUtils.long2Ip(array[_rand.nextInt() % array.length]); + } @Override public String reserve(NicProfile nic, NetworkConfiguration config, VirtualMachineProfile vm, DeployDestination dest) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; + assert (nic.getReservationStrategy() == ReservationStrategy.Start) : "What can I do for nics that are not allocated at start? "; + + nic.setBroadcastUri(config.getBroadcastUri()); + nic.setIsolationUri(config.getBroadcastUri()); + nic.setGateway(config.getGateway()); + nic.setIp4Address(acquireGuestIpAddress(config)); + nic.setNetmask(NetUtils.cidr2Netmask(config.getCidr())); + nic.setDns1(config.getDns1()); + nic.setDns2(config.getDns2()); + return "ABCD"; } @Override public boolean release(String uniqueId) { - // TODO Auto-generated method stub - return false; + return true; } @Override public void destroy(NetworkConfiguration config, NetworkOffering offering) { - // TODO Auto-generated method stub - + config.getBroadcastUri(); } - } diff --git a/server/src/com/cloud/network/dao/NetworkConfigurationDao.java b/server/src/com/cloud/network/dao/NetworkConfigurationDao.java index dc98d7529c1..74571cecc0f 100644 --- a/server/src/com/cloud/network/dao/NetworkConfigurationDao.java +++ b/server/src/com/cloud/network/dao/NetworkConfigurationDao.java @@ -33,4 +33,11 @@ public interface NetworkConfigurationDao extends GenericDao createSearchBuilderForAccount(); List getNetworkConfigurationsForOffering(long offeringId, long dataCenterId, long accountId); List getRelatedNetworkConfigurations(long related); + + /** + * Retrieves the next available mac address in this network configuration. + * @param networkConfigId id + * @return mac address if there is one. null if not. + */ + String getNextAvailableMacAddress(long networkConfigId); } diff --git a/server/src/com/cloud/network/dao/NetworkConfigurationDaoImpl.java b/server/src/com/cloud/network/dao/NetworkConfigurationDaoImpl.java index 4df669c1e04..754687c5065 100644 --- a/server/src/com/cloud/network/dao/NetworkConfigurationDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkConfigurationDaoImpl.java @@ -17,9 +17,13 @@ */ package com.cloud.network.dao; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.List; +import java.util.Random; import javax.ejb.Local; +import javax.persistence.TableGenerator; import com.cloud.network.Network.BroadcastDomainType; import com.cloud.network.Network.Mode; @@ -33,7 +37,10 @@ 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.SequenceFetcher; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; @Local(value=NetworkConfigurationDao.class) @DB(txn=false) public class NetworkConfigurationDaoImpl extends GenericDaoBase implements NetworkConfigurationDao { @@ -44,6 +51,9 @@ public class NetworkConfigurationDaoImpl extends GenericDaoBase RelatedConfigsSearch; NetworkAccountDaoImpl _accountsDao = new NetworkAccountDaoImpl(); + final TableGenerator _tgMacAddress; + Random _rand = new Random(System.currentTimeMillis()); + long _prefix = 0x2; protected NetworkConfigurationDaoImpl() { super(); @@ -79,6 +89,8 @@ public class NetworkConfigurationDaoImpl extends GenericDaoBase findBy(TrafficType trafficType, Mode mode, BroadcastDomainType broadcastType, long networkOfferingId, long dataCenterId) { @@ -116,6 +128,13 @@ public class NetworkConfigurationDaoImpl extends GenericDaoBase offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork); - NetworkOfferingVO controlOffering = offerings.get(0); NetworkConfigurationVO controlConfig = _networkMgr.setupNetworkConfiguration(_systemAcct, controlOffering, plan).get(0); - router = new DomainRouterVO(id, _offering.getId(), VirtualMachineName.getRouterName(id, _instance), _template.getId(), _template.getGuestOSId(), owner.getDomainId(), owner.getId(), virtualConfig.getId(), _offering.getOfferHA()); - _routerDao.persist(router); - - List> networks = new ArrayList>(3); + List> networks = new ArrayList>(3); + NetworkOfferingVO publicOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmPublicNetwork).get(0); + List publicConfigs = _networkMgr.setupNetworkConfiguration(_systemAcct, publicOffering, plan); NicProfile defaultNic = new NicProfile(); defaultNic.setDefaultNic(true); + defaultNic.setIp4Address(sourceNatIp); defaultNic.setDeviceId(2); - networks.add(new Pair((NetworkConfigurationVO)publicConfig, defaultNic)); - networks.add(new Pair((NetworkConfigurationVO)virtualConfig, null)); - networks.add(new Pair(controlConfig, null)); + networks.add(new Pair(publicConfigs.get(0), defaultNic)); + NicProfile gatewayNic = new NicProfile(); + gatewayNic.setIp4Address(guestConfig.getGateway()); + gatewayNic.setBroadcastUri(guestConfig.getBroadcastUri()); + gatewayNic.setBroadcastType(guestConfig.getBroadcastDomainType()); + gatewayNic.setIsolationUri(guestConfig.getBroadcastUri()); + gatewayNic.setMode(guestConfig.getMode()); + gatewayNic.setNetmask(NetUtils.getCidrSubNet(guestConfig.getCidr())); + networks.add(new Pair((NetworkConfigurationVO)guestConfig, gatewayNic)); + networks.add(new Pair(controlConfig, null)); + + router = new DomainRouterVO(id, _offering.getId(), VirtualMachineName.getRouterName(id, _instance), _template.getId(), _template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestConfig.getId(), _offering.getOfferHA()); + router = _routerDao.persist(router); _vmMgr.allocate(router, _template, _offering, networks, plan, owner); } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 05b2f75e68e..cb0fb3449ad 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -564,6 +564,9 @@ public class AccountManagerImpl implements AccountManager { @Override public AccountVO getSystemAccount() { + if (_systemAccount == null) { + _systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); + } return _systemAccount; } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 8f1c70f0ff3..08d72a0d2e6 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -3917,16 +3917,16 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM s_logger.debug("Allocating in the DB for vm"); - Transaction txn = Transaction.currentTxn(); - txn.start(); - vm = _vmDao.persist(vm); - List configs = _networkMgr.setupNetworkConfiguration(owner, offering, plan); List> networks = new ArrayList>(); for (NetworkConfigurationVO config : configs) { networks.add(new Pair(config, null)); } + Transaction txn = Transaction.currentTxn(); + txn.start(); + vm = _vmDao.persist(vm); + if (_itMgr.allocate(vm, template, offering, rootDiskOffering, dataDiskOfferings, networks, plan, owner) == null) { return null; } diff --git a/server/src/com/cloud/vm/dao/NicDao.java b/server/src/com/cloud/vm/dao/NicDao.java index 6f4e3616a3e..6213eaa3330 100644 --- a/server/src/com/cloud/vm/dao/NicDao.java +++ b/server/src/com/cloud/vm/dao/NicDao.java @@ -10,5 +10,7 @@ import com.cloud.vm.NicVO; public interface NicDao extends GenericDao { List listBy(long instanceId); + + List listIpAddressInNetworkConfiguration(long networkConfigId); } diff --git a/server/src/com/cloud/vm/dao/NicDaoImpl.java b/server/src/com/cloud/vm/dao/NicDaoImpl.java index 15f7c63e83f..ba209d5e8bf 100644 --- a/server/src/com/cloud/vm/dao/NicDaoImpl.java +++ b/server/src/com/cloud/vm/dao/NicDaoImpl.java @@ -8,13 +8,16 @@ import java.util.List; import javax.ejb.Local; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.vm.NicVO; @Local(value=NicDao.class) public class NicDaoImpl extends GenericDaoBase implements NicDao { private final SearchBuilder InstanceSearch; + private final GenericSearchBuilder IpSearch; protected NicDaoImpl() { super(); @@ -22,6 +25,12 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { InstanceSearch = createSearchBuilder(); InstanceSearch.and("instance", InstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); InstanceSearch.done(); + + IpSearch = createSearchBuilder(String.class); + IpSearch.select(null, Func.DISTINCT, IpSearch.entity().getIp4Address()); + IpSearch.and("nc", IpSearch.entity().getNetworkConfigurationId(), SearchCriteria.Op.EQ); + IpSearch.and("address", IpSearch.entity().getIp4Address(), SearchCriteria.Op.NNULL); + IpSearch.done(); } @Override @@ -31,4 +40,10 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { return listBy(sc); } + @Override + public List listIpAddressInNetworkConfiguration(long networkConfigId) { + SearchCriteria sc = IpSearch.create(); + sc.setParameters("nc", networkConfigId); + return customSearch(sc, null); + } } diff --git a/setup/db/create-index-fk.sql b/setup/db/create-index-fk.sql index c1b3d6ed727..7801aaac0c2 100755 --- a/setup/db/create-index-fk.sql +++ b/setup/db/create-index-fk.sql @@ -61,6 +61,7 @@ ALTER TABLE `cloud`.`storage_pool` ADD CONSTRAINT `fk_storage_pool__cluster_id` ALTER TABLE `cloud`.`storage_pool_details` ADD CONSTRAINT `fk_storage_pool_details__pool_id` FOREIGN KEY `fk_storage_pool__pool_id`(`pool_id`) REFERENCES `storage_pool`(`id`) ON DELETE CASCADE; ALTER TABLE `cloud`.`storage_pool_details` ADD INDEX `i_storage_pool_details__name__value`(`name`, `value`); +ALTER TABLE `cloud`.`op_network_configurations` ADD CONSTRAINT `fk_op_network_configurations__id` FOREIGN KEY `fk_op_network_configurations__id`(`id`) REFERENCES `network_configurations`(`id`) ON DELETE CASCADE; ALTER TABLE `cloud`.`user` ADD INDEX `i_user__secret_key_removed`(`secret_key`, `removed`); ALTER TABLE `cloud`.`user` ADD INDEX `i_user__removed`(`removed`); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 836a32d8894..9db4f587e77 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -91,6 +91,13 @@ CREATE TABLE `cloud`.`hypervsior_properties` ( `max_network_devices` int(10) NOT NULL COMMENT 'maximum number of network devices' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`op_network_configurations`( + `id` bigint unsigned NOT NULL UNIQUE KEY, + `mac_address_seq` bigint unsigned NOT NULL DEFAULT 1 COMMENT 'mac address', + PRIMARY KEY(`id`) +# CONSTRAINT `fk__op_network_configurations__id` FOREIGN KEY `fk_op_network_configurations__id`(`id`) REFERENCES `network_configurations`(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE TABLE `cloud`.`network_configurations` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `name` varchar(255) COMMENT 'name for this network', @@ -107,11 +114,15 @@ CREATE TABLE `cloud`.`network_configurations` ( `related` bigint unsigned NOT NULL COMMENT 'related to what other network configuration', `domain_id` bigint unsigned NOT NULL COMMENT 'foreign key to domain id', `account_id` bigint unsigned NOT NULL COMMENT 'owner of this network', - `mac_address_seq` bigint unsigned DEFAULT 1 COMMENT 'mac address seq number', - `dns` varchar(255) COMMENT 'comma separated DNS list', + `dns1` varchar(255) COMMENT 'comma separated DNS list', + `dns2` varchar(255) COMMENT 'comma separated DNS list', + `guru_data` varchar(1024) COMMENT 'data stored by the network guru that setup this network', + `set_fields` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'which fields are set already', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + CREATE TABLE `cloud`.`account_network_ref` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `account_id` bigint unsigned NOT NULL COMMENT 'account id', @@ -613,7 +624,7 @@ CREATE TABLE `cloud`.`user_vm` ( CREATE TABLE `cloud`.`domain_router` ( `id` bigint unsigned UNIQUE NOT NULL COMMENT 'Primary Key', - `gateway` varchar(15) NOT NULL COMMENT 'ip address of the gateway to this domR', + `gateway` varchar(15) COMMENT 'ip address of the gateway to this domR', `ram_size` int(10) unsigned NOT NULL DEFAULT 128 COMMENT 'memory to use in mb', `dns1` varchar(15) COMMENT 'dns1', `dns2` varchar(15) COMMENT 'dns2', @@ -621,15 +632,15 @@ CREATE TABLE `cloud`.`domain_router` ( `public_mac_address` varchar(17) COMMENT 'mac address of the public facing network card', `public_ip_address` varchar(15) COMMENT 'public ip address used for source net', `public_netmask` varchar(15) COMMENT 'netmask used for the domR', - `guest_mac_address` varchar(17) NOT NULL COMMENT 'mac address of the pod facing network card', + `guest_mac_address` varchar(17) COMMENT 'mac address of the pod facing network card', `guest_dc_mac_address` varchar(17) COMMENT 'mac address of the data center facing network card', - `guest_netmask` varchar(15) NOT NULL COMMENT 'netmask used for the guest network', - `guest_ip_address` varchar(15) NOT NULL COMMENT ' ip address in the guest network', + `guest_netmask` varchar(15) COMMENT 'netmask used for the guest network', + `guest_ip_address` varchar(15) COMMENT ' ip address in the guest network', `vnet` varchar(18) COMMENT 'vnet', `dc_vlan` varchar(18) COMMENT 'vnet', `vlan_db_id` bigint unsigned COMMENT 'Foreign key into vlan id table', `vlan_id` varchar(255) COMMENT 'optional VLAN ID for DomainRouter that can be used in rundomr.sh', - `dhcp_ip_address` bigint unsigned NOT NULL DEFAULT 2 COMMENT 'next ip address for dhcp for this domR', + `dhcp_ip_address` bigint unsigned DEFAULT 2 COMMENT 'next ip address for dhcp for this domR', `network_configuration_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'network configuration that this domain router belongs to', `role` varchar(64) NOT NULL COMMENT 'type of role played by this router', PRIMARY KEY (`id`) diff --git a/utils/src/com/cloud/utils/Pair.java b/utils/src/com/cloud/utils/Pair.java index ef5ad3ed41a..0d06a2b30c8 100755 --- a/utils/src/com/cloud/utils/Pair.java +++ b/utils/src/com/cloud/utils/Pair.java @@ -44,6 +44,11 @@ public class Pair { return t; } + public void set(T t, U u) { + this.t = t; + this.u = u; + } + @Override // Note: This means any two pairs with null for both values will match each // other but what can I do? This is due to stupid type erasure. diff --git a/utils/src/com/cloud/utils/SerialVersionUID.java b/utils/src/com/cloud/utils/SerialVersionUID.java index a2132767e06..4026a683b2e 100755 --- a/utils/src/com/cloud/utils/SerialVersionUID.java +++ b/utils/src/com/cloud/utils/SerialVersionUID.java @@ -31,7 +31,8 @@ public interface SerialVersionUID { public static final long UUID = Base | 0x1; public static final long CloudRuntimeException = Base | 0x2; public static final long CloudStartupServlet = Base | 0x3; - public static final long CloudServiceImpl = Base | 0x4; + public static final long CloudServiceImpl = Base | 0x4; + public static final long AccountLimitException = Base | 0x5; public static final long UnsupportedVersionException = Base | 0xb; public static final long DataCenterIpAddressPK = Base | 0xc; public static final long UnableToExecuteException = Base | 0xd; diff --git a/utils/src/com/cloud/utils/component/ComponentLocator.java b/utils/src/com/cloud/utils/component/ComponentLocator.java index 14d111d2126..47a616c84f2 100755 --- a/utils/src/com/cloud/utils/component/ComponentLocator.java +++ b/utils/src/com/cloud/utils/component/ComponentLocator.java @@ -348,6 +348,9 @@ public class ComponentLocator extends Thread implements ComponentLocatorMBean { Info info = entry.getValue(); s_logger.info("Injecting Manager: " + info.name); inject(info.clazz, info.instance); + } + for (Map.Entry> entry : entries) { + Info info = entry.getValue(); s_logger.info("Configuring Manager: " + info.name); try { info.instance.configure(info.name, info.params); diff --git a/utils/src/com/cloud/utils/db/GenericDao.java b/utils/src/com/cloud/utils/db/GenericDao.java index 530da65469f..b2318293992 100755 --- a/utils/src/com/cloud/utils/db/GenericDao.java +++ b/utils/src/com/cloud/utils/db/GenericDao.java @@ -222,4 +222,6 @@ public interface GenericDao { */ boolean configure(String name, Map params) throws ConfigurationException; + List customSearch(SearchCriteria sc, Filter filter); + } \ No newline at end of file diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index 236d49980bb..bc39ab4c694 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -427,6 +427,15 @@ public abstract class GenericDaoBase implements Gene } } + @Override @DB(txn=false) + public List customSearch(SearchCriteria sc, final Filter filter) { + if (_removed != null) { + sc.addAnd(_removed.second().field.getName(), SearchCriteria.Op.NULL); + } + + return searchIncludingRemoved(sc, filter); + } + @DB(txn=false) protected void setField(Object entity, Field field, ResultSet rs, int index) throws SQLException { try { @@ -731,6 +740,7 @@ public abstract class GenericDaoBase implements Gene return _entityBeanType; } + @DB(txn=false) protected T findOneIncludingRemovedBy(final SearchCriteria sc) { Filter filter = new Filter(1); List results = searchIncludingRemoved(sc, filter, null, false); diff --git a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java index 11609eb2f3d..0a3b7e47b1c 100644 --- a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java +++ b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java @@ -96,6 +96,15 @@ public class GenericSearchBuilder implements MethodInterceptor { return this; } + /** + * Specifies the field to select. + * + * @param fieldName The field name of the result object to put the value of the field selected. This can be null if you're selecting only one field and the result is not a complex object. + * @param func function to place. + * @param useless column to select. Call this with this.entity() method. + * @param params parameters to the function. + * @return a SearchBuilder to build more search parts. + */ public GenericSearchBuilder select(String fieldName, Func func, Object useless, Object... params) { assert _entity != null : "SearchBuilder cannot be modified once it has been setup"; assert _specifiedAttrs.size() <= 1 : "You can't specify more than one field to search on"; @@ -346,7 +355,7 @@ public class GenericSearchBuilder implements MethodInterceptor { } if (op == Op.SC) { - sql.append(" (").append(((SearchCriteria)params[0]).getWhereClause()).append(") "); + sql.append(" (").append(((SearchCriteria)params[0]).getWhereClause()).append(") "); return; } diff --git a/utils/src/com/cloud/utils/db/SequenceFetcher.java b/utils/src/com/cloud/utils/db/SequenceFetcher.java index 5413b76309e..d562cc0056e 100644 --- a/utils/src/com/cloud/utils/db/SequenceFetcher.java +++ b/utils/src/com/cloud/utils/db/SequenceFetcher.java @@ -19,6 +19,7 @@ package com.cloud.utils.db; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -83,6 +84,7 @@ public class SequenceFetcher { @Override @SuppressWarnings("unchecked") public T call() throws Exception { try { + PreparedStatement stmt = null; StringBuilder sql = new StringBuilder("SELECT "); sql.append(_tg.valueColumnName()).append(" FROM ").append(_tg.table()); sql.append(" WHERE ").append(_tg.pkColumnName()).append(" = ? FOR UPDATE"); @@ -97,22 +99,23 @@ public class SequenceFetcher { } sql = new StringBuilder("UPDATE "); - sql.append(_tg.table()).append(" SET ").append(_tg.valueColumnName()).append("=").append(_tg.valueColumnName()).append("+?"); + sql.append(_tg.table()).append(" SET ").append(_tg.valueColumnName()).append("=").append("?+?"); sql.append(" WHERE ").append(_tg.pkColumnName()).append("=?"); PreparedStatement updateStmt = txn.prepareStatement(sql.toString()); - updateStmt.setInt(1, _tg.allocationSize()); + updateStmt.setInt(2, _tg.allocationSize()); if (_key == null) { - updateStmt.setString(2, _tg.pkColumnValue()); + updateStmt.setString(3, _tg.pkColumnValue()); } else { - updateStmt.setObject(2, _key); + updateStmt.setObject(3, _key); } ResultSet rs = null; try { txn.start(); - rs = selectStmt.executeQuery(); + stmt = selectStmt; + rs = stmt.executeQuery(); Object obj = null; while (rs.next()) { if (_clazz.isAssignableFrom(Long.class)) { @@ -129,10 +132,14 @@ public class SequenceFetcher { return null; } - int rows = updateStmt.executeUpdate(); + updateStmt.setObject(1, obj); + stmt = updateStmt; + int rows = stmt.executeUpdate(); assert rows == 1 : "Come on....how exactly did we update this many rows " + rows + " for " + updateStmt.toString(); txn.commit(); return (T)obj; + } catch (SQLException e) { + s_logger.warn("Caught this exception when running: " + (stmt != null ? stmt.toString() : ""), e); } finally { if (rs != null) { rs.close(); @@ -142,7 +149,7 @@ public class SequenceFetcher { txn.close(); } } catch (Exception e) { - s_logger.warn("Caught this exception when running", e); + s_logger.warn("Caught this exception when running.", e); } return null; } diff --git a/utils/src/com/cloud/utils/db/SqlGenerator.java b/utils/src/com/cloud/utils/db/SqlGenerator.java index 947f11ffb1c..183e8ec450a 100755 --- a/utils/src/com/cloud/utils/db/SqlGenerator.java +++ b/utils/src/com/cloud/utils/db/SqlGenerator.java @@ -103,6 +103,11 @@ public class SqlGenerator { for (Field field : fields) { field.setAccessible(true); + TableGenerator tg = field.getAnnotation(TableGenerator.class); + if (tg != null) { + _generators.put(field.getName(), tg); + } + if (!DbUtil.isPersistable(field)) { continue; } @@ -123,11 +128,6 @@ public class SqlGenerator { continue; } - TableGenerator tg = field.getAnnotation(TableGenerator.class); - if (tg != null) { - _generators.put(field.getName(), tg); - } - Attribute attr = new Attribute(clazz, overrides, field, tableName, embedded, isId); if (attr.isId()) { diff --git a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java index 5b296f617b2..76a093a7099 100755 --- a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java +++ b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java @@ -36,4 +36,8 @@ public class CloudRuntimeException extends RuntimeException { public CloudRuntimeException(String message, Throwable th) { super(message, th); } + + protected CloudRuntimeException() { + super(); + } } diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index df63bcb505b..754df95e6fa 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -604,6 +604,11 @@ public class NetUtils { return long2Ip(numericNetmask); } + public static String cidr2Netmask(String cidr) { + String[] tokens = cidr.split("\\/"); + return getCidrNetmask(Integer.parseInt(tokens[1])); + } + public static long getCidrSize(String netmask) { long ip = ip2Long(netmask); int count = 0;