diff --git a/server/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java b/server/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java index 96cb4a862e7..8c54196df99 100644 --- a/server/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java +++ b/server/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java @@ -18,43 +18,21 @@ package com.cloud.api.commands; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.apache.log4j.Logger; import com.cloud.api.BaseCmd; +import com.cloud.api.BaseCmd.Manager; +import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.ServerApiException; -import com.cloud.dc.HostPodVO; -import com.cloud.dc.Vlan; -import com.cloud.dc.Vlan.VlanType; +import com.cloud.api.response.VlanIpRangeResponse; import com.cloud.dc.VlanVO; -import com.cloud.user.Account; -import com.cloud.user.User; -import com.cloud.utils.Pair; - +import com.cloud.serializer.SerializerHelper; + +@Implementation(method="createVlanAndPublicIpRange", manager=Manager.ConfigManager) public class CreateVlanIpRangeCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateVlanIpRangeCmd.class.getName()); private static final String s_name = "createvlaniprangeresponse"; - private static final List> s_properties = new ArrayList>(); - - static { - s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.END_IP, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.FOR_VIRTUAL_NETWORK, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.GATEWAY, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.NETMASK, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.POD_ID, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.START_IP, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.VLAN, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.ZONE_ID, Boolean.TRUE)); - - s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE)); - } ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -140,86 +118,32 @@ public class CreateVlanIpRangeCmd extends BaseCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// + @Override public String getName() { return s_name; - } - public List> getProperties() { - return s_properties; - } - + } + @Override - public List> execute(Map params) { - Boolean forVirtualNetwork = (Boolean) params.get(BaseCmd.Properties.FOR_VIRTUAL_NETWORK.getName()); - String vlanId = (String) params.get(BaseCmd.Properties.VLAN.getName()); - String vlanGateway = (String) params.get(BaseCmd.Properties.GATEWAY.getName()); - String vlanNetmask = (String) params.get(BaseCmd.Properties.NETMASK.getName()); - Long zoneId = (Long) params.get(BaseCmd.Properties.ZONE_ID.getName()); - String accountName = (String) params.get(BaseCmd.Properties.ACCOUNT.getName()); - Long domainId = (Long) params.get(BaseCmd.Properties.DOMAIN_ID.getName()); - Long podId = (Long) params.get(BaseCmd.Properties.POD_ID.getName()); - String startIp = (String) params.get(BaseCmd.Properties.START_IP.getName()); - String endIp = (String) params.get(BaseCmd.Properties.END_IP.getName()); - Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName()); - - if (userId == null) { - userId = Long.valueOf(User.UID_SYSTEM); - } - - // If forVirtualNetworks isn't specified, default it to true - if (forVirtualNetwork == null) { - forVirtualNetwork = Boolean.TRUE; - } - - // If the VLAN id is null, default it to untagged - if (vlanId == null) { - vlanId = Vlan.UNTAGGED; - } - - // If an account name and domain ID are specified, look up the account - Long accountId = null; - if (accountName != null && domainId != null) { - Account account = getManagementServer().findAccountByName(accountName, domainId); - if (account == null || account.getRemoved() != null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid account."); - } else { - accountId = account.getId(); - } - } - - VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached; - - // Create a VLAN and public IP addresses - VlanVO vlan = null; - try { - vlan = getManagementServer().createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIp, endIp); - } catch (Exception e) { - s_logger.error("Error adding VLAN: ", e); - throw new ServerApiException (BaseCmd.INTERNAL_ERROR, e.getMessage()); - } - - List> returnValues = new ArrayList>(); - returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), vlan.getId())); - returnValues.add(new Pair(BaseCmd.Properties.FOR_VIRTUAL_NETWORK.getName(), forVirtualNetwork)); - returnValues.add(new Pair(BaseCmd.Properties.VLAN.getName(), vlan.getVlanId())); - returnValues.add(new Pair(BaseCmd.Properties.ZONE_ID.getName(), vlan.getDataCenterId())); - - if (accountId != null) { - returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountName)); - returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), domainId)); - returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(domainId).getName())); - } - - if (podId != null) { - HostPodVO pod = getManagementServer().findHostPodById(podId); - returnValues.add(new Pair(BaseCmd.Properties.POD_ID.getName(), podId)); - returnValues.add(new Pair(BaseCmd.Properties.POD_NAME.getName(), pod.getName())); - } - - returnValues.add(new Pair(BaseCmd.Properties.GATEWAY.getName(), vlan.getVlanGateway())); - returnValues.add(new Pair(BaseCmd.Properties.NETMASK.getName(), vlan.getVlanNetmask())); - returnValues.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), vlan.getIpRange())); - returnValues.add(new Pair(BaseCmd.Properties.START_IP.getName(), startIp)); - returnValues.add(new Pair(BaseCmd.Properties.END_IP.getName(), endIp)); - return returnValues; + public String getResponse() { + VlanVO vlan = (VlanVO)getResponseObject(); + + VlanIpRangeResponse response = new VlanIpRangeResponse(); + response.setAccountName(accountName); + response.setDescription(vlan.getIpRange()); + response.setDomainId(domainId); + response.setEndIp(endIp); + response.setForVirtualNetwork(forVirtualNetwork); + response.setGateway(vlan.getVlanGateway()); + response.setId(vlan.getId()); + response.setNetmask(vlan.getVlanNetmask()); + response.setPodId(podId); + response.setStartIp(startIp); + response.setVlan(vlan.getVlanId()); + response.setZoneId(vlan.getDataCenterId()); + // TODO: implement +// response.setDomainName(vlan.getDomainName()); +// response.setPodName(podName); + + return SerializerHelper.toSerializedString(response); } } diff --git a/server/src/com/cloud/api/response/VlanIpRangeResponse.java b/server/src/com/cloud/api/response/VlanIpRangeResponse.java new file mode 100644 index 00000000000..f7f6e5ec3d3 --- /dev/null +++ b/server/src/com/cloud/api/response/VlanIpRangeResponse.java @@ -0,0 +1,160 @@ +package com.cloud.api.response; + +import com.cloud.api.ResponseObject; +import com.cloud.serializer.Param; + +public class VlanIpRangeResponse implements ResponseObject { + @Param(name="id") + private Long id; + + @Param(name="forvirtualnetwork") + private Boolean forVirtualNetwork; + + @Param(name="zoneid") + private Long zoneId; + + @Param(name="vlan") + private String vlan; + + @Param(name="account") + private String accountName; + + @Param(name="domainid") + private Long domainId; + + @Param(name="domain") + private String domainName; + + @Param(name="podid") + private Long podId; + + @Param(name="podname") + private String podName; + + @Param(name="gateway") + private String gateway; + + @Param(name="netmask") + private String netmask; + + @Param(name="description") + private String description; + + @Param(name="startip") + private String startIp; + + @Param(name="endip") + private String endIp; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Boolean getForVirtualNetwork() { + return forVirtualNetwork; + } + + public void setForVirtualNetwork(Boolean forVirtualNetwork) { + this.forVirtualNetwork = forVirtualNetwork; + } + + public Long getZoneId() { + return zoneId; + } + + public void setZoneId(Long zoneId) { + this.zoneId = zoneId; + } + + public String getVlan() { + return vlan; + } + + public void setVlan(String vlan) { + this.vlan = vlan; + } + + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public Long getDomainId() { + return domainId; + } + + public void setDomainId(Long domainId) { + this.domainId = domainId; + } + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public Long getPodId() { + return podId; + } + + public void setPodId(Long podId) { + this.podId = podId; + } + + public String getPodName() { + return podName; + } + + public void setPodName(String podName) { + this.podName = podName; + } + + public String getGateway() { + return gateway; + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } + + public String getNetmask() { + return netmask; + } + + public void setNetmask(String netmask) { + this.netmask = netmask; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getStartIp() { + return startIp; + } + + public void setStartIp(String startIp) { + this.startIp = startIp; + } + + public String getEndIp() { + return endIp; + } + + public void setEndIp(String endIp) { + this.endIp = endIp; + } +} diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index 2d34e9624da..71141f245fa 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -23,6 +23,7 @@ import com.cloud.api.commands.AddConfigCmd; import com.cloud.api.commands.CreateDiskOfferingCmd; import com.cloud.api.commands.CreatePodCmd; import com.cloud.api.commands.CreateServiceOfferingCmd; +import com.cloud.api.commands.CreateVlanIpRangeCmd; import com.cloud.api.commands.DeleteDiskOfferingCmd; import com.cloud.api.commands.DeletePodCmd; import com.cloud.api.commands.DeleteServiceOfferingCmd; @@ -35,8 +36,9 @@ import com.cloud.api.commands.UpdateServiceOfferingCmd; import com.cloud.api.commands.UpdateZoneCmd; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; -import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InternalErrorException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.service.ServiceOfferingVO; @@ -196,21 +198,34 @@ public interface ConfigurationManager extends Manager { */ DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String dns3, String dns4, String vnetRange, String guestCidr) throws InvalidParameterValueException, InternalErrorException; - /** + /** * Edits a zone in the database. Will not allow you to edit DNS values if there are VMs in the specified zone. * @param UpdateZoneCmd * @return Updated zone */ - DataCenterVO editZone(UpdateZoneCmd cmd) throws InvalidParameterValueException, InternalErrorException; - - /** + DataCenterVO editZone(UpdateZoneCmd cmd) throws InvalidParameterValueException, InternalErrorException; + + /** * Deletes a zone from the database. Will not allow you to delete zones that are being used anywhere in the system. * @param userId * @param zoneId */ - void deleteZone(DeleteZoneCmd cmd) throws InvalidParameterValueException, InternalErrorException; + void deleteZone(DeleteZoneCmd cmd) throws InvalidParameterValueException, InternalErrorException; /** + * Associates an ip address list to an account. The list of ip addresses are all addresses associated with the given vlan id. + * @param userId + * @param accountId + * @param zoneId + * @param vlanId + * @throws InsufficientAddressCapacityException + * @throws InvalidParameterValueException + * @throws InternalErrorException + */ + public void associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId) throws InsufficientAddressCapacityException, + InvalidParameterValueException, InternalErrorException; + + /** * Adds a VLAN to the database, along with an IP address range. Can add three types of VLANs: (1) zone-wide VLANs on the virtual public network (2) pod-wide direct attached VLANs (3) account-specific direct attached VLANs * @param userId * @param vlanType - either "DomR" (VLAN for a virtual public network) or "DirectAttached" (VLAN for IPs that will be directly attached to UserVMs) @@ -225,8 +240,9 @@ public interface ConfigurationManager extends Manager { * @throws InvalidParameterValueException * @return The new VlanVO object */ - VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException; - + VlanVO createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InvalidParameterValueException, InternalErrorException, InsufficientCapacityException; +// VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException; + /** * Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated IP addresses. * @param userId diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 7c0e9cf5cfd..b2f9fd850d5 100644 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -37,6 +37,7 @@ import com.cloud.api.commands.AddConfigCmd; import com.cloud.api.commands.CreateDiskOfferingCmd; import com.cloud.api.commands.CreatePodCmd; import com.cloud.api.commands.CreateServiceOfferingCmd; +import com.cloud.api.commands.CreateVlanIpRangeCmd; import com.cloud.api.commands.DeleteDiskOfferingCmd; import com.cloud.api.commands.DeletePodCmd; import com.cloud.api.commands.DeleteServiceOfferingCmd; @@ -47,6 +48,7 @@ import com.cloud.api.commands.UpdateDiskOfferingCmd; import com.cloud.api.commands.UpdatePodCmd; import com.cloud.api.commands.UpdateServiceOfferingCmd; import com.cloud.api.commands.UpdateZoneCmd; +import com.cloud.configuration.ResourceCount.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.AccountVlanMapVO; import com.cloud.dc.DataCenterVO; @@ -63,16 +65,22 @@ import com.cloud.dc.dao.PodVlanMapDao; import com.cloud.dc.dao.VlanDao; import com.cloud.domain.DomainVO; 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.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InternalErrorException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.NetworkManager; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.ServiceOffering.GuestIpType; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.User; import com.cloud.user.UserContext; @@ -85,6 +93,7 @@ import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.net.NetUtils; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.State; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.VMInstanceDao; @@ -111,6 +120,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager { @Inject UserDao _userDao; @Inject DataCenterDao _dcDao; @Inject HostPodDao _hostPodDao; + @Inject AccountManager _accountMgr; + @Inject NetworkManager _networkMgr; public boolean _premium; private int _maxVolumeSizeInGb; @@ -1190,14 +1201,50 @@ public class ConfigurationManagerImpl implements ConfigurationManager { return genChangeRangeSuccessString(problemIPs, add); } } - - public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException { - + + @Override +// public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException { + public VlanVO createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InvalidParameterValueException, InternalErrorException, InsufficientCapacityException { + Long userId = UserContext.current().getUserId(); + if (userId == null) { + userId = Long.valueOf(User.UID_SYSTEM); + } + + // If forVirtualNetworks isn't specified, default it to true + Boolean forVirtualNetwork = cmd.isForVirtualNetwork(); + if (forVirtualNetwork == null) { + forVirtualNetwork = Boolean.TRUE; + } + + // If the VLAN id is null, default it to untagged + String vlanId = cmd.getVlan(); + if (vlanId == null) { + vlanId = Vlan.UNTAGGED; + } + + // If an account name and domain ID are specified, look up the account + String accountName = cmd.getAccountName(); + Long domainId = cmd.getDomainId(); + Account account = null; + if ((accountName != null) && (domainId != null)) { + account = _accountDao.findActiveAccount(accountName, domainId); + if (account == null) { + throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid account."); + } + } + + VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached; + Long zoneId = cmd.getZoneId(); + Long podId = cmd.getPodId(); + String startIP = cmd.getStartIp(); + String endIP = cmd.getEndIp(); + String vlanGateway = cmd.getGateway(); + String vlanNetmask = cmd.getNetmask(); + //check for hypervisor type to be xenserver String hypervisorType = _configDao.getValue("hypervisor.type"); - if(hypervisorType.equalsIgnoreCase("xenserver")) - { + if(hypervisorType.equalsIgnoreCase("xenserver")) { //check for the vlan being added before going to db, to see if it is untagged if(vlanType.toString().equalsIgnoreCase("VirtualNetwork") && vlanId.equalsIgnoreCase("untagged")) { @@ -1208,33 +1255,38 @@ public class ConfigurationManagerImpl implements ConfigurationManager { } } - + DataCenterVO zone; if (zoneId == null || ((zone = _zoneDao.findById(zoneId)) == null)) { throw new InvalidParameterValueException("Please specify a valid zone."); - } - //remove this + } + + boolean associateIpRangeToAccount = false; if (vlanType.equals(VlanType.VirtualNetwork)) { - if (!(accountId == null && podId == null) && false) { - throw new InvalidParameterValueException("IP ranges for the virtual network must be zone-wide."); - } + if (account != null) { + // verify resource limits + long ipResourceLimit = _accountMgr.findCorrectResourceLimit((AccountVO)account, ResourceType.public_ip); + long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1; + if (s_logger.isDebugEnabled()) { + s_logger.debug(" IPResourceLimit " +ipResourceLimit + " accountIpRange " + accountIpRange); + } + if (ipResourceLimit != -1 && accountIpRange > ipResourceLimit){ // -1 means infinite + throw new InvalidParameterValueException(" Public IP Resource Limit is set to " + ipResourceLimit + " which is less than the IP range of " + accountIpRange + " provided"); + } + associateIpRangeToAccount = true; + } } else if (vlanType.equals(VlanType.DirectAttached)) { - if (!((accountId != null && podId == null) || (accountId == null && podId != null))) { + if (!((account != null && podId == null) || + (account == null && podId != null))) { throw new InvalidParameterValueException("Direct Attached IP ranges must either be pod-wide, or for one account."); } - - if (accountId != null) { + + if (account != null) { // VLANs for an account must be tagged if (vlanId.equals(Vlan.UNTAGGED)) { throw new InvalidParameterValueException("Direct Attached IP ranges for an account must be tagged."); } - - // Check that the account ID is valid - AccountVO account; - if ((account = _accountDao.findById(accountId)) == null) { - throw new InvalidParameterValueException("Please specify a valid account."); - } - + // Make sure there aren't any pod VLANs in this zone List podsInZone = _podDao.listByDataCenterId(zone.getId()); for (HostPodVO pod : podsInZone) { @@ -1244,7 +1296,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager { } // Make sure the specified account isn't already assigned to a VLAN in this zone - List accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId); + List accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(account.getId()); for (AccountVlanMapVO accountVlanMap : accountVlanMaps) { VlanVO vlan = _vlanDao.findById(accountVlanMap.getVlanDbId()); if (vlan.getDataCenterId() == zone.getId().longValue()) { @@ -1281,12 +1333,12 @@ public class ConfigurationManagerImpl implements ConfigurationManager { if (!NetUtils.isValidIp(vlanGateway)) { throw new InvalidParameterValueException("Please specify a valid gateway"); } - + // Make sure the netmask is valid if (!NetUtils.isValidIp(vlanNetmask)) { throw new InvalidParameterValueException("Please specify a valid netmask"); } - + String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask); // Check if the new VLAN's subnet conflicts with the guest network in the specified zone @@ -1295,23 +1347,23 @@ public class ConfigurationManagerImpl implements ConfigurationManager { String guestIpNetwork = NetUtils.getIpRangeStartIpFromCidr(cidrPair[0],Long.parseLong(cidrPair[1])); long guestCidrSize = Long.parseLong(cidrPair[1]); long vlanCidrSize = NetUtils.getCidrSize(vlanNetmask); - + long cidrSizeToUse = -1; if (vlanCidrSize < guestCidrSize) { cidrSizeToUse = vlanCidrSize; } else { cidrSizeToUse = guestCidrSize; } - + String guestSubnet = NetUtils.getCidrSubNet(guestIpNetwork, cidrSizeToUse); - + if (newVlanSubnet.equals(guestSubnet)) { throw new InvalidParameterValueException("The new IP range you have specified has the same subnet as the guest network in zone: " + zone.getName() + ". Please specify a different gateway/netmask."); } - + // Check if there are any errors with the IP range checkPublicIpRangeErrors(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP); - + // Throw an exception if any of the following is true: // 1. Another VLAN in the same zone has a different tag but the same subnet as the new VLAN // 2. Another VLAN in the same zone that has the same tag and subnet as the new VLAN has IPs that overlap with the IPs being added @@ -1356,8 +1408,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager { vlan = _vlanDao.persist(vlan); // Persist the IP range - if (accountId != null && vlanType.equals(VlanType.VirtualNetwork)){ - if(!savePublicIPRangeForAccount(startIP, endIP, zoneId, vlan.getId(), accountId, _accountDao.findById(accountId).getDomainId())){ + if (account != null && vlanType.equals(VlanType.VirtualNetwork)){ + if(!savePublicIPRangeForAccount(startIP, endIP, zoneId, vlan.getId(), account.getId(), account.getDomainId())) { deletePublicIPRange(vlan.getId()); _vlanDao.delete(vlan.getId()); throw new InternalErrorException("Failed to save IP range. Please contact Cloud Support."); //It can be Direct IP or Public IP. @@ -1368,9 +1420,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager { throw new InternalErrorException("Failed to save IP range. Please contact Cloud Support."); //It can be Direct IP or Public IP. } - if (accountId != null) { + if (account != null) { // This VLAN is account-specific, so create an AccountVlanMapVO entry - AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(accountId, vlan.getId()); + AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(account.getId(), vlan.getId()); _accountVlanMapDao.persist(accountVlanMapVO); } else if (podId != null) { // This VLAN is pod-wide, so create a PodVlanMapVO entry @@ -1383,14 +1435,95 @@ public class ConfigurationManagerImpl implements ConfigurationManager { eventMsg += ", end IP = " + endIP; } eventMsg += "."; - saveConfigurationEvent(userId, accountId, EventTypes.EVENT_VLAN_IP_RANGE_CREATE, eventMsg, "vlanType=" + vlanType, "dcId=" + zoneId, - "accountId=" + accountId, "podId=" + podId, + saveConfigurationEvent(userId, account.getId(), EventTypes.EVENT_VLAN_IP_RANGE_CREATE, eventMsg, "vlanType=" + vlanType, "dcId=" + zoneId, + "accountId=" + account.getId(), "podId=" + podId, "vlanId=" + vlanId, "vlanGateway=" + vlanGateway, "vlanNetmask=" + vlanNetmask, "startIP=" + startIP, "endIP=" + endIP); - + + // if this is an account VLAN, now associate the IP Addresses to the account + associateIpAddressListToAccount(userId, account.getId(), zoneId, vlan.getId()); + return vlan; } + + @Override @DB + public void associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId) throws InsufficientAddressCapacityException, + InvalidParameterValueException, InternalErrorException { + + Transaction txn = Transaction.currentTxn(); + AccountVO account = null; + + try { + //Acquire Lock + account = _accountDao.acquire(accountId); + if (account == null) { + s_logger.warn("Unable to lock account: " + accountId); + throw new InternalErrorException("Unable to acquire account lock"); + } + s_logger.debug("Associate IP address lock acquired"); + + //Get Router + DomainRouterVO router = _domrDao.findBy(accountId, zoneId); + if (router == null) { + s_logger.debug("No router found for account: " + account.getAccountName() + "."); + return; + } + + if (router.getState() == State.Running) { + //Get Vlans associated with the account + List vlansForAccount = new ArrayList(); + if (vlanId == null){ + vlansForAccount.addAll(_vlanDao.listVlansForAccountByType(zoneId, account.getId(), VlanType.VirtualNetwork)); + s_logger.debug("vlansForAccount "+ vlansForAccount); + }else{ + vlansForAccount.add(_vlanDao.findById(vlanId)); + } + + // Creating a list of all the ips that can be assigned to this account + txn.start(); + List ipAddrsList = new ArrayList(); + for (VlanVO vlan : vlansForAccount){ + ipAddrsList.addAll(_publicIpAddressDao.assignAcccountSpecificIps(accountId, account.getDomainId().longValue(), vlan.getId(), false)); + + long size = ipAddrsList.size(); + _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip, size); + s_logger.debug("Assigning new ip addresses " +ipAddrsList); + } + if(ipAddrsList.isEmpty()) + return; + + String params = "\nsourceNat=" + false + "\ndcId=" + zoneId; + + // Associate the IP's to DomR + boolean success = _networkMgr.associateIP(router,ipAddrsList, true); + String errorMsg = "Unable to assign public IP address pool"; + if (!success) { + s_logger.debug(errorMsg); + for(String ip : ipAddrsList){ + EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_NET_IP_ASSIGN, "Unable to assign public IP " +ip, params); + } + throw new InternalErrorException(errorMsg); + } + txn.commit(); + for(String ip : ipAddrsList){ + EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, EventTypes.EVENT_NET_IP_ASSIGN, "Successfully assigned account IP " +ip, params); + } + } + } catch (InternalErrorException iee) { + s_logger.error("Associate IP threw an InternalErrorException.", iee); + throw iee; + } catch (Throwable t) { + s_logger.error("Associate IP address threw an exception.", t); + throw new InternalErrorException("Associate IP address exception"); + } finally { + if (account != null) { + _accountDao.release(accountId); + s_logger.debug("Associate IP address lock released"); + } + } + + } public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId) throws InvalidParameterValueException { VlanVO vlan = _vlanDao.findById(vlanDbId); diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 0c1483b7d86..29cbd025e76 100644 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -53,7 +53,6 @@ import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenterIpAddressVO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; -import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; import com.cloud.domain.DomainVO; import com.cloud.event.EventVO; @@ -418,23 +417,6 @@ public interface ManagementServer { boolean disassociateIpAddress(DisassociateIPAddrCmd cmd) throws PermissionDeniedException; long disassociateIpAddressAsync(long userId, long accountId, String ipAddress); - /** - * Adds a VLAN to the database, along with an IP address range. Can add three types of VLANs: (1) zone-wide VLANs on the virtual network (2) pod-wide direct attached VLANs (3) account-specific direct attached VLANs - * @param userId - * @param vlanType - either "DomR" (VLAN for a virtual network) or "DirectAttached" (VLAN for IPs that will be directly attached to UserVMs) - * @param zoneId - * @param accountId - * @param podId - * @param add - * @param vlanId - * @param gateway - * @param startIP - * @param endIP - * @return The new VlanVO object - * @throws Exception - */ - VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws Exception; - /** * Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated IP addresses. * @param userId @@ -1620,23 +1602,6 @@ public interface ManagementServer { */ Snapshot findSnapshotById(long snapshotId); - /** - * Create a private template from a given snapshot - * @param snapshotId the id of the snapshot to use as the basis of the template - * @param name user provided string to use to name the template - * @param description the display text to show when listing the template as given by the user - * @param guestOSId the OS of the template - * @param requiresHvm whether the new template will require HVM - * @param bits number of bits (32-bit or 64-bit) - * @param passwordEnabled whether or not the template is password enabled - * @param iswhether or not the template is public - * @return valid template if success, null otherwise - * @throws InvalidParameterValueException, ResourceAllocationException - */ - VMTemplateVO createPrivateTemplate(VMTemplateVO template, Long userId, long snapshotId, String name, String description) throws InvalidParameterValueException; - long createPrivateTemplateAsync(Long userId, long vmId, String name, String description, long guestOSId, Boolean requiresHvm, Integer bits, Boolean passwordEnabled, boolean isPublic, boolean featured, Long snapshotId) throws InvalidParameterValueException, ResourceAllocationException, InternalErrorException; - - /** * Finds a diskOffering by the specified ID. * @param diskOfferingId diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 92659325a4a..f1f3c3b04fc 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -62,7 +62,6 @@ import com.cloud.api.commands.CopyTemplateCmd; import com.cloud.api.commands.CreateDomainCmd; import com.cloud.api.commands.CreatePortForwardingServiceCmd; import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd; -import com.cloud.api.commands.CreateTemplateCmd; import com.cloud.api.commands.CreateUserCmd; import com.cloud.api.commands.CreateVolumeCmd; import com.cloud.api.commands.DeleteIsoCmd; @@ -102,7 +101,6 @@ import com.cloud.async.executor.AssociateIpAddressParam; import com.cloud.async.executor.AttachISOParam; import com.cloud.async.executor.CopyTemplateParam; import com.cloud.async.executor.CreateOrUpdateRuleParam; -import com.cloud.async.executor.CreatePrivateTemplateParam; import com.cloud.async.executor.DeleteDomainParam; import com.cloud.async.executor.DeleteRuleParam; import com.cloud.async.executor.DeleteTemplateParam; @@ -655,7 +653,7 @@ public class ManagementServerImpl implements ManagementServer { EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_CREATE, "User, " + username + " for accountId = " + accountId + " and domainId = " + domainId + " was created."); - return dbUser; + return _userAccountDao.findById(dbUser.getId()); } catch (Exception e) { EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_CREATE, "Error creating user, " + username + " for accountId = " + accountId + " and domainId = " + domainId); @@ -1492,84 +1490,6 @@ public class ManagementServerImpl implements ManagementServer { return null; } - @DB - public void associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId) throws InsufficientAddressCapacityException, - InvalidParameterValueException, InternalErrorException { - - Transaction txn = Transaction.currentTxn(); - AccountVO account = null; - - try { - //Acquire Lock - account = _accountDao.acquire(accountId); - if (account == null) { - s_logger.warn("Unable to lock account: " + accountId); - throw new InternalErrorException("Unable to acquire account lock"); - } - s_logger.debug("Associate IP address lock acquired"); - - //Get Router - DomainRouterVO router = _routerDao.findBy(accountId, zoneId); - if (router == null) { - s_logger.debug("No router found for account: " + account.getAccountName() + "."); - return; - } - - if (router.getState() == State.Running) { - //Get Vlans associated with the account - List vlansForAccount = new ArrayList(); - if (vlanId == null){ - vlansForAccount.addAll(_vlanDao.listVlansForAccountByType(zoneId, account.getId(), VlanType.VirtualNetwork)); - s_logger.debug("vlansForAccount "+ vlansForAccount); - }else{ - vlansForAccount.add(_vlanDao.findById(vlanId)); - } - - // Creating a list of all the ips that can be assigned to this account - txn.start(); - List ipAddrsList = new ArrayList(); - for (VlanVO vlan : vlansForAccount){ - ipAddrsList.addAll(_publicIpAddressDao.assignAcccountSpecificIps(accountId, account.getDomainId().longValue(), vlan.getId(), false)); - - long size = ipAddrsList.size(); - _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip, size); - s_logger.debug("Assigning new ip addresses " +ipAddrsList); - } - if(ipAddrsList.isEmpty()) - return; - - String params = "\nsourceNat=" + false + "\ndcId=" + zoneId; - - // Associate the IP's to DomR - boolean success = _networkMgr.associateIP(router,ipAddrsList, true); - String errorMsg = "Unable to assign public IP address pool"; - if (!success) { - s_logger.debug(errorMsg); - for(String ip : ipAddrsList){ - EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_NET_IP_ASSIGN, "Unable to assign public IP " +ip, params); - } - throw new InternalErrorException(errorMsg); - } - txn.commit(); - for(String ip : ipAddrsList){ - EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, EventTypes.EVENT_NET_IP_ASSIGN, "Successfully assigned account IP " +ip, params); - } - } - } catch (InternalErrorException iee) { - s_logger.error("Associate IP threw an InternalErrorException.", iee); - throw iee; - } catch (Throwable t) { - s_logger.error("Associate IP address threw an exception.", t); - throw new InternalErrorException("Associate IP address exception"); - } finally { - if (account != null) { - _accountDao.release(accountId); - s_logger.debug("Associate IP address lock released"); - } - } - - } - @Override @DB public String associateIpAddress(long userId, long accountId, long domainId, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, @@ -1800,44 +1720,6 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job, true); } - @DB - @Override - public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws Exception{ - - if(accountId != null && vlanType == VlanType.VirtualNetwork){ - long ipResourceLimit = _accountMgr.findCorrectResourceLimit( _accountDao.findById(accountId), ResourceType.public_ip); - long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1 ; - s_logger.debug(" IPResourceLimit " +ipResourceLimit + " accountIpRange " + accountIpRange); - if (ipResourceLimit != -1 && accountIpRange > ipResourceLimit){ // -1 means infinite - throw new InvalidParameterValueException(" Public IP Resource Limit is set to " + ipResourceLimit + " which is less than the IP range of " + accountIpRange + " provided"); - } - String params = "\nsourceNat=" + false + "\ndcId=" + zoneId; - Transaction txn = Transaction.currentTxn(); - try{ - txn.start(); - VlanVO vlan = _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP); - associateIpAddressListToAccount(userId, accountId, zoneId, vlan.getId()); - txn.commit(); - return vlan; - }catch(Exception e){ - txn.rollback(); - long startIPLong = NetUtils.ip2Long(startIP); - long endIPLong = NetUtils.ip2Long(endIP); - while (startIPLong <= endIPLong) { - EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_NET_IP_ASSIGN, "Unable to assign public IP " +NetUtils.long2Ip(startIPLong), params); - startIPLong += 1; - } - throw new Exception(e.getMessage()); - } - } - return _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP); - } - -// @Override -// public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId) throws InvalidParameterValueException { -// return _configMgr.deleteVlanAndPublicIpRange(userId, vlanDbId); -// } - @Override public VolumeVO createVolume(long userId, long accountId, String name, long zoneId, long diskOfferingId, long startEventId, long size) throws InternalErrorException { EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VOLUME_CREATE, "Creating volume", startEventId); @@ -2515,7 +2397,7 @@ public class ManagementServerImpl implements ManagementServer { } try { - associateIpAddressListToAccount(userId, accountId, dc.getId(),null); + _configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null); } catch (InsufficientAddressCapacityException e) { s_logger.debug("Unable to assign public IP address pool: " +e.getMessage()); } @@ -6660,57 +6542,6 @@ public class ManagementServerImpl implements ManagementServer { } } - @Override - public VMTemplateVO createPrivateTemplate(VMTemplateVO template, Long userId, long snapshotId, String name, String description) throws InvalidParameterValueException { - - return _vmMgr.createPrivateTemplate(template, userId, snapshotId, name, description); - } - - @Override - public long createPrivateTemplateAsync(Long userId, long volumeId, String name, String description, long guestOSId, Boolean requiresHvm, Integer bits, Boolean passwordEnabled, boolean isPublic, boolean featured, Long snapshotId) - throws InvalidParameterValueException, ResourceAllocationException, InternalErrorException { - if (name.length() > 32) { - throw new InvalidParameterValueException("Template name should be less than 32 characters"); - } - - if (!name.matches("^[\\p{Alnum} ._-]+")) { - throw new InvalidParameterValueException("Only alphanumeric, space, dot, dashes and underscore characters allowed"); - } - - // The volume below could be destroyed or removed. - VolumeVO volume = _volumeDao.findById(volumeId); - - // If private template is created from Volume, check that the volume will not be active when the private template is created - if (snapshotId == null && !_storageMgr.volumeInactive(volume)) { - String msg = "Unable to create private template for volume: " + volume.getName() + "; volume is attached to a non-stopped VM."; - - if (s_logger.isInfoEnabled()) { - s_logger.info(msg); - } - - throw new InternalErrorException(msg); - } - - // Check that the guest OS is valid - GuestOSVO guestOS = _guestOSDao.findById(guestOSId); - if (guestOS == null) { - throw new InvalidParameterValueException("Please specify a valid guest OS."); - } - - long eventId = EventUtils.saveScheduledEvent(userId, volume.getAccountId(), EventTypes.EVENT_TEMPLATE_CREATE, "creating template" +name); - CreatePrivateTemplateParam param = new CreatePrivateTemplateParam(userId, volume.getAccountId(), volumeId, guestOSId, eventId, name, description, requiresHvm, bits, passwordEnabled, isPublic, featured, snapshotId); - Gson gson = GsonHelper.getBuilder().create(); - - AsyncJobVO job = new AsyncJobVO(); - job.setUserId(UserContext.current().getUserId()); - job.setAccountId(volume.getAccountId()); - job.setCmd("CreatePrivateTemplate"); - job.setCmdInfo(gson.toJson(param)); - job.setCmdOriginator(CreateTemplateCmd.getResultObjectName()); - - return _asyncMgr.submitAsyncJob(job, true); - } - @Override public DiskOfferingVO findDiskOfferingById(long diskOfferingId) { return _diskOfferingDao.findById(diskOfferingId);