From 157156dd356edd16e79514ffdb9b57b63af3d438 Mon Sep 17 00:00:00 2001 From: alena Date: Thu, 9 Dec 2010 10:58:42 -0800 Subject: [PATCH] 1)Introduced new Network Guru - used for direct tagged network. 2)Made vm start with multiple networks --- client/tomcatconf/components.xml.in | 1 + .../ConfigurationManagerImpl.java | 11 +- .../src/com/cloud/network/NetworkManager.java | 3 + .../com/cloud/network/NetworkManagerImpl.java | 57 +++++-- .../src/com/cloud/network/dao/NetworkDao.java | 2 + .../com/cloud/network/dao/NetworkDaoImpl.java | 14 ++ .../cloud/network/guru/DirectNetworkGuru.java | 158 ++++++++++++++++++ .../cloud/network/guru/GuestNetworkGuru.java | 2 +- .../router/DomainRouterManagerImpl.java | 25 +-- 9 files changed, 238 insertions(+), 35 deletions(-) create mode 100644 server/src/com/cloud/network/guru/DirectNetworkGuru.java diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index e7095585d93..7164a764dd5 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -44,6 +44,7 @@ + diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index b45b6600f5d..fbe8a5c6cbd 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1507,6 +1507,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual network"); } + //if end ip is not specified, default it to startIp + if (endIP == null && startIP != null) { + endIP = startIP; + } + //Verify that network is valid, and ip range matches network's cidr if (networkId != null) { NetworkVO network = _networkDao.findById(networkId); @@ -2455,9 +2460,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Please specify a valid IP range id."); } - if (vlan.getNetworkId() != null) { - throw new InvalidParameterValueException("Fail to delete a vlan range as there are networks associated with it"); - } +// if (vlan.getNetworkId() != null) { +// throw new InvalidParameterValueException("Fail to delete a vlan range as there are networks associated with it"); +// } return deleteVlanAndPublicIpRange(userId, vlanDbId); diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index d86f097123f..83006c00878 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -19,6 +19,7 @@ package com.cloud.network; import java.util.List; +import com.cloud.dc.Vlan.VlanType; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.exception.ConcurrentOperationException; @@ -112,4 +113,6 @@ public interface NetworkManager extends NetworkService { String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException; boolean applyRules(Ip ip, List rules, boolean continueOnError) throws ResourceUnavailableException; + + PublicIp fetchNewPublicIp(long dcId, VlanType vlanUse, Account owner, Long networkId, boolean sourceNat) throws InsufficientAddressCapacityException; } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 967078c9991..25a3ba01d9e 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -192,14 +192,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag private Map _configs; - @DB - protected PublicIp fetchNewPublicIp(long dcId, VlanType vlanUse, Account owner, Long networkId, boolean sourceNat) throws InsufficientAddressCapacityException { + @Override @DB + public PublicIp fetchNewPublicIp(long dcId, VlanType vlanUse, Account owner, Long networkId, boolean sourceNat) throws InsufficientAddressCapacityException { Transaction txn = Transaction.currentTxn(); txn.start(); SearchCriteria sc = AssignIpAddressSearch.create(); sc.setParameters("dc", dcId); - sc.setJoinParameters("vlan", "type", vlanUse); + //for direct network take ip addresses only from the vlans belonging to the network + if (vlanUse == VlanType.DirectAttached) { + sc.setJoinParameters("vlan", "networkId", networkId); + } + sc.setJoinParameters("vlan", "type", vlanUse); + Filter filter = new Filter(IPAddressVO.class, "vlanId", true, 0l, 1l); List addrs = _ipAddressDao.lockRows(sc, filter, true); @@ -214,7 +219,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag addr.setAllocatedTime(new Date()); addr.setAllocatedInDomainId(owner.getDomainId()); addr.setAllocatedToAccountId(owner.getId()); - addr.setAssociatedNetworkId(networkId); + addr.setState(IpAddress.State.Allocating); + + if (vlanUse == VlanType.DirectAttached) { + addr.setState(IpAddress.State.Allocated); + } if (!_ipAddressDao.update(addr.getAddress(), addr)) { throw new CloudRuntimeException("Found address to allocate but unable to update: " + addr); @@ -445,6 +454,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag for (IPAddressVO addr : userIps) { if (addr.getState() == IpAddress.State.Allocating) { addr.setState(IpAddress.State.Allocated); + addr.setAssociatedNetworkId(network.getId()); _ipAddressDao.update(addr.getAddress(), addr); } else if (addr.getState() == IpAddress.State.Releasing) { _ipAddressDao.unassignIpAddress(addr.getAddress()); @@ -531,7 +541,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag _accountMgr.incrementResourceCount(ownerId, ResourceType.public_ip); String ipAddress = ip.getAddress(); - event.setParameters("address=" + ipAddress + "\nsourceNat=" + false + "\ndcId=" + zoneId); event.setDescription("Assigned a public IP address: " + ipAddress); _eventDao.persist(event); @@ -714,6 +723,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag AssignIpAddressSearch.and("allocated", AssignIpAddressSearch.entity().getAllocatedTime(), Op.NULL); AssignIpAddressSearch.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER); vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); + vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ); AssignIpAddressSearch.done(); IpAddressSearch = _ipAddressDao.createSearchBuilder(); @@ -773,17 +783,21 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new ConcurrentOperationException("Unable to acquire lock on " + owner); } try { - List configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId()); + if (predefined == null || (predefined.getBroadcastUri() == null && predefined.getBroadcastDomainType() != BroadcastDomainType.Vlan)) { + List configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId()); if (configs.size() > 0) { if (s_logger.isDebugEnabled()) { s_logger.debug("Found existing network configuration for offering " + offering + ": " + configs.get(0)); } return configs; } + } else if (predefined != null && predefined.getBroadcastUri() != null) { + //don't allow duplicated vlans in the same zone + List configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId()); } - configs = new ArrayList(); + List configs = new ArrayList(); long related = -1; @@ -1047,16 +1061,17 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag nic.setNetmask(profile.getNetmask()); nic.setGateway(profile.getGateway()); nic.setAddressFormat(profile.getFormat()); - _nicDao.update(nic.getId(), nic); - for (NetworkElement element : _networkElements) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Asking " + element.getName() + " to prepare for " + nic); - } - element.prepare(config, profile, vmProfile, dest, context); - } + _nicDao.update(nic.getId(), nic); } else { profile = new NicProfile(nic, config, nic.getBroadcastUri(), nic.getIsolationUri()); } + + for (NetworkElement element : _networkElements) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Asking " + element.getName() + " to prepare for " + nic); + } + element.prepare(config, profile, vmProfile, dest, context); + } vmProfile.addNic(profile); } @@ -1587,6 +1602,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Boolean isShared = cmd.getIsShared(); Account owner = null; + //if end ip is not specified, default it to startIp + if (endIP == null && startIP != null) { + endIP = startIP; + } + //Check if network offering exists NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); if (networkOffering == null || networkOffering.isSystemOnly()) { @@ -1617,6 +1637,15 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag owner = ctxAccount; } + //Don't allow to create network with vlan that already exists in the system + if (networkOffering.getGuestIpType() == GuestIpType.Direct && vlanId != null) { + String uri ="vlan://" + vlanId; + List networks = _networksDao.listBy(zoneId, uri); + if ((networks != null && !networks.isEmpty())) { + throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId); + } + } + //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 = _networksDao.createSearchBuilder(); diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java index 14a7c35b2e9..abfec4f3491 100644 --- a/server/src/com/cloud/network/dao/NetworkDao.java +++ b/server/src/com/cloud/network/dao/NetworkDao.java @@ -44,4 +44,6 @@ public interface NetworkDao extends GenericDao { String getNextAvailableMacAddress(long networkConfigId); List listBy(long accountId, long networkId); + + List listBy(long zoneId, String broadcastUri); } diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index 2151ea4a756..9c51e46ebcd 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -50,6 +50,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N final SearchBuilder AccountSearch; final SearchBuilder RelatedConfigSearch; final SearchBuilder AccountNetworkSearch; + final SearchBuilder ZoneBroadcastUriSearch; NetworkAccountDaoImpl _accountsDao = new NetworkAccountDaoImpl(); final TableGenerator _tgMacAddress; @@ -93,6 +94,12 @@ public class NetworkDaoImpl extends GenericDaoBase implements N AccountNetworkSearch.join("networkSearch", mapJoin, AccountNetworkSearch.entity().getId(), mapJoin.entity().getNetworkId(), JoinBuilder.JoinType.INNER); AccountNetworkSearch.done(); + + ZoneBroadcastUriSearch = createSearchBuilder(); + ZoneBroadcastUriSearch.and("dataCenterId", ZoneBroadcastUriSearch.entity().getDataCenterId(), Op.EQ); + ZoneBroadcastUriSearch.and("broadcastUri", ZoneBroadcastUriSearch.entity().getBroadcastUri(), Op.EQ); + ZoneBroadcastUriSearch.done(); + _tgMacAddress = _tgs.get("macAddress"); } @@ -200,4 +207,11 @@ public class NetworkDaoImpl extends GenericDaoBase implements N sc.setJoinParameters("networkSearch", "accountId", accountId); return listBy(sc); } + + public List listBy(long zoneId, String broadcastUri) { + SearchCriteria sc = ZoneBroadcastUriSearch.create(); + sc.setParameters("dataCenterId", zoneId); + sc.setParameters("broadcastUri", broadcastUri); + return search(sc, null); + } } diff --git a/server/src/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/com/cloud/network/guru/DirectNetworkGuru.java new file mode 100644 index 00000000000..1ab35c1e1f3 --- /dev/null +++ b/server/src/com/cloud/network/guru/DirectNetworkGuru.java @@ -0,0 +1,158 @@ +/** + * + */ +package com.cloud.network.guru; + +import java.util.Random; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlan; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapcityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.Network; +import com.cloud.network.NetworkManager; +import com.cloud.network.NetworkVO; +import com.cloud.network.Network.State; +import com.cloud.network.Networks.AddressFormat; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.IsolationType; +import com.cloud.network.Networks.Mode; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.addr.PublicIp; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.offering.NetworkOffering; +import com.cloud.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.net.NetUtils; +import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value={NetworkGuru.class}) +public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { + private static final Logger s_logger = Logger.getLogger(DirectNetworkGuru.class); + + @Inject DataCenterDao _dcDao; + @Inject VlanDao _vlanDao; + @Inject NetworkManager _networkMgr; + @Inject IPAddressDao _ipAddressDao; + Random _rand = new Random(System.currentTimeMillis()); + + @Override + public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { + //Change traffic type to Public after Alex's fix + if (!(offering.getTrafficType() == TrafficType.Guest && offering.getGuestIpType() == GuestIpType.Direct)) { + s_logger.trace("We only take care of public direct network, so this is no ours"); + return null; + } + + NetworkVO config = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId()); + DataCenterVO dc = _dcDao.findById(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()); + } + + if (userSpecified.getBroadcastUri() != null) { + config.setBroadcastUri(userSpecified.getBroadcastUri()); + config.setState(State.Setup); + } + } + + config.setDns1(dc.getDns1()); + config.setDns2(dc.getDns2()); + + return config; + } + + protected DirectNetworkGuru() { + super(); + } + + protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { + if (nic.getIp4Address() == null) { + PublicIp ip = _networkMgr.fetchNewPublicIp(dc.getId(), VlanType.DirectAttached, vm.getOwner(), network.getId(), false); + nic.setIp4Address(ip.getAddress()); + nic.setGateway(ip.getGateway()); + nic.setNetmask(ip.getNetmask()); + nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag())); + nic.setBroadcastType(BroadcastDomainType.Vlan); + nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag())); + nic.setFormat(AddressFormat.Ip4); + nic.setReservationId(ip.getVlanTag()); + nic.setMacAddress(NetUtils.long2Mac(ip.getMacAddress() | 0x060000000000l | (((long)_rand.nextInt(32768) << 25) & 0x00fffe000000l))); + } + nic.setDns1(dc.getDns1()); + nic.setDns2(dc.getDns2()); + } + + @Override + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + InsufficientAddressCapacityException, ConcurrentOperationException { + + if (nic == null) { + nic = new NicProfile(ReservationStrategy.Create, null, null, null, null); + } else if (nic.getIp4Address() == null) { + nic.setStrategy(ReservationStrategy.Start); + } else { + nic.setStrategy(ReservationStrategy.Create); + } + + DataCenter dc = _dcDao.findById(network.getDataCenterId()); + getIp(nic, dc, vm, network); + + return nic; + } + + @Override + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { + if (nic.getIp4Address() == null) { + getIp(nic, dest.getDataCenter(), vm, network); + } + } + + @Override + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + return true; + } + + @Override + public Network implement(Network network, NetworkOffering offering, DeployDestination destination, ReservationContext context) { + return network; + } + + @Override + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + } + + @Override + public void destroy(Network network, NetworkOffering offering) { + } + + @Override + public boolean trash(Network network, NetworkOffering offering, Account owner) { + return true; + } +} diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index 5a914922ef5..3aeef29c916 100644 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -71,7 +71,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { - if (offering.getTrafficType() != TrafficType.Guest) { + if (offering.getTrafficType() != TrafficType.Guest || offering.getGuestIpType() != GuestIpType.Virtual) { return null; } diff --git a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java index 5e078d2a840..a6091480de7 100644 --- a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java +++ b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java @@ -132,7 +132,6 @@ import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.PortForwardingRuleVO; import com.cloud.network.rules.RulesManager; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.service.ServiceOfferingVO; @@ -177,9 +176,9 @@ import com.cloud.vm.State; import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineGuru; +import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; @@ -2174,21 +2173,13 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute String type = null; String dhcpRange = null; - if (network.getGuestType() == GuestIpType.Virtual) { - //If network is virtual, get first ip address from cidr - String cidr = network.getCidr(); - String[] splitResult = cidr.split("\\/"); - long size = Long.valueOf(splitResult[1]); - dhcpRange = NetUtils.getIpRangeStartIpFromCidr(splitResult[0], size); - } else { - //If network is direct, get first ip address of corresponding vlan - List vlans = _vlanDao.listVlansByNetworkId(network.getId()); - if (vlans != null) { - String ipRange = vlans.get(0).getIpRange(); - String[] ips = ipRange.split("-"); - dhcpRange = ips[0]; - } - } + + //get first ip address from network cidr + String cidr = network.getCidr(); + String[] splitResult = cidr.split("\\/"); + long size = Long.valueOf(splitResult[1]); + dhcpRange = NetUtils.getIpRangeStartIpFromCidr(splitResult[0], size); + String domain = network.getNetworkDomain(); if (router.getRole() == Role.DHCP_USERDATA) {