You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bf...@apache.org on 2013/04/16 20:03:35 UTC
[02/50] [abbrv] git commit: updated
refs/heads/ui-new-project-switcher to a748988
Dedicate Public IP address range to an account
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8f865c5a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8f865c5a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8f865c5a
Branch: refs/heads/ui-new-project-switcher
Commit: 8f865c5a901d1fb066709e1809fd5538af3eea11
Parents: 95cbb79
Author: Likitha Shetty <li...@citrix.com>
Authored: Mon Apr 8 22:44:45 2013 +0530
Committer: Likitha Shetty <li...@citrix.com>
Committed: Fri Apr 12 23:27:35 2013 +0530
----------------------------------------------------------------------
.../cloud/configuration/ConfigurationService.java | 6 +
api/src/com/cloud/event/EventTypes.java | 4 +
.../admin/vlan/DedicatePublicIpRangeCmd.java | 108 ++++
.../admin/vlan/ReleasePublicIpRangeCmd.java | 77 +++
client/tomcatconf/commands.properties.in | 2 +
.../cloud/configuration/ConfigurationManager.java | 5 +-
.../configuration/ConfigurationManagerImpl.java | 173 ++++++-
.../src/com/cloud/network/NetworkManagerImpl.java | 45 ++-
.../src/com/cloud/network/NetworkServiceImpl.java | 9 -
.../src/com/cloud/server/ManagementServerImpl.java | 3 +
server/src/com/cloud/user/AccountManagerImpl.java | 6 +-
.../configuration/ConfigurationManagerTest.java | 413 +++++++++++++++
.../cloud/vpc/MockConfigurationManagerImpl.java | 23 +-
test/integration/component/test_public_ip_range.py | 173 ++++++
tools/marvin/marvin/integration/lib/base.py | 19 +-
15 files changed, 1017 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/api/src/com/cloud/configuration/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/configuration/ConfigurationService.java b/api/src/com/cloud/configuration/ConfigurationService.java
index e63fcec..6937d0b 100644
--- a/api/src/com/cloud/configuration/ConfigurationService.java
+++ b/api/src/com/cloud/configuration/ConfigurationService.java
@@ -35,7 +35,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
@@ -234,6 +236,10 @@ public interface ConfigurationService {
boolean deleteVlanIpRange(DeleteVlanIpRangeCmd cmd);
+ Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd) throws ResourceAllocationException;
+
+ boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd);
+
NetworkOffering createNetworkOffering(CreateNetworkOfferingCmd cmd);
NetworkOffering updateNetworkOffering(UpdateNetworkOfferingCmd cmd);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 6a26212..0ee7f40 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -226,6 +226,8 @@ public class EventTypes {
// VLANs/IP ranges
public static final String EVENT_VLAN_IP_RANGE_CREATE = "VLAN.IP.RANGE.CREATE";
public static final String EVENT_VLAN_IP_RANGE_DELETE = "VLAN.IP.RANGE.DELETE";
+ public static final String EVENT_VLAN_IP_RANGE_DEDICATE = "VLAN.IP.RANGE.DEDICATE";
+ public static final String EVENT_VLAN_IP_RANGE_RELEASE = "VLAN.IP.RANGE.RELEASE";
public static final String EVENT_STORAGE_IP_RANGE_CREATE = "STORAGE.IP.RANGE.CREATE";
public static final String EVENT_STORAGE_IP_RANGE_DELETE = "STORAGE.IP.RANGE.DELETE";
@@ -545,6 +547,8 @@ public class EventTypes {
// VLANs/IP ranges
entityEventDetails.put(EVENT_VLAN_IP_RANGE_CREATE, Vlan.class.getName());
entityEventDetails.put(EVENT_VLAN_IP_RANGE_DELETE,Vlan.class.getName());
+ entityEventDetails.put(EVENT_VLAN_IP_RANGE_DEDICATE, Vlan.class.getName());
+ entityEventDetails.put(EVENT_VLAN_IP_RANGE_RELEASE,Vlan.class.getName());
entityEventDetails.put(EVENT_STORAGE_IP_RANGE_CREATE, StorageNetworkIpRange.class.getName());
entityEventDetails.put(EVENT_STORAGE_IP_RANGE_DELETE, StorageNetworkIpRange.class.getName());
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java
new file mode 100755
index 0000000..e7b1105
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java
@@ -0,0 +1,108 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.vlan;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
+import org.apache.cloudstack.api.response.VlanIpRangeResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.Vlan;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicatePublicIpRange", description="Dedicates a Public IP range to an account", responseObject=VlanIpRangeResponse.class)
+public class DedicatePublicIpRangeCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicatePublicIpRangeCmd.class.getName());
+
+ private static final String s_name = "dedicatepubliciprangeresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VlanIpRangeResponse.class,
+ required=true, description="the id of the VLAN IP range")
+ private Long id;
+
+ @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, required=true,
+ description="account who will own the VLAN")
+ private String accountName;
+
+ @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class,
+ description="project who will own the VLAN")
+ private Long projectId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class,
+ required=true, description="domain ID of the account owning a VLAN")
+ private Long domainId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public Long getProjectId() {
+ return projectId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, ResourceAllocationException {
+ Vlan result = _configService.dedicatePublicIpRange(this);
+ if (result != null) {
+ VlanIpRangeResponse response = _responseGenerator.createVlanIpRangeResponse(result);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate vlan ip range");
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java
new file mode 100644
index 0000000..91cc7d3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java
@@ -0,0 +1,77 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.vlan;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.VlanIpRangeResponse;
+import org.apache.log4j.Logger;
+
+import com.cloud.user.Account;
+
+@APICommand(name = "releasePublicIpRange", description="Releases a Public IP range back to the system pool", responseObject=SuccessResponse.class)
+public class ReleasePublicIpRangeCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleasePublicIpRangeCmd.class.getName());
+
+ private static final String s_name = "releasepubliciprangeresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VlanIpRangeResponse.class,
+ required=true, description="the id of the Public IP range")
+ private Long id;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = _configService.releasePublicIpRange(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release public ip range");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 4ce9fd3..798d226 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -124,6 +124,8 @@ listDiskOfferings=15
createVlanIpRange=1
deleteVlanIpRange=1
listVlanIpRanges=1
+dedicatePublicIpRange=1
+releasePublicIpRange=1
#### address commands
associateIpAddress=15
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/src/com/cloud/configuration/ConfigurationManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java
old mode 100644
new mode 100755
index c5f65e9..d7faf19
--- a/server/src/com/cloud/configuration/ConfigurationManager.java
+++ b/server/src/com/cloud/configuration/ConfigurationManager.java
@@ -30,6 +30,7 @@ import com.cloud.dc.Vlan;
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.Capability;
import com.cloud.network.Network.Provider;
@@ -150,6 +151,8 @@ public interface ConfigurationManager extends ConfigurationService, Manager {
*/
boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller);
+ boolean releasePublicIpRange(long userId, long vlanDbId, Account caller);
+
/**
* Converts a comma separated list of tags to a List
*
@@ -211,7 +214,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager {
ClusterVO getCluster(long id);
- boolean deleteAccountSpecificVirtualRanges(long accountId);
+ boolean releaseAccountSpecificVirtualRanges(long accountId);
/**
* Edits a pod in the database. Will not allow you to edit pods that are being used anywhere in the system.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index ceeae1e..fce3c01 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -56,7 +56,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
@@ -2306,9 +2308,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks");
}
- // if it's an account specific range, associate ip address list to the account
- boolean associateIpRangeToAccount = false;
-
if (forVirtualNetwork) {
if (vlanOwner != null) {
@@ -2316,8 +2315,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
//check resource limits
_resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountIpRange);
-
- associateIpRangeToAccount = true;
}
}
@@ -2332,21 +2329,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
endIP, vlanGateway, vlanNetmask, vlanId, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
txn.commit();
- if (associateIpRangeToAccount) {
- _networkMgr.associateIpAddressListToAccount(userId, vlanOwner.getId(), zoneId, vlan.getId(), null);
- }
-
- // Associate ips to the network
- if (associateIpRangeToAccount) {
- if (network.getState() == Network.State.Implemented) {
- s_logger.debug("Applying ip associations for vlan id=" + vlanId + " in network " + network);
- if (!_networkMgr.applyIpAssociations(network, false)) {
- s_logger.warn("Failed to apply ip associations for vlan id=1 as a part of add vlan range for account id=" + vlanOwner.getId());
- }
- } else {
- s_logger.trace("Network id=" + network.getId() + " is not Implemented, no need to apply ipAssociations");
- }
- }
return vlan;
}
@@ -2699,6 +2681,149 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
@Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_DEDICATE, eventDescription = "dedicating vlan ip range", async = false)
+ public Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd) throws ResourceAllocationException {
+ Long vlanDbId = cmd.getId();
+ String accountName = cmd.getAccountName();
+ Long domainId = cmd.getDomainId();
+ Long projectId = cmd.getProjectId();
+
+ // Check if account is valid
+ Account vlanOwner = null;
+ if (projectId != null) {
+ if (accountName != null) {
+ throw new InvalidParameterValueException("accountName and projectId are mutually exclusive");
+ }
+ Project project = _projectMgr.getProject(projectId);
+ if (project == null) {
+ throw new InvalidParameterValueException("Unable to find project by id " + projectId);
+ }
+ vlanOwner = _accountMgr.getAccount(project.getProjectAccountId());
+ }
+
+ if ((accountName != null) && (domainId != null)) {
+ vlanOwner = _accountDao.findActiveAccount(accountName, domainId);
+ if (vlanOwner == null) {
+ throw new InvalidParameterValueException("Please specify a valid account");
+ }
+ }
+
+ // Check if range is valid
+ VlanVO vlan = _vlanDao.findById(vlanDbId);
+ if (vlan == null) {
+ throw new InvalidParameterValueException("Please specify a valid Public IP range id");
+ }
+
+ // Check if range has already been dedicated
+ List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanDbId);
+ if (maps != null && !maps.isEmpty()) {
+ throw new InvalidParameterValueException("Specified Public IP range has already been dedicated");
+ }
+
+ // Verify that zone exists and is advanced
+ Long zoneId = vlan.getDataCenterId();
+ DataCenterVO zone = _zoneDao.findById(zoneId);
+ if (zone == null) {
+ throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
+ }
+ if (zone.getNetworkType() == NetworkType.Basic) {
+ throw new InvalidParameterValueException("Public IP range can be dedicated to an account only in the zone of type " + NetworkType.Advanced);
+ }
+
+ // Check Public IP resource limits
+ int accountPublicIpRange = _publicIpAddressDao.countIPs(zoneId, vlanDbId, false);
+ _resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountPublicIpRange);
+
+ // Check if any of the Public IP addresses is allocated to another account
+ List<IPAddressVO> ips = _publicIpAddressDao.listByVlanId(vlanDbId);
+ for (IPAddressVO ip : ips) {
+ Long allocatedToAccountId = ip.getAllocatedToAccountId();
+ if (allocatedToAccountId != null) {
+ Account accountAllocatedTo = _accountMgr.getActiveAccountById(allocatedToAccountId);
+ if (!accountAllocatedTo.getAccountName().equalsIgnoreCase(accountName))
+ throw new InvalidParameterValueException("Public IP address in range is already allocated to another account");
+ }
+ }
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+
+ // Create an AccountVlanMapVO entry
+ AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(vlanOwner.getId(), vlan.getId());
+ _accountVlanMapDao.persist(accountVlanMapVO);
+
+ txn.commit();
+
+ return vlan;
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_RELEASE, eventDescription = "releasing a public ip range", async = false)
+ public boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd) {
+ Long vlanDbId = cmd.getId();
+
+ VlanVO vlan = _vlanDao.findById(vlanDbId);
+ if (vlan == null) {
+ throw new InvalidParameterValueException("Please specify a valid IP range id.");
+ }
+
+ return releasePublicIpRange(vlanDbId, UserContext.current().getCallerUserId(), UserContext.current().getCaller());
+ }
+
+ @Override
+ @DB
+ public boolean releasePublicIpRange(long vlanDbId, long userId, Account caller) {
+ VlanVO vlan = _vlanDao.findById(vlanDbId);
+
+ List<AccountVlanMapVO> acctVln = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanDbId);
+ // Verify range is dedicated
+ if (acctVln == null || acctVln.isEmpty()) {
+ throw new InvalidParameterValueException("Can't release Public IP range " + vlanDbId + " as it not dedicated to any account");
+ }
+
+ // Check if range has any allocated public IPs
+ long allocIpCount = _publicIpAddressDao.countIPs(vlan.getDataCenterId(), vlanDbId, true);
+ boolean success = true;
+ if (allocIpCount > 0) {
+ try {
+ vlan = _vlanDao.acquireInLockTable(vlanDbId, 30);
+ if (vlan == null) {
+ throw new CloudRuntimeException("Unable to acquire vlan configuration: " + vlanDbId);
+ }
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("lock vlan " + vlanDbId + " is acquired");
+ }
+ List<IPAddressVO> ips = _publicIpAddressDao.listByVlanId(vlanDbId);
+ for (IPAddressVO ip : ips) {
+ // Disassociate allocated IP's that are not in use
+ if ( !ip.isOneToOneNat() && !(ip.isSourceNat() && _networkModel.getNetwork(ip.getAssociatedWithNetworkId()) != null) &&
+ !(_firewallDao.countRulesByIpId(ip.getId()) > 0) ) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Releasing Public IP addresses" + ip +" of vlan " + vlanDbId + " as part of Public IP" +
+ " range release to the system pool");
+ }
+ success = success && _networkMgr.disassociatePublicIpAddress(ip.getId(), userId, caller);
+ }
+ }
+ if (!success) {
+ s_logger.warn("Some Public IP addresses that were not in use failed to be released as a part of" +
+ " vlan " + vlanDbId + "release to the system pool");
+ }
+ } finally {
+ _vlanDao.releaseFromLockTable(vlanDbId);
+ }
+ }
+
+ // A Public IP range can only be dedicated to one account at a time
+ if (_accountVlanMapDao.remove(acctVln.get(0).getId())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
public List<String> csvTagsToList(String tags) {
List<String> tagsList = new ArrayList<String>();
@@ -3957,14 +4082,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Override
@DB
- public boolean deleteAccountSpecificVirtualRanges(long accountId) {
+ public boolean releaseAccountSpecificVirtualRanges(long accountId) {
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId);
boolean result = true;
if (maps != null && !maps.isEmpty()) {
Transaction txn = Transaction.currentTxn();
txn.start();
for (AccountVlanMapVO map : maps) {
- if (!deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), map.getVlanDbId(),
+ if (!releasePublicIpRange(map.getVlanDbId(), _accountMgr.getSystemUser().getId(),
_accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM))) {
result = false;
}
@@ -3972,10 +4097,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (result) {
txn.commit();
} else {
- s_logger.error("Failed to delete account specific virtual ip ranges for account id=" + accountId);
+ s_logger.error("Failed to release account specific virtual ip ranges for account id=" + accountId);
}
} else {
- s_logger.trace("Account id=" + accountId + " has no account specific virtual ip ranges, nothing to delete");
+ s_logger.trace("Account id=" + accountId + " has no account specific virtual ip ranges, nothing to release");
}
return result;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index a97f2ce..5b60466 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -348,7 +348,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
}
@DB
- public PublicIp fetchNewPublicIp(long dcId, Long podId, Long vlanDbId, Account owner, VlanType vlanUse,
+ public PublicIp fetchNewPublicIp(long dcId, Long podId, List<Long> vlanDbIds, Account owner, VlanType vlanUse,
Long guestNetworkId, boolean sourceNat, boolean assign, String requestedIp, boolean isSystem, Long vpcId)
throws InsufficientAddressCapacityException {
StringBuilder errorMessage = new StringBuilder("Unable to get ip adress in ");
@@ -364,9 +364,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
errorMessage.append(" zone id=" + dcId);
}
- if (vlanDbId != null) {
- sc.addAnd("vlanId", SearchCriteria.Op.EQ, vlanDbId);
- errorMessage.append(", vlanId id=" + vlanDbId);
+ if ( vlanDbIds != null && !vlanDbIds.isEmpty() ) {
+ sc.setParameters("vlanId", vlanDbIds.toArray());
+ errorMessage.append(", vlanId id=" + vlanDbIds.toArray());
}
sc.setParameters("dc", dcId);
@@ -526,14 +526,14 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
}
// If account has Account specific ip ranges, try to allocate ip from there
- Long vlanId = null;
+ List<Long> vlanIds = new ArrayList<Long>();
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByAccount(ownerId);
if (maps != null && !maps.isEmpty()) {
- vlanId = maps.get(0).getVlanDbId();
+ vlanIds.add(maps.get(0).getVlanDbId());
}
- ip = fetchNewPublicIp(dcId, null, vlanId, owner, VlanType.VirtualNetwork, guestNtwkId,
+ ip = fetchNewPublicIp(dcId, null, vlanIds, owner, VlanType.VirtualNetwork, guestNtwkId,
isSourceNat, false, null, false, vpcId);
IPAddressVO publicIp = ip.ip();
@@ -669,6 +669,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
VlanType vlanType = VlanType.VirtualNetwork;
boolean assign = false;
+ boolean allocateFromDedicatedRange = false;
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
// zone is of type DataCenter. See DataCenterVO.java.
@@ -702,8 +703,32 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
txn.start();
- ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null,
- false, assign, null, isSystem, null);
+ // If account has dedicated Public IP ranges, allocate IP from the dedicated range
+ List<Long> vlanDbIds = new ArrayList<Long>();
+ List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByAccount(ipOwner.getId());
+ for (AccountVlanMapVO map : maps) {
+ vlanDbIds.add(map.getVlanDbId());
+ }
+ if (vlanDbIds != null && !vlanDbIds.isEmpty()) {
+ allocateFromDedicatedRange = true;
+ }
+
+ try {
+ if (allocateFromDedicatedRange) {
+ ip = fetchNewPublicIp(zone.getId(), null, vlanDbIds, ipOwner, vlanType, null,
+ false, assign, null, isSystem, null);
+ }
+ } catch(InsufficientAddressCapacityException e) {
+ s_logger.warn("All IPs dedicated to account " + ipOwner.getId() + " has been acquired." +
+ " Now acquiring from the system pool");
+ txn.close();
+ allocateFromDedicatedRange = false;
+ }
+
+ if (!allocateFromDedicatedRange) {
+ ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null,
+ isSystem, null);
+ }
if (ip == null) {
@@ -1082,7 +1107,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
AssignIpAddressSearch = _ipAddressDao.createSearchBuilder();
AssignIpAddressSearch.and("dc", AssignIpAddressSearch.entity().getDataCenterId(), Op.EQ);
AssignIpAddressSearch.and("allocated", AssignIpAddressSearch.entity().getAllocatedTime(), Op.NULL);
- AssignIpAddressSearch.and("vlanId", AssignIpAddressSearch.entity().getVlanId(), Op.EQ);
+ AssignIpAddressSearch.and("vlanId", AssignIpAddressSearch.entity().getVlanId(), Op.IN);
SearchBuilder<VlanVO> vlanSearch = _vlanDao.createSearchBuilder();
vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ);
vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/src/com/cloud/network/NetworkServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 4eb620c..a8cbaa7 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -697,15 +697,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
throw new IllegalArgumentException("only ip addresses that belong to a virtual network may be disassociated.");
}
- // Check for account wide pool. It will have an entry for account_vlan_map.
- if (_accountVlanMapDao.findAccountVlanMap(ipVO.getAllocatedToAccountId(), ipVO.getVlanId()) != null) {
- //see IPaddressVO.java
- InvalidParameterValueException ex = new InvalidParameterValueException("Sepcified IP address uuid belongs to" +
- " Account wide IP pool and cannot be disassociated");
- ex.addProxyObject("user_ip_address", ipAddressId, "ipAddressId");
- throw ex;
- }
-
// don't allow releasing system ip address
if (ipVO.getSystem()) {
InvalidParameterValueException ex = new InvalidParameterValueException("Can't release system IP address with specified id");
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index b869d1e..d9a4317 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -59,6 +59,7 @@ import org.apache.cloudstack.api.command.admin.storage.*;
import org.apache.cloudstack.api.command.admin.systemvm.*;
import org.apache.cloudstack.api.command.admin.usage.*;
import org.apache.cloudstack.api.command.admin.user.*;
+import org.apache.cloudstack.api.command.admin.vlan.*;
import org.apache.cloudstack.api.command.admin.vpc.*;
import org.apache.cloudstack.api.command.user.autoscale.*;
import org.apache.cloudstack.api.command.user.firewall.*;
@@ -2037,6 +2038,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(CreateVlanIpRangeCmd.class);
cmdList.add(DeleteVlanIpRangeCmd.class);
cmdList.add(ListVlanIpRangesCmd.class);
+ cmdList.add(DedicatePublicIpRangeCmd.class);
+ cmdList.add(ReleasePublicIpRangeCmd.class);
cmdList.add(AssignVMCmd.class);
cmdList.add(MigrateVMCmd.class);
cmdList.add(RecoverVMCmd.class);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/src/com/cloud/user/AccountManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index fe714c5..e74c491 100755
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -690,13 +690,13 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
accountCleanupNeeded = true;
}
- // delete account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned
+ // release account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned
// up successfully
if (networksDeleted) {
- if (!_configMgr.deleteAccountSpecificVirtualRanges(accountId)) {
+ if (!_configMgr.releaseAccountSpecificVirtualRanges(accountId)) {
accountCleanupNeeded = true;
} else {
- s_logger.debug("Account specific Virtual IP ranges " + " are successfully deleted as a part of account id=" + accountId + " cleanup.");
+ s_logger.debug("Account specific Virtual IP ranges " + " are successfully released as a part of account id=" + accountId + " cleanup.");
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/test/com/cloud/configuration/ConfigurationManagerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
new file mode 100755
index 0000000..ee98d53
--- /dev/null
+++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
@@ -0,0 +1,413 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.lang.reflect.Field;
+
+import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
+import org.apache.log4j.Logger;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import com.cloud.configuration.Resource.ResourceType;
+import com.cloud.dc.AccountVlanMapVO;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.Vlan;
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.dao.AccountVlanMapDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.network.NetworkManager;
+import com.cloud.network.dao.FirewallRulesDao;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressVO;
+import com.cloud.projects.ProjectManager;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountVO;
+import com.cloud.user.ResourceLimitService;
+import com.cloud.user.UserContext;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.net.Ip;
+
+import junit.framework.Assert;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doNothing;
+
+public class ConfigurationManagerTest {
+
+ private static final Logger s_logger = Logger.getLogger(ConfigurationManagerTest.class);
+
+ ConfigurationManagerImpl configurationMgr = new ConfigurationManagerImpl();
+
+ DedicatePublicIpRangeCmd dedicatePublicIpRangesCmd = new DedicatePublicIpRangeCmdExtn();
+ Class<?> _dedicatePublicIpRangeClass = dedicatePublicIpRangesCmd.getClass().getSuperclass();
+
+ ReleasePublicIpRangeCmd releasePublicIpRangesCmd = new ReleasePublicIpRangeCmdExtn();
+ Class<?> _releasePublicIpRangeClass = releasePublicIpRangesCmd.getClass().getSuperclass();
+
+ @Mock AccountManager _accountMgr;
+ @Mock ProjectManager _projectMgr;
+ @Mock ResourceLimitService _resourceLimitMgr;
+ @Mock NetworkManager _networkMgr;
+ @Mock AccountDao _accountDao;
+ @Mock VlanDao _vlanDao;
+ @Mock AccountVlanMapDao _accountVlanMapDao;
+ @Mock IPAddressDao _publicIpAddressDao;
+ @Mock DataCenterDao _zoneDao;
+ @Mock FirewallRulesDao _firewallDao;
+
+ VlanVO vlan = new VlanVO(Vlan.VlanType.VirtualNetwork, "vlantag", "vlangateway","vlannetmask", 1L, "iprange", 1L, 1L, null, null, null);
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ configurationMgr._accountMgr = _accountMgr;
+ configurationMgr._projectMgr = _projectMgr;
+ configurationMgr._resourceLimitMgr = _resourceLimitMgr;
+ configurationMgr._networkMgr = _networkMgr;
+ configurationMgr._accountDao = _accountDao;
+ configurationMgr._vlanDao = _vlanDao;
+ configurationMgr._accountVlanMapDao = _accountVlanMapDao;
+ configurationMgr._publicIpAddressDao = _publicIpAddressDao;
+ configurationMgr._zoneDao = _zoneDao;
+ configurationMgr._firewallDao = _firewallDao;
+
+ Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString());
+ when(configurationMgr._accountMgr.getAccount(anyLong())).thenReturn(account);
+ when(configurationMgr._accountDao.findActiveAccount(anyString(), anyLong())).thenReturn(account);
+ when(configurationMgr._accountMgr.getActiveAccountById(anyLong())).thenReturn(account);
+
+ when(configurationMgr._publicIpAddressDao.countIPs(anyLong(), anyLong(), anyBoolean())).thenReturn(1);
+
+ doNothing().when(configurationMgr._resourceLimitMgr).checkResourceLimit(any(Account.class),
+ any(ResourceType.class), anyLong());
+
+ when(configurationMgr._accountVlanMapDao.persist(any(AccountVlanMapVO.class))).thenReturn(new AccountVlanMapVO());
+
+ when(configurationMgr._vlanDao.acquireInLockTable(anyLong(), anyInt())).thenReturn(vlan);
+
+ UserContext.registerContext(1, account, null, true);
+
+ Field dedicateIdField = _dedicatePublicIpRangeClass.getDeclaredField("id");
+ dedicateIdField.setAccessible(true);
+ dedicateIdField.set(dedicatePublicIpRangesCmd, 1L);
+
+ Field accountNameField = _dedicatePublicIpRangeClass.getDeclaredField("accountName");
+ accountNameField.setAccessible(true);
+ accountNameField.set(dedicatePublicIpRangesCmd, "accountname");
+
+ Field projectIdField = _dedicatePublicIpRangeClass.getDeclaredField("projectId");
+ projectIdField.setAccessible(true);
+ projectIdField.set(dedicatePublicIpRangesCmd, null);
+
+ Field domainIdField = _dedicatePublicIpRangeClass.getDeclaredField("domainId");
+ domainIdField.setAccessible(true);
+ domainIdField.set(dedicatePublicIpRangesCmd, 1L);
+
+ Field releaseIdField = _releasePublicIpRangeClass.getDeclaredField("id");
+ releaseIdField.setAccessible(true);
+ releaseIdField.set(releasePublicIpRangesCmd, 1L);
+ }
+
+ @Test
+ public void testDedicatePublicIpRange() throws Exception {
+
+ s_logger.info("Running tests for DedicatePublicIpRange API");
+
+ /*
+ * TEST 1: given valid parameters DedicatePublicIpRange should succeed
+ */
+ runDedicatePublicIpRangePostiveTest();
+
+ /*
+ * TEST 2: given invalid public ip range DedicatePublicIpRange should fail
+ */
+ runDedicatePublicIpRangeInvalidRange();
+ /*
+ * TEST 3: given public IP range that is already dedicated to a different account DedicatePublicIpRange should fail
+ */
+ runDedicatePublicIpRangeDedicatedRange();
+
+ /*
+ * TEST 4: given zone is of type Basic DedicatePublicIpRange should fail
+ */
+ runDedicatePublicIpRangeInvalidZone();
+
+ /*
+ * TEST 5: given range is already allocated to a different account DedicatePublicIpRange should fail
+ */
+ runDedicatePublicIpRangeIPAdressAllocated();
+ }
+
+ @Test
+ public void testReleasePublicIpRange() throws Exception {
+
+ s_logger.info("Running tests for DedicatePublicIpRange API");
+
+ /*
+ * TEST 1: given valid parameters and no allocated public ip's in the range ReleasePublicIpRange should succeed
+ */
+ runReleasePublicIpRangePostiveTest1();
+
+ /*
+ * TEST 2: given valid parameters ReleasePublicIpRange should succeed
+ */
+ runReleasePublicIpRangePostiveTest2();
+
+ /*
+ * TEST 3: given range doesn't exist
+ */
+ runReleasePublicIpRangeInvalidIpRange();
+
+ /*
+ * TEST 4: given range is not dedicated to any account
+ */
+ runReleaseNonDedicatedPublicIpRange();
+ }
+
+ void runDedicatePublicIpRangePostiveTest() throws Exception {
+ Transaction txn = Transaction.open("runDedicatePublicIpRangePostiveTest");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByAccount(anyLong())).thenReturn(null);
+
+ DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
+ null, null, NetworkType.Advanced, null, null, true, true, null, null);
+ when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc);
+
+ List<IPAddressVO> ipAddressList = new ArrayList<IPAddressVO>();
+ IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false);
+ ipAddressList.add(ipAddress);
+ when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList);
+
+ try {
+ Vlan result = configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd);
+ Assert.assertNotNull(result);
+ } catch (Exception e) {
+ s_logger.info("exception in testing runDedicatePublicIpRangePostiveTest message: " + e.toString());
+ } finally {
+ txn.close("runDedicatePublicIpRangePostiveTest");
+ }
+ }
+
+ void runDedicatePublicIpRangeInvalidRange() throws Exception {
+ Transaction txn = Transaction.open("runDedicatePublicIpRangeInvalidRange");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(null);
+ try {
+ configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd);
+ } catch (Exception e) {
+ Assert.assertTrue(e.getMessage().contains("Please specify a valid Public IP range id"));
+ } finally {
+ txn.close("runDedicatePublicIpRangeInvalidRange");
+ }
+ }
+
+ void runDedicatePublicIpRangeDedicatedRange() throws Exception {
+ Transaction txn = Transaction.open("runDedicatePublicIpRangeDedicatedRange");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ // public ip range is already dedicated
+ List<AccountVlanMapVO> accountVlanMaps = new ArrayList<AccountVlanMapVO>();
+ AccountVlanMapVO accountVlanMap = new AccountVlanMapVO(1, 1);
+ accountVlanMaps.add(accountVlanMap);
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(accountVlanMaps);
+
+ DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
+ null, null, NetworkType.Advanced, null, null, true, true, null, null);
+ when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc);
+
+ List<IPAddressVO> ipAddressList = new ArrayList<IPAddressVO>();
+ IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false);
+ ipAddressList.add(ipAddress);
+ when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList);
+
+ try {
+ configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd);
+ } catch (Exception e) {
+ Assert.assertTrue(e.getMessage().contains("Public IP range has already been dedicated"));
+ } finally {
+ txn.close("runDedicatePublicIpRangePublicIpRangeDedicated");
+ }
+ }
+
+ void runDedicatePublicIpRangeInvalidZone() throws Exception {
+ Transaction txn = Transaction.open("runDedicatePublicIpRangeInvalidZone");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(null);
+
+ // public ip range belongs to zone of type basic
+ DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
+ null, null, NetworkType.Basic, null, null, true, true, null, null);
+ when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc);
+
+ List<IPAddressVO> ipAddressList = new ArrayList<IPAddressVO>();
+ IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false);
+ ipAddressList.add(ipAddress);
+ when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList);
+
+ try {
+ configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd);
+ } catch (Exception e) {
+ Assert.assertTrue(e.getMessage().contains("Public IP range can be dedicated to an account only in the zone of type Advanced"));
+ } finally {
+ txn.close("runDedicatePublicIpRangeInvalidZone");
+ }
+ }
+
+ void runDedicatePublicIpRangeIPAdressAllocated() throws Exception {
+ Transaction txn = Transaction.open("runDedicatePublicIpRangeIPAdressAllocated");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByAccount(anyLong())).thenReturn(null);
+
+ DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
+ null, null, NetworkType.Advanced, null, null, true, true, null, null);
+ when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc);
+
+ // one of the ip addresses of the range is allocated to different account
+ List<IPAddressVO> ipAddressList = new ArrayList<IPAddressVO>();
+ IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false);
+ ipAddress.setAllocatedToAccountId(1L);
+ ipAddressList.add(ipAddress);
+ when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList);
+
+ try {
+ configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd);
+ } catch (Exception e) {
+ Assert.assertTrue(e.getMessage().contains("Public IP address in range is already allocated to another account"));
+ } finally {
+ txn.close("runDedicatePublicIpRangeIPAdressAllocated");
+ }
+ }
+
+ void runReleasePublicIpRangePostiveTest1() throws Exception {
+ Transaction txn = Transaction.open("runReleasePublicIpRangePostiveTest1");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ List<AccountVlanMapVO> accountVlanMaps = new ArrayList<AccountVlanMapVO>();
+ AccountVlanMapVO accountVlanMap = new AccountVlanMapVO(1, 1);
+ accountVlanMaps.add(accountVlanMap);
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(accountVlanMaps);
+
+ // no allocated ip's
+ when(configurationMgr._publicIpAddressDao.countIPs(anyLong(), anyLong(), anyBoolean())).thenReturn(0);
+
+ when(configurationMgr._accountVlanMapDao.remove(anyLong())).thenReturn(true);
+ try {
+ Boolean result = configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd);
+ Assert.assertTrue(result);
+ } catch (Exception e) {
+ s_logger.info("exception in testing runReleasePublicIpRangePostiveTest1 message: " + e.toString());
+ } finally {
+ txn.close("runReleasePublicIpRangePostiveTest1");
+ }
+ }
+
+ void runReleasePublicIpRangePostiveTest2() throws Exception {
+ Transaction txn = Transaction.open("runReleasePublicIpRangePostiveTest2");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ List<AccountVlanMapVO> accountVlanMaps = new ArrayList<AccountVlanMapVO>();
+ AccountVlanMapVO accountVlanMap = new AccountVlanMapVO(1, 1);
+ accountVlanMaps.add(accountVlanMap);
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(accountVlanMaps);
+
+ when(configurationMgr._publicIpAddressDao.countIPs(anyLong(), anyLong(), anyBoolean())).thenReturn(1);
+
+ List<IPAddressVO> ipAddressList = new ArrayList<IPAddressVO>();
+ IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false);
+ ipAddressList.add(ipAddress);
+ when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList);
+
+ when(configurationMgr._firewallDao.countRulesByIpId(anyLong())).thenReturn(0L);
+
+ when(configurationMgr._networkMgr.disassociatePublicIpAddress(anyLong(), anyLong(), any(Account.class))).thenReturn(true);
+
+ when(configurationMgr._vlanDao.releaseFromLockTable(anyLong())).thenReturn(true);
+
+ when(configurationMgr._accountVlanMapDao.remove(anyLong())).thenReturn(true);
+ try {
+ Boolean result = configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd);
+ Assert.assertTrue(result);
+ } catch (Exception e) {
+ s_logger.info("exception in testing runReleasePublicIpRangePostiveTest2 message: " + e.toString());
+ } finally {
+ txn.close("runReleasePublicIpRangePostiveTest2");
+ }
+ }
+
+ void runReleasePublicIpRangeInvalidIpRange() throws Exception {
+ Transaction txn = Transaction.open("runReleasePublicIpRangeInvalidIpRange");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(null);
+ try {
+ configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd);
+ } catch (Exception e) {
+ Assert.assertTrue(e.getMessage().contains("Please specify a valid IP range id"));
+ } finally {
+ txn.close("runReleasePublicIpRangeInvalidIpRange");
+ }
+ }
+
+ void runReleaseNonDedicatedPublicIpRange() throws Exception {
+ Transaction txn = Transaction.open("runReleaseNonDedicatedPublicIpRange");
+
+ when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan);
+
+ when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(null);
+ try {
+ configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd);
+ } catch (Exception e) {
+ Assert.assertTrue(e.getMessage().contains("as it not dedicated to any account"));
+ } finally {
+ txn.close("runReleaseNonDedicatedPublicIpRange");
+ }
+ }
+
+
+ public class DedicatePublicIpRangeCmdExtn extends DedicatePublicIpRangeCmd {
+ public long getEntityOwnerId() {
+ return 1;
+ }
+ }
+
+ public class ReleasePublicIpRangeCmdExtn extends ReleasePublicIpRangeCmd {
+ public long getEntityOwnerId() {
+ return 1;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
old mode 100644
new mode 100755
index b0063fa..a03e361
--- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
@@ -40,7 +40,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
@@ -544,7 +546,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
* @see com.cloud.configuration.ConfigurationManager#deleteAccountSpecificVirtualRanges(long)
*/
@Override
- public boolean deleteAccountSpecificVirtualRanges(long accountId) {
+ public boolean releaseAccountSpecificVirtualRanges(long accountId) {
// TODO Auto-generated method stub
return false;
}
@@ -613,5 +615,24 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
return null;
}
+ @Override
+ public Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd)
+ throws ResourceAllocationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean releasePublicIpRange(long userId, long vlanDbId,
+ Account caller) {
+ // TODO Auto-generated method stub
+ return false;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/test/integration/component/test_public_ip_range.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_public_ip_range.py b/test/integration/component/test_public_ip_range.py
new file mode 100755
index 0000000..f2c967f
--- /dev/null
+++ b/test/integration/component/test_public_ip_range.py
@@ -0,0 +1,173 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" P1 tests for Dedicating Public IP addresses
+"""
+#Import Local Modules
+import marvin
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.integration.lib.utils import *
+from marvin.integration.lib.base import *
+from marvin.integration.lib.common import *
+import datetime
+
+class Services:
+ """Test Dedicating Public IP addresses
+ """
+
+ def __init__(self):
+ self.services = {
+ "domain": {
+ "name": "Domain",
+ },
+ "account": {
+ "email": "test@test.com",
+ "firstname": "Test",
+ "lastname": "User",
+ "username": "test",
+ "password": "password",
+ },
+ "gateway": "10.102.197.1",
+ "netmask": "255.255.255.0",
+ "forvirtualnetwork": "true",
+ "startip": "10.102.197.70",
+ "endip": "10.102.197.73",
+ "zoneid": "1",
+ "podid": "",
+ "vlan": "101",
+ }
+
+class TesDedicatePublicIPRange(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.api_client = super(TesDedicatePublicIPRange, cls).getClsTestClient().getApiClient()
+ cls.services = Services().services
+ # Get Zone, Domain
+ cls.domain = get_domain(cls.api_client, cls.services)
+ cls.zone = get_zone(cls.api_client, cls.services)
+
+ # Create Account
+ cls.account = Account.create(
+ cls.api_client,
+ cls.services["account"],
+ domainid=cls.domain.id
+ )
+ cls._cleanup = [
+ cls.account,
+ ]
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ # Cleanup resources used
+ cleanup_resources(cls.api_client, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.cleanup = []
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @attr(tags = ["publiciprange", "dedicate", "release"])
+ def test_dedicatePublicIpRange(self):
+ """Test public IP range dedication
+ """
+
+ # Validate the following:
+ # 1. Create a Public IP range
+ # 2. Created IP range should be present, verify with listVlanIpRanges
+ # 3. Dedicate the created IP range to user account
+ # 4. Verify IP range is dedicated, verify with listVlanIpRanges
+ # 5. Release the dedicated Public IP range back to the system
+ # 6. Verify IP range has been released, verify with listVlanIpRanges
+ # 7. Delete the Public IP range
+
+ self.debug("Creating Public IP range")
+ self.public_ip_range = PublicIpRange.create(
+ self.api_client,
+ self.services
+ )
+ list_public_ip_range_response = PublicIpRange.list(
+ self.apiclient,
+ id=self.public_ip_range.vlan.id
+ )
+ self.debug(
+ "Verify listPublicIpRanges response for public ip ranges: %s" \
+ % self.public_ip_range.vlan.id
+ )
+ self.assertEqual(
+ isinstance(list_public_ip_range_response, list),
+ True,
+ "Check for list Public IP range response"
+ )
+ public_ip_response = list_public_ip_range_response[0]
+ self.assertEqual(
+ public_ip_response.id,
+ self.public_ip_range.vlan.id,
+ "Check public ip range response id is in listVlanIpRanges"
+ )
+
+ self.debug("Dedicating Public IP range");
+ dedicate_public_ip_range_response = PublicIpRange.dedicate(
+ self.apiclient,
+ self.public_ip_range.vlan.id,
+ account=self.account.account.name,
+ domainid=self.account.account.domainid
+ )
+ list_public_ip_range_response = PublicIpRange.list(
+ self.apiclient,
+ id=self.public_ip_range.vlan.id
+ )
+ public_ip_response = list_public_ip_range_response[0]
+ self.assertEqual(
+ public_ip_response.account,
+ self.account.account.name,
+ "Check account name is in listVlanIpRanges as the account public ip range is dedicated to"
+ )
+
+ self.debug("Releasing Public IP range");
+ self.public_ip_range.release(self.apiclient)
+ list_public_ip_range_response = PublicIpRange.list(
+ self.apiclient,
+ id=self.public_ip_range.vlan.id
+ )
+ public_ip_response = list_public_ip_range_response[0]
+ self.assertEqual(
+ public_ip_response.account,
+ "system",
+ "Check account name is system account in listVlanIpRanges"
+ )
+
+ self.debug("Deleting Public IP range");
+ self.public_ip_range.delete(self.apiclient)
+
+ return
+
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f865c5a/tools/marvin/marvin/integration/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py
old mode 100644
new mode 100755
index d27ab3b..3df68ab
--- a/tools/marvin/marvin/integration/lib/base.py
+++ b/tools/marvin/marvin/integration/lib/base.py
@@ -1873,7 +1873,7 @@ class PublicIpRange:
"""Delete VlanIpRange"""
cmd = deleteVlanIpRange.deleteVlanIpRangeCmd()
- cmd.id = self.id
+ cmd.id = self.vlan.id
apiclient.deleteVlanIpRange(cmd)
@classmethod
@@ -1884,6 +1884,23 @@ class PublicIpRange:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVlanIpRanges(cmd))
+ @classmethod
+ def dedicate(cls, apiclient, id, account=None, domainid=None, projectid=None):
+ """Dedicate VLAN IP range"""
+
+ cmd = dedicatePublicIpRange.dedicatePublicIpRangeCmd()
+ cmd.id = id
+ cmd.account = account
+ cmd.domainid = domainid
+ cmd.projectid = projectid
+ return PublicIpRange(apiclient.dedicatePublicIpRange(cmd).__dict__)
+
+ def release(self, apiclient):
+ """Release VLAN IP range"""
+
+ cmd = releasePublicIpRange.releasePublicIpRangeCmd()
+ cmd.id = self.vlan.id
+ return apiclient.releasePublicIpRange(cmd)
class SecondaryStorage:
"""Manage Secondary storage"""