bug 14239: limit number of Isolated account specific networks per account

status 14239: resolved fixed

Conflicts:

	api/src/com/cloud/api/commands/CreateNetworkCmd.java
	server/src/com/cloud/network/NetworkManagerImpl.java
	server/test/com/cloud/network/MockNetworkManagerImpl.java
This commit is contained in:
Alena Prokharchyk 2012-03-12 15:50:00 -07:00
parent af06038b9d
commit ad1192e264
17 changed files with 210 additions and 152 deletions

View File

@ -30,6 +30,7 @@ import com.cloud.api.response.NetworkResponse;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.network.Network;
import com.cloud.network.Network.GuestType;
import com.cloud.offering.NetworkOffering;
@ -208,8 +209,8 @@ public class CreateNetworkCmd extends BaseCmd {
}
@Override
public void execute() throws InsufficientCapacityException, ConcurrentOperationException{
// an exception thrown by createNetwork() will be caught by the dispatcher.
// an exception thrown by createNetwork() will be caught by the dispatcher.
public void execute() throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException{
Network result = _networkService.createNetwork(this);
if (result != null) {
NetworkResponse response = _responseGenerator.createNetworkResponse(result);

View File

@ -30,6 +30,7 @@ import com.cloud.api.response.VlanIpRangeResponse;
import com.cloud.dc.Vlan;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@ -159,7 +160,7 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
}
@Override
public void execute() throws ResourceUnavailableException{
public void execute() throws ResourceUnavailableException, ResourceAllocationException{
try {
Vlan result = _configService.createVlanAndPublicIpRange(this);
if (result != null) {

View File

@ -97,6 +97,25 @@ public class AccountResponse extends BaseResponse {
@SerializedName("vmrunning") @Param(description="the total number of virtual machines running for this account")
private Integer vmRunning;
@SerializedName("projectlimit") @Param(description="the total number of projects the account can own")
private String projectLimit;
@SerializedName("projecttotal") @Param(description="the total number of projects being administrated by this account")
private Long projectTotal;
@SerializedName("projectavailable") @Param(description="the total number of projects available for administration by this account")
private String projectAvailable;
@SerializedName("networklimit") @Param(description="the total number of networks the account can own")
private String networkLimit;
@SerializedName("networktotal") @Param(description="the total number of networks owned by account")
private Long networkTotal;
@SerializedName("networkavailable") @Param(description="the total number of networks available to be created for this account")
private String networkAvailable;
@SerializedName(ApiConstants.STATE) @Param(description="the state of the account")
private String state;
@ -113,218 +132,110 @@ public class AccountResponse extends BaseResponse {
@SerializedName(ApiConstants.ACCOUNT_DETAILS) @Param(description="details for the account")
private Map<String, String> details;
public Long getId() {
return id.getValue();
}
public void setId(Long id) {
this.id.setValue(id);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Short getAccountType() {
return accountType;
}
public void setAccountType(Short accountType) {
this.accountType = accountType;
}
public Long getDomainId() {
return domainId.getValue();
}
public void setDomainId(Long domainId) {
this.domainId.setValue(domainId);
}
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public Long getBytesReceived() {
return bytesReceived;
}
public void setBytesReceived(Long bytesReceived) {
this.bytesReceived = bytesReceived;
}
public Long getBytesSent() {
return bytesSent;
}
public void setBytesSent(Long bytesSent) {
this.bytesSent = bytesSent;
}
public String getVmLimit() {
return vmLimit;
}
public void setVmLimit(String vmLimit) {
this.vmLimit = vmLimit;
}
public Long getVmTotal() {
return vmTotal;
}
public void setVmTotal(Long vmTotal) {
this.vmTotal = vmTotal;
}
public String getVmAvailable() {
return vmAvailable;
}
public void setVmAvailable(String vmAvailable) {
this.vmAvailable = vmAvailable;
}
public String getIpLimit() {
return ipLimit;
}
public void setIpLimit(String ipLimit) {
this.ipLimit = ipLimit;
}
public Long getIpTotal() {
return ipTotal;
}
public void setIpTotal(Long ipTotal) {
this.ipTotal = ipTotal;
}
public String getIpAvailable() {
return ipAvailable;
}
public void setIpAvailable(String ipAvailable) {
this.ipAvailable = ipAvailable;
}
public String getVolumeLimit() {
return volumeLimit;
}
public void setVolumeLimit(String volumeLimit) {
this.volumeLimit = volumeLimit;
}
public Long getVolumeTotal() {
return volumeTotal;
}
public void setVolumeTotal(Long volumeTotal) {
this.volumeTotal = volumeTotal;
}
public String getVolumeAvailable() {
return volumeAvailable;
}
public void setVolumeAvailable(String volumeAvailable) {
this.volumeAvailable = volumeAvailable;
}
public String getSnapshotLimit() {
return snapshotLimit;
}
public void setSnapshotLimit(String snapshotLimit) {
this.snapshotLimit = snapshotLimit;
}
public Long getSnapshotTotal() {
return snapshotTotal;
}
public void setSnapshotTotal(Long snapshotTotal) {
this.snapshotTotal = snapshotTotal;
}
public String getSnapshotAvailable() {
return snapshotAvailable;
}
public void setSnapshotAvailable(String snapshotAvailable) {
this.snapshotAvailable = snapshotAvailable;
}
public String getTemplateLimit() {
return templateLimit;
}
public void setTemplateLimit(String templateLimit) {
this.templateLimit = templateLimit;
}
public Long getTemplateTotal() {
return templateTotal;
}
public void setTemplateTotal(Long templateTotal) {
this.templateTotal = templateTotal;
}
public String getTemplateAvailable() {
return templateAvailable;
}
public void setTemplateAvailable(String templateAvailable) {
this.templateAvailable = templateAvailable;
}
public Integer getVmStopped() {
return vmStopped;
}
public void setVmStopped(Integer vmStopped) {
this.vmStopped = vmStopped;
}
public Integer getVmRunning() {
return vmRunning;
}
public void setVmRunning(Integer vmRunning) {
this.vmRunning = vmRunning;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Boolean getCleanupRequired() {
return cleanupRequired;
}
public void setCleanupRequired(Boolean cleanupRequired) {
this.cleanupRequired = cleanupRequired;
}
public List<UserResponse> getUsers() {
return this.users;
}
public void setUsers(List<UserResponse> users) {
this.users = users;
}
@ -336,8 +247,28 @@ public class AccountResponse extends BaseResponse {
public void setDetails(Map<String, String> details) {
this.details = details;
}
public Map getDetails() {
return details;
public void setProjectLimit(String projectLimit) {
this.projectLimit = projectLimit;
}
public void setProjectTotal(Long projectTotal) {
this.projectTotal = projectTotal;
}
public void setProjectAvailable(String projectAvailable) {
this.projectAvailable = projectAvailable;
}
public void setNetworkLimit(String networkLimit) {
this.networkLimit = networkLimit;
}
public void setNetworkTotal(Long networkTotal) {
this.networkTotal = networkTotal;
}
public void setNetworkAvailable(String networkAvailable) {
this.networkAvailable = networkAvailable;
}
}

View File

@ -47,6 +47,7 @@ import com.cloud.dc.Pod;
import com.cloud.dc.Vlan;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Networks.TrafficType;
import com.cloud.offering.DiskOffering;
@ -215,10 +216,11 @@ public interface ConfigurationService {
* @param gateway
* @param startIP
* @param endIP
* @throws ResourceAllocationException TODO
* @throws
* @return The new Vlan object
*/
Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException;
Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException;
boolean deleteVlanIpRange(DeleteVlanIpRangeCmd cmd);

View File

@ -27,7 +27,8 @@ public interface Resource {
volume("volume", 2, ResourceOwnerType.Account, ResourceOwnerType.Domain),
snapshot("snapshot", 3, ResourceOwnerType.Account, ResourceOwnerType.Domain),
template("template", 4, ResourceOwnerType.Account, ResourceOwnerType.Domain),
project("project", 5, ResourceOwnerType.Account, ResourceOwnerType.Domain);
project("project", 5, ResourceOwnerType.Account, ResourceOwnerType.Domain),
network("network", 6, ResourceOwnerType.Account, ResourceOwnerType.Domain);
private String name;
private ResourceOwnerType[] supportedOwners;

View File

@ -57,7 +57,7 @@ public interface NetworkService {
boolean disassociateIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;
Network createNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException;
Network createNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException;
List<? extends Network> searchForNetworks(ListNetworksCmd cmd);

View File

@ -279,7 +279,7 @@ public class ApiResponseHelper implements ResponseGenerator {
Long ips = ipLimit - ipTotal;
// check how many free ips are left, and if it's less than max allowed number of ips from account - use this
// value
// value
Long ipsLeft = ApiDBUtils.countFreePublicIps();
boolean unlimited = true;
if (ips.longValue() > ipsLeft.longValue()) {
@ -341,7 +341,25 @@ public class ApiResponseHelper implements ResponseGenerator {
accountResponse.setVmStopped(vmStopped);
accountResponse.setVmRunning(vmRunning);
accountResponse.setObjectName("account");
//get resource limits for projects
Long projectLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.project, account.getId());
String projectLimitDisplay = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit);
Long projectTotal = ApiDBUtils.getResourceCount(ResourceType.project, account.getId());
String projectAvail = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal);
accountResponse.setProjectLimit(projectLimitDisplay);
accountResponse.setProjectTotal(projectTotal);
accountResponse.setProjectAvailable(projectAvail);
//get resource limits for networks
Long networkLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.network, account.getId());
String networkLimitDisplay = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit);
Long networkTotal = ApiDBUtils.getResourceCount(ResourceType.network, account.getId());
String networkAvail = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit - networkTotal);
accountResponse.setNetworkLimit(networkLimitDisplay);
accountResponse.setNetworkTotal(networkTotal);
accountResponse.setNetworkAvailable(networkAvail);
// adding all the users for an account as part of the response obj
List<UserVO> usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
List<UserResponse> userResponseList = new ArrayList<UserResponse>();

View File

@ -78,7 +78,7 @@ public enum Config {
CopyVolumeWait("Storage", StorageManager.class, Integer.class, "copy.volume.wait", "10800", "In second, timeout for copy volume command", null),
CreatePrivateTemplateFromVolumeWait("Storage", UserVmManager.class, Integer.class, "create.private.template.from.volume.wait", "10800", "In second, timeout for CreatePrivateTemplateFromVolumeCommand", null),
CreatePrivateTemplateFromSnapshotWait("Storage", UserVmManager.class, Integer.class, "create.private.template.from.snapshot.wait", "10800", "In second, timeout for CreatePrivateTemplateFromSnapshotCommand", null),
BackupSnapshotWait(
BackupSnapshotWait(
"Storage", StorageManager.class, Integer.class, "backup.snapshot.wait", "21600", "In second, timeout for BackupSnapshotCommand", null),
// Network
@ -300,6 +300,8 @@ public enum Config {
DefaultMaxAccountTemplates("Account Defaults", ManagementServer.class, Long.class, "max.account.templates", "20", "The default maximum number of templates that can be deployed for an account", null),
DefaultMaxAccountSnapshots("Account Defaults", ManagementServer.class, Long.class, "max.account.snapshots", "20", "The default maximum number of snapshots that can be created for an account", null),
DefaultMaxAccountVolumes("Account Defaults", ManagementServer.class, Long.class, "max.account.volumes", "20", "The default maximum number of volumes that can be created for an account", null),
DefaultMaxAccountNetworks("Account Defaults", ManagementServer.class, Long.class, "max.account.networks", "20", "The default maximum number of networks that can be created for an account", null),
ResourceCountCheckInterval("Advanced", ManagementServer.class, Long.class, "resourcecount.check.interval", "0", "Time (in seconds) to wait before retrying resource count check task. Default is 0 which is to never run the task", "Seconds"),
DirectAgentLoadSize("Advanced", ManagementServer.class, Integer.class, "direct.agent.load.size", "16", "The number of direct agents to load each time", null),
@ -320,6 +322,7 @@ public enum Config {
DefaultMaxProjectTemplates("Project Defaults", ManagementServer.class, Long.class, "max.project.templates", "20", "The default maximum number of templates that can be deployed for a project", null),
DefaultMaxProjectSnapshots("Project Defaults", ManagementServer.class, Long.class, "max.project.snapshots", "20", "The default maximum number of snapshots that can be created for a project", null),
DefaultMaxProjectVolumes("Project Defaults", ManagementServer.class, Long.class, "max.project.volumes", "20", "The default maximum number of volumes that can be created for a project", null),
DefaultMaxProjectNetworks("Project Defaults", ManagementServer.class, Long.class, "max.project.networks", "20", "The default maximum number of networks that can be created for a project", null),
ProjectInviteRequired("Project Defaults", ManagementServer.class, Boolean.class, "project.invite.required", "false", "If invitation confirmation is required when add account to project. Default value is false", null),
ProjectInvitationExpirationTime("Project Defaults", ManagementServer.class, Long.class, "project.invite.timeout", "86400", "Invitation expiration time (in seconds). Default is 1 day - 86400 seconds", null),

View File

@ -98,6 +98,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
@ -2063,7 +2064,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_CREATE, eventDescription = "creating vlan ip range", async = false)
public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException {
Long zoneId = cmd.getZoneId();
Long podId = cmd.getPodId();
String startIP = cmd.getStartIp();
@ -2279,13 +2280,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
if (associateIpRangeToAccount) {
_networkMgr.associateIpAddressListToAccount(userId, account.getId(), zoneId, vlan.getId(), network);
if (network == null) {
List<? extends Network> networks = _networkMgr.getIsolatedNetworksOwnedByAccountInZone(zoneId, account);
network = networks.get(0);
}
if (network == null) {
throw new CloudRuntimeException("Failed to associate vlan to the account id=" + account.getId() + ", default network failed to create");
}
}
txn.commit();

View File

@ -35,6 +35,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network.Capability;
@ -168,9 +169,10 @@ public interface NetworkManager extends NetworkService {
boolean destroyNetwork(long networkId, ReservationContext context);
Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, boolean isSecurityGroupEnabled, Long domainId,
PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess) throws ConcurrentOperationException, InsufficientCapacityException;
PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
/**
* @throws ResourceAllocationException TODO
* @throws InsufficientCapacityException
* Associates an ip address list to an account. The list of ip addresses are all addresses associated
* with the
@ -183,7 +185,7 @@ public interface NetworkManager extends NetworkService {
* @throws
*/
boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network networkToAssociateWith) throws InsufficientCapacityException, ConcurrentOperationException,
ResourceUnavailableException;
ResourceUnavailableException, ResourceAllocationException;
Nic getNicInNetwork(long vmId, long networkId);

View File

@ -2232,7 +2232,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_CREATE, eventDescription = "creating network")
public Network createNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException {
public Network createNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException {
Long networkOfferingId = cmd.getNetworkOfferingId();
String gateway = cmd.getGateway();
String startIP = cmd.getStartIp();
@ -2469,17 +2469,23 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Override
@DB
public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, boolean isSecurityGroupEnabled,
Long domainId, PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess) throws ConcurrentOperationException, InsufficientCapacityException {
Long domainId, PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId);
NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
// this method supports only guest network creation
if (networkOffering.getTrafficType() != TrafficType.Guest) {
if (ntwkOff.getTrafficType() != TrafficType.Guest) {
s_logger.warn("Only guest networks can be created using this method");
return null;
}
boolean updateResourceCount = (!ntwkOff.getSpecifyVlan() && aclType == ACLType.Account);
//check resource limits
if (updateResourceCount) {
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.network);
}
// Validate network offering
if (networkOffering.getState() != NetworkOffering.State.Enabled) {
if (ntwkOff.getState() != NetworkOffering.State.Enabled) {
// see NetworkOfferingVO
InvalidParameterValueException ex = new InvalidParameterValueException("Can't use specified network offering id as its stat is not " + NetworkOffering.State.Enabled);
ex.addProxyObject("network_offerings", networkOfferingId, "networkOfferingId");
@ -2497,6 +2503,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
// Validate zone
DataCenterVO zone = _dcDao.findById(zoneId);
if (zone.getNetworkType() == NetworkType.Basic) {
// In Basic zone the network should have aclType=Domain, domainId=1, subdomainAccess=true
if (aclType == null || aclType != ACLType.Domain) {
throw new InvalidParameterValueException("Only AclType=Domain can be specified for network creation in Basic zone");
}
// Only one guest network is supported in Basic zone
List<NetworkVO> guestNetworks = _networksDao.listByZoneAndTrafficType(zone.getId(), TrafficType.Guest);
if (!guestNetworks.isEmpty()) {
@ -2504,16 +2515,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
// if zone is basic, only Shared network offerings w/o source nat service are allowed
if (!(networkOffering.getGuestType() == GuestType.Shared && !areServicesSupportedByNetworkOffering(networkOffering.getId(), Service.SourceNat))) {
if (!(ntwkOff.getGuestType() == GuestType.Shared && !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) {
throw new InvalidParameterValueException("For zone of type " + NetworkType.Basic + " only offerings of guestType " + GuestType.Shared + " with disabled " + Service.SourceNat.getName()
+ " service are allowed");
}
// In Basic zone the network should have aclType=Domain, domainId=1, subdomainAccess=true
if (aclType == null || aclType != ACLType.Domain) {
throw new InvalidParameterValueException("Only AclType=Domain can be specified for network creation in Basic zone");
}
if (domainId == null || domainId != Domain.ROOT_DOMAIN) {
throw new InvalidParameterValueException("Guest network in Basic zone should be dedicated to ROOT domain");
}
@ -2535,8 +2541,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
} else if (zone.getNetworkType() == NetworkType.Advanced) {
if (zone.isSecurityGroupEnabled()) {
// Only Account specific Isolated network with sourceNat service disabled are allowed in security group
// enabled zone
boolean allowCreation = (networkOffering.getGuestType() == GuestType.Isolated && !areServicesSupportedByNetworkOffering(networkOffering.getId(), Service.SourceNat));
// enabled zone
boolean allowCreation = (ntwkOff.getGuestType() == GuestType.Isolated && !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat));
if (!allowCreation) {
throw new InvalidParameterValueException("Only Account specific Isolated network with sourceNat service disabled are allowed in security group enabled zone");
}
@ -2545,7 +2551,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
// VlanId can be specified only when network offering supports it
boolean vlanSpecified = (vlanId != null);
if (vlanSpecified != networkOffering.getSpecifyVlan()) {
if (vlanSpecified != ntwkOff.getSpecifyVlan()) {
if (vlanSpecified) {
throw new InvalidParameterValueException("Can't specify vlan; corresponding offering says specifyVlan=false");
} else {
@ -2598,10 +2604,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
// In Advance zone Cidr for Shared networks and Isolated networks w/o source nat service can't be NULL - 2.2.x
// limitation, remove after we introduce support for multiple ip ranges
// limitation, remove after we introduce support for multiple ip ranges
// with different Cidrs for the same Shared network
boolean cidrRequired = zone.getNetworkType() == NetworkType.Advanced && networkOffering.getTrafficType() == TrafficType.Guest
&& (networkOffering.getGuestType() == GuestType.Shared || (networkOffering.getGuestType() == GuestType.Isolated && !areServicesSupportedByNetworkOffering(networkOffering.getId(), Service.SourceNat)));
boolean cidrRequired = zone.getNetworkType() == NetworkType.Advanced && ntwkOff.getTrafficType() == TrafficType.Guest
&& (ntwkOff.getGuestType() == GuestType.Shared || (ntwkOff.getGuestType() == GuestType.Isolated && !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)));
if (cidr == null && cidrRequired) {
throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask are required when create network of type " + Network.GuestType.Shared + " and network of type " + GuestType.Isolated + " with service "
+ Service.SourceNat.getName() + " disabled");
@ -2613,7 +2619,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
// Check if cidr is RFC1918 compliant if the network is Guest Isolated
if (cidr != null && networkOffering.getGuestType() == Network.GuestType.Isolated && networkOffering.getTrafficType() == TrafficType.Guest) {
if (cidr != null && ntwkOff.getGuestType() == Network.GuestType.Isolated && ntwkOff.getTrafficType() == TrafficType.Guest) {
if (!NetUtils.validateGuestCidr(cidr)) {
throw new InvalidParameterValueException("Virtual Guest Cidr " + cidr + " is not RFC1918 compliant");
}
@ -2644,7 +2650,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
}
List<NetworkVO> networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, true, domainId, aclType, subdomainAccess);
List<NetworkVO> networks = setupNetwork(owner, ntwkOff, userNetwork, plan, name, displayText, true, domainId, aclType, subdomainAccess);
Network network = null;
if (networks == null || networks.isEmpty()) {
@ -2663,6 +2669,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
network = networks.get(0);
}
}
if (updateResourceCount) {
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.network);
}
txn.commit();
UserContext.current().setEventDetails("Network Id: " + network.getId());
@ -3719,7 +3729,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Override
@DB
public boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network network) throws InsufficientCapacityException, ConcurrentOperationException,
ResourceUnavailableException {
ResourceUnavailableException, ResourceAllocationException {
Account owner = _accountMgr.getActiveAccountById(accountId);
boolean createNetwork = false;

View File

@ -95,5 +95,7 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long> {
void setCheckForGc(long networkId);
int getNetworkCountByNetworkOffId(long networkOfferingId);
long countNetworksUserCanCreate(long ownerId);
}

View File

@ -24,6 +24,7 @@ import java.util.Random;
import javax.ejb.Local;
import javax.persistence.TableGenerator;
import com.cloud.acl.ControlledEntity.ACLType;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
@ -35,6 +36,8 @@ import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDaoImpl;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
@ -61,6 +64,7 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
final GenericSearchBuilder<NetworkVO, Long> CountByOfferingId;
final SearchBuilder<NetworkVO> PhysicalNetworkSearch;
final SearchBuilder<NetworkVO> SecurityGroupSearch;
final GenericSearchBuilder<NetworkVO, Long> NetworksRegularUserCanCreateSearch;
private final GenericSearchBuilder<NetworkVO, Integer> NetworksCount;
@ -68,6 +72,7 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
NetworkDomainDaoImpl _domainsDao = ComponentLocator.inject(NetworkDomainDaoImpl.class);
NetworkOpDaoImpl _opDao = ComponentLocator.inject(NetworkOpDaoImpl.class);
NetworkServiceMapDaoImpl _ntwkSvcMap = ComponentLocator.inject(NetworkServiceMapDaoImpl.class);
NetworkOfferingDaoImpl _ntwkOffDao = ComponentLocator.inject(NetworkOfferingDaoImpl.class);
final TableGenerator _tgMacAddress;
@ -145,6 +150,18 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
NetworksCount.select(null, Func.COUNT, NetworksCount.entity().getId());
NetworksCount.and("networkOfferingId", NetworksCount.entity().getNetworkOfferingId(), SearchCriteria.Op.EQ);
NetworksCount.done();
NetworksRegularUserCanCreateSearch = createSearchBuilder(Long.class);
NetworksRegularUserCanCreateSearch.and("aclType", NetworksRegularUserCanCreateSearch.entity().getAclType(), Op.EQ);
NetworksRegularUserCanCreateSearch.select(null, Func.COUNT, NetworksRegularUserCanCreateSearch.entity().getId());
SearchBuilder<NetworkAccountVO> join4 = _accountsDao.createSearchBuilder();
join4.and("account", join4.entity().getAccountId(), Op.EQ);
join4.and("isOwner", join4.entity().isOwner(), Op.EQ);
NetworksRegularUserCanCreateSearch.join("accounts", join4, NetworksRegularUserCanCreateSearch.entity().getId(), join4.entity().getNetworkId(), JoinBuilder.JoinType.INNER);
SearchBuilder<NetworkOfferingVO> join5 = _ntwkOffDao.createSearchBuilder();
join5.and("specifyVlan", join5.entity().getSpecifyVlan(), Op.EQ);
NetworksRegularUserCanCreateSearch.join("ntwkOff", join5, NetworksRegularUserCanCreateSearch.entity().getNetworkOfferingId(), join5.entity().getId(), JoinBuilder.JoinType.INNER);
NetworksRegularUserCanCreateSearch.done();
_tgMacAddress = _tgs.get("macAddress");
@ -416,5 +433,14 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
List<Integer> count = customSearch(sc, null);
return count.get(0);
}
@Override
public long countNetworksUserCanCreate(long ownerId) {
SearchCriteria<Long> sc = NetworksRegularUserCanCreateSearch.create();
sc.setParameters("aclType", ACLType.Account);
sc.setJoinParameters("accounts", "account", ownerId);
sc.setJoinParameters("ntwkOff", "specifyVlan", false);
return customSearch(sc, null).get(0);
}
}

View File

@ -52,6 +52,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccount.Role;
import com.cloud.projects.dao.ProjectAccountDao;
@ -117,6 +118,8 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager {
private ProjectDao _projectDao;
@Inject
private ProjectAccountDao _projectAccountDao;
@Inject
private NetworkDao _networkDao;
protected SearchBuilder<ResourceCountVO> ResourceCountSearch;
ScheduledExecutorService _rcExecutor;
@ -162,12 +165,14 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager {
projectResourceLimitMap.put(Resource.ResourceType.template, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectTemplates.key())));
projectResourceLimitMap.put(Resource.ResourceType.user_vm, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectUserVms.key())));
projectResourceLimitMap.put(Resource.ResourceType.volume, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectVolumes.key())));
projectResourceLimitMap.put(Resource.ResourceType.network, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectNetworks.key())));
accountResourceLimitMap.put(Resource.ResourceType.public_ip, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountPublicIPs.key())));
accountResourceLimitMap.put(Resource.ResourceType.snapshot, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountSnapshots.key())));
accountResourceLimitMap.put(Resource.ResourceType.template, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountTemplates.key())));
accountResourceLimitMap.put(Resource.ResourceType.user_vm, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountUserVms.key())));
accountResourceLimitMap.put(Resource.ResourceType.volume, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountVolumes.key())));
accountResourceLimitMap.put(Resource.ResourceType.network, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountNetworks.key())));
return true;
}
@ -724,6 +729,8 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager {
newCount = _vmTemplateDao.countTemplatesForAccount(accountId);
} else if (type == Resource.ResourceType.project) {
newCount = _projectAccountDao.countByAccountIdAndRole(accountId, Role.Admin);
} else if (type == Resource.ResourceType.network) {
newCount = _networkDao.countNetworksUserCanCreate(accountId);
} else {
throw new InvalidParameterValueException("Unsupported resource type " + type);
}

View File

@ -1477,7 +1477,7 @@ public class Upgrade218to22 implements DbUpgrade {
upgradeDomainResourceCounts(conn, ResourceType.public_ip);
}
private void upgradeDomainResourceCounts(Connection conn, ResourceType resourceType) {
public static void upgradeDomainResourceCounts(Connection conn, ResourceType resourceType) {
try {
PreparedStatement account_count_pstmt = conn.prepareStatement("SELECT account_id, count from resource_count where type='" + resourceType + "'");

View File

@ -31,6 +31,7 @@ import java.util.UUID;
import org.apache.log4j.Logger;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
@ -88,6 +89,10 @@ public class Upgrade2214to30 implements DbUpgrade {
migrateUserConcentratedPlannerChoice(conn);
// update domain router table for element it;
updateRouters(conn);
// update network account resource count
udpateAccountNetworkResourceCount(conn);
// update network domain resource count
udpateDomainNetworkResourceCount(conn);
}
@Override
@ -1089,5 +1094,57 @@ public class Upgrade2214to30 implements DbUpgrade {
} catch (SQLException e) {
}
}
}
}
protected void udpateAccountNetworkResourceCount(Connection conn) {
PreparedStatement pstmt = null;
ResultSet rs = null;
ResultSet rs1 = null;
long accountId = 0;
try {
pstmt = conn.prepareStatement("select id from `cloud`.`account` where removed is null");
rs = pstmt.executeQuery();
while (rs.next()) {
accountId = rs.getLong(1);
//get networks count for the account
pstmt = conn.prepareStatement("select count(*) from `cloud`.`networks` n, `cloud`.`account_network_ref` a, `cloud`.`network_offerings` no" +
" WHERE n.acl_type='Account' and n.id=a.network_id and a.account_id=? and a.is_owner=1 and no.specify_vlan=false and no.traffic_type='Guest'");
pstmt.setLong(1, accountId);
rs1 = pstmt.executeQuery();
long count = 0;
while (rs1.next()) {
count = rs1.getLong(1);
}
pstmt = conn.prepareStatement("insert into `cloud`.`resource_count` (account_id, domain_id, type, count) VALUES (?, null, 'network', ?)");
pstmt.setLong(1, accountId);
pstmt.setLong(2, count);
pstmt.executeUpdate();
s_logger.debug("Updated network resource count for account id=" + accountId + " to be " + count);
}
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to update network resource count for account id=" + accountId, e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (rs1 != null) {
rs1.close();
}
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
}
}
}
protected void udpateDomainNetworkResourceCount(Connection conn) {
Upgrade218to22.upgradeDomainResourceCounts(conn, ResourceType.network);
}
}

View File

@ -139,6 +139,7 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT'
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'max.project.templates', '20', 'The default maximum number of templates that can be deployed for a project');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'max.project.snapshots', '20', 'The default maximum number of snapshots that can be created for a project');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'max.project.volumes', '20', 'The default maximum number of volumes that can be created for a project');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'max.project.networks', '20', 'The default maximum number of networks that can be created for a project');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'project.invite.required', 'false', 'If invitation confirmation is required when add account to project. Default value is false');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'project.invite.timeout', '86400', 'Invitation expiration time (in seconds). Default is 1 day - 86400 seconds');
@ -716,3 +717,5 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag
UPDATE `cloud`.`network_offerings` SET display_text='Offering for Shared Security group enabled networks' where display_text='System-Guest-Network';
UPDATE `cloud`.`configuration` SET category = 'Secure' where name in ('alert.smtp.password', 'network.loadbalancer.haproxy.stats.auth', 'security.singlesignon.key', 'project.smtp.password');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.networks', '20', 'The default maximum number of networks that can be created for an account');