diff --git a/api/src/com/cloud/configuration/ConfigurationService.java b/api/src/com/cloud/configuration/ConfigurationService.java index e63fcece525..6937d0b64de 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); diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 6a26212ecc7..0ee7f402fd7 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()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java index 95728dd184d..c5130587ec5 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java @@ -111,14 +111,14 @@ public class UpdateClusterCmd extends BaseCmd { if(cpuovercommitratio != null){ return Float.parseFloat(cpuovercommitratio); } - return 1.0f; + return null; } public Float getMemoryOvercommitRaito (){ if (memoryovercommitratio != null){ return Float.parseFloat(memoryovercommitratio); } - return 1.0f; + return null; } @Override @@ -127,9 +127,16 @@ public class UpdateClusterCmd extends BaseCmd { if (cluster == null) { throw new InvalidParameterValueException("Unable to find the cluster by id=" + getId()); } + if (getMemoryOvercommitRaito() !=null){ + if ((getMemoryOvercommitRaito().compareTo(1f) < 0)) { + throw new InvalidParameterValueException("Memory overcommit ratio should be greater than or equal to one"); + } + } - if ((getMemoryOvercommitRaito().compareTo(1f) < 0) | (getCpuOvercommitRatio().compareTo(1f) < 0)) { - throw new InvalidParameterValueException("Cpu and ram overcommit ratios should be greater than one"); + if (getCpuOvercommitRatio() !=null){ + if (getCpuOvercommitRatio().compareTo(1f) < 0) { + throw new InvalidParameterValueException("Cpu overcommit ratio should be greater than or equal to one"); + } } Cluster result = _resourceService.updateCluster(cluster, getClusterType(), getHypervisor(), getAllocationState(), getManagedstate(), getMemoryOvercommitRaito(), getCpuOvercommitRatio()); 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 00000000000..e7b1105af94 --- /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"); + } + } + +} 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 00000000000..91cc7d33da9 --- /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"); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java index cd559d8c470..b08b6aeff17 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java @@ -93,6 +93,9 @@ public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { } public String getStickyMethod() { + if (stickyMethod == null) { + return "sourceip"; + } return stickyMethod; } diff --git a/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java index 0fd064f41b5..38e080bd28a 100644 --- a/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java +++ b/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java @@ -50,6 +50,10 @@ public class GlobalLoadBalancerResponse extends BaseResponse implements Controll @Param(description = "session persistence method used for the global load balancer") private String stickyMethod; + @SerializedName(ApiConstants.GSLB_SERVICE_TYPE) + @Param(description = "GSLB service type") + private String serviceType; + @SerializedName(ApiConstants.REGION_ID) @Param(description = "Region Id in which global load balancer is created") private Integer regionId; @@ -96,6 +100,10 @@ public class GlobalLoadBalancerResponse extends BaseResponse implements Controll this.stickyMethod = stickyMethod; } + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + public void setServiceDomainName(String domainName) { this.gslbDomainName = domainName; } diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 35f7ed200f1..7960996a229 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 diff --git a/core/src/com/cloud/vm/VmDetailConstants.java b/core/src/com/cloud/vm/VmDetailConstants.java index 90068d1b72b..5ff3ce02fe4 100644 --- a/core/src/com/cloud/vm/VmDetailConstants.java +++ b/core/src/com/cloud/vm/VmDetailConstants.java @@ -20,4 +20,5 @@ public interface VmDetailConstants { public static final String KEYBOARD = "keyboard"; public static final String NIC_ADAPTER = "nicAdapter"; public static final String ROOK_DISK_CONTROLLER = "rootDiskController"; + public static final String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag"; } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java index 2d6b94fdfaf..fc4aea85822 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java @@ -23,7 +23,7 @@ import java.util.UUID; import javax.inject.Inject; import org.apache.cloudstack.storage.to.ImageDataStoreTO; -import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; +import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.to.TemplateTO; import org.mockito.Mockito; @@ -126,7 +126,7 @@ public class DirectAgentTest extends CloudStackTestNGBase { @Test public void testDownloadTemplate() { - ImageOnPrimayDataStoreTO image = Mockito.mock(ImageOnPrimayDataStoreTO.class); + ImageOnPrimaryDataStoreTO image = Mockito.mock(ImageOnPrimaryDataStoreTO.class); PrimaryDataStoreTO primaryStore = Mockito.mock(PrimaryDataStoreTO.class); Mockito.when(primaryStore.getUuid()).thenReturn(this.getLocalStorageUuid()); Mockito.when(image.getPrimaryDataStore()).thenReturn(primaryStore); diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java index f4be0676b9b..1734bc409cc 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java +++ b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java @@ -18,14 +18,14 @@ */ package org.apache.cloudstack.storage.command; -import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; +import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeTO; import com.cloud.agent.api.Command; public class CreateVolumeFromBaseImageCommand extends Command implements StorageSubSystemCommand { private final VolumeTO volume; - private final ImageOnPrimayDataStoreTO image; + private final ImageOnPrimaryDataStoreTO image; public CreateVolumeFromBaseImageCommand(VolumeTO volume, String image) { this.volume = volume; @@ -36,7 +36,7 @@ public class CreateVolumeFromBaseImageCommand extends Command implements Storage return this.volume; } - public ImageOnPrimayDataStoreTO getImage() { + public ImageOnPrimaryDataStoreTO getImage() { return this.image; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java index 91b6c6329bb..40a65dcf07f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java @@ -64,7 +64,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto return null; } - public List getPrimayrDataStoreProviders() { + public List getPrimaryDataStoreProviders() { List providers = new ArrayList(); for (DataStoreProvider provider : providerMap.values()) { if (provider instanceof PrimaryDataStoreProvider) { @@ -138,7 +138,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto throw new InvalidParameterValueException("Invalid parameter, need to specify type: either primary or image"); } if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.PRIMARY.toString())) { - return this.getPrimayrDataStoreProviders(); + return this.getPrimaryDataStoreProviders(); } else if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.IMAGE.toString())) { return this.getImageDataStoreProviders(); } else { diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimayDataStoreTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java similarity index 92% rename from engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimayDataStoreTO.java rename to engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java index 18743d70bf2..a9a3cc43c0e 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimayDataStoreTO.java +++ b/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java @@ -20,11 +20,11 @@ package org.apache.cloudstack.storage.to; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; -public class ImageOnPrimayDataStoreTO { +public class ImageOnPrimaryDataStoreTO { private final String pathOnPrimaryDataStore; private PrimaryDataStoreTO dataStore; private final TemplateTO template; - public ImageOnPrimayDataStoreTO(TemplateOnPrimaryDataStoreInfo template) { + public ImageOnPrimaryDataStoreTO(TemplateOnPrimaryDataStoreInfo template) { this.pathOnPrimaryDataStore = template.getPath(); //this.dataStore = template.getPrimaryDataStore().getDataStoreTO(); this.template = new TemplateTO(template.getTemplate()); diff --git a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java index 430cf92659d..4c2c7f1c131 100644 --- a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java +++ b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java @@ -52,35 +52,37 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements ExcludeList avoid) throws AffinityConflictException { VirtualMachine vm = vmProfile.getVirtualMachine(); - AffinityGroupVMMapVO vmGroupMapping = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType()); + List vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType()); - if (vmGroupMapping != null) { - AffinityGroupVO group = _affinityGroupDao.findById(vmGroupMapping.getAffinityGroupId()); + for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) { + if (vmGroupMapping != null) { + AffinityGroupVO group = _affinityGroupDao.findById(vmGroupMapping.getAffinityGroupId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Processing affinity group " + group.getName() + " for VM Id: " + vm.getId()); - } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Processing affinity group " + group.getName() + " for VM Id: " + vm.getId()); + } - List groupVMIds = _affinityGroupVMMapDao.listVmIdsByAffinityGroup(group.getId()); - groupVMIds.remove(vm.getId()); + List groupVMIds = _affinityGroupVMMapDao.listVmIdsByAffinityGroup(group.getId()); + groupVMIds.remove(vm.getId()); + + for (Long groupVMId : groupVMIds) { + VMInstanceVO groupVM = _vmInstanceDao.findById(groupVMId); + if (groupVM != null && !groupVM.isRemoved()) { + if (groupVM.getHostId() != null) { + avoid.addHost(groupVM.getHostId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Added host " + groupVM.getHostId() + " to avoid set, since VM " + + groupVM.getId() + " is present on the host"); + } + } else if (VirtualMachine.State.Stopped.equals(groupVM.getState()) + && groupVM.getLastHostId() != null) { + avoid.addHost(groupVM.getLastHostId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Added host " + groupVM.getLastHostId() + " to avoid set, since VM " + + groupVM.getId() + " is present on the host, in Stopped state"); + } - for (Long groupVMId : groupVMIds) { - VMInstanceVO groupVM = _vmInstanceDao.findById(groupVMId); - if (groupVM != null && !groupVM.isRemoved()) { - if (groupVM.getHostId() != null) { - avoid.addHost(groupVM.getHostId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Added host " + groupVM.getHostId() + " to avoid set, since VM " - + groupVM.getId() + " is present on the host"); } - } else if (VirtualMachine.State.Stopped.equals(groupVM.getState()) - && groupVM.getLastHostId() != null) { - avoid.addHost(groupVM.getLastHostId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Added host " + groupVM.getLastHostId() + " to avoid set, since VM " - + groupVM.getId() + " is present on the host, in Stopped state"); - } - } } } diff --git a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java index d2f25654c7a..09563da2264 100644 --- a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java +++ b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java @@ -217,7 +217,7 @@ public class AlertsSyslogAppender extends AppenderSkeleton { message.append("unknown" + MESSAGE_DELIMITER_STRING); } - if (alertType > 0) { + if (alertType >= 0) { message.append("alertType").append(_keyValueDelimiter).append(" ").append(alertsMap.get(alertType)) .append(MESSAGE_DELIMITER_STRING); if (dataCenterId != 0) { @@ -333,4 +333,4 @@ public class AlertsSyslogAppender extends AppenderSkeleton { public void setKeyValueDelimiter(String keyValueDelimiter) { this._keyValueDelimiter = keyValueDelimiter; } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index 20146970daa..f6f0923c7ae 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -27,6 +27,7 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -40,6 +41,8 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.cluster.ClusterManager; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; @@ -84,6 +87,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { @Inject VmwareManager _vmwareMgr; @Inject SecondaryStorageVmManager _secStorageMgr; @Inject NetworkModel _networkMgr; + @Inject ConfigurationDao _configDao; protected VMwareGuru() { super(); @@ -212,8 +216,21 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { sbMacSequence.deleteCharAt(sbMacSequence.length() - 1); String bootArgs = to.getBootArgs(); to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString()); + + } + + // Don't do this if the virtual machine is one of the special types + // Should only be done on user machines + if(!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO + || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)) { + String nestedVirt = _configDao.getValue(Config.VmwareEnableNestedVirtualization.key()); + if (nestedVirt != null) { + s_logger.debug("Nested virtualization requested, adding flag to vm configuration"); + details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, nestedVirt); + to.setDetails(details); + + } } - // Determine the VM's OS description GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); to.setOs(guestOS.getDisplayName()); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 634827b6468..f569595b8b0 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -232,6 +232,7 @@ import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.DatastoreSummary; import com.vmware.vim25.DynamicProperty; +import com.vmware.vim25.HostCapability; import com.vmware.vim25.HostFirewallInfo; import com.vmware.vim25.HostFirewallRuleset; import com.vmware.vim25.HostNetworkTrafficShapingPolicy; @@ -2147,6 +2148,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(),(int) (vmSpec.getMaxRam()/(1024*1024)), ramMb, translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), vmSpec.getLimitCpuUse()); + + if ("true".equals(vmSpec.getDetails().get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG))) { + s_logger.debug("Nested Virtualization enabled in configuration, checking hypervisor capability"); + ManagedObjectReference hostMor = vmMo.getRunningHost().getMor(); + ManagedObjectReference computeMor = context.getVimClient().getMoRefProp(hostMor, "parent"); + ManagedObjectReference environmentBrowser = + context.getVimClient().getMoRefProp(computeMor, "environmentBrowser"); + HostCapability hostCapability = context.getService().queryTargetCapabilities(environmentBrowser, hostMor); + if (hostCapability.isNestedHVSupported()) { + s_logger.debug("Hypervisor supports nested virtualization, enabling for VM " + vmSpec.getName()); + vmConfigSpec.setNestedHVEnabled(true); + } + else { + s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName()); + vmConfigSpec.setNestedHVEnabled(false); + } + } VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[totalChangeDevices]; int i = 0; diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java index 9c291491114..7e0ccbed39c 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java @@ -39,7 +39,7 @@ import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol; -import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; +import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeTO; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -207,7 +207,7 @@ public class XenServerStorageResource { protected Answer execute(CreateVolumeFromBaseImageCommand cmd) { VolumeTO volume = cmd.getVolume(); - ImageOnPrimayDataStoreTO baseImage = cmd.getImage(); + ImageOnPrimaryDataStoreTO baseImage = cmd.getImage(); Connection conn = hypervisorResource.getConnection(); try { diff --git a/server/pom.xml b/server/pom.xml index a3971954475..ca56851ec15 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -158,8 +158,6 @@ com/cloud/network/vpn/RemoteAccessVpnTest.java com/cloud/network/security/SecurityGroupManagerImpl2Test.java com/cloud/network/security/SecurityGroupManagerImpl2Test.java - - org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 476038d51a1..6f900832dd9 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -746,11 +746,13 @@ public class ApiResponseHelper implements ResponseGenerator { GlobalLoadBalancerResponse response = new GlobalLoadBalancerResponse(); response.setAlgorithm(globalLoadBalancerRule.getAlgorithm()); response.setStickyMethod(globalLoadBalancerRule.getPersistence()); + response.setServiceType(globalLoadBalancerRule.getServiceType()); response.setServiceDomainName(globalLoadBalancerRule.getGslbDomain()); response.setName(globalLoadBalancerRule.getName()); response.setDescription(globalLoadBalancerRule.getDescription()); response.setRegionIdId(globalLoadBalancerRule.getRegion()); response.setId(globalLoadBalancerRule.getUuid()); + response.setObjectName("globalloadbalancer"); return response; } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 2bc06c032b7..ac9a3be3159 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -1941,7 +1941,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); isAscending = (isAscending == null ? true : isAscending); Filter searchFilter = new Filter(DiskOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); + SearchCriteria sc = _diskOfferingJoinDao.createSearchCriteria(); Account account = UserContext.current().getCaller(); @@ -1956,9 +1956,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (account.getType() == Account.ACCOUNT_TYPE_ADMIN || isPermissible(account.getDomainId(), domainId) ) { // check if the user's domain == do's domain || user's domain is // a child of so's domain for non-root users - sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); - SearchCriteria sc = sb.create(); - sc.setParameters("domainId", domainId); + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); return _diskOfferingJoinDao.searchAndCount(sc, searchFilter); } else { throw new PermissionDeniedException("The account:" + account.getAccountName() @@ -1966,11 +1964,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); - sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); - - boolean includePublicOfferings = false; List domainIds = null; // For non-root users, only return all offerings for the user's domain, and everything above till root if ((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) @@ -1987,16 +1981,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - sb.and("domainIdIn", sb.entity().getDomainId(), SearchCriteria.Op.IN); + + SearchCriteria spc = _diskOfferingJoinDao.createSearchCriteria(); - // include also public offering if no keyword, name and id specified - if ( keyword == null && name == null && id == null ){ - includePublicOfferings = true; - } + spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); + spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where + sc.addAnd("domainId", SearchCriteria.Op.SC, spc); + sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root users should not see system offering at all + } - SearchCriteria sc = sb.create(); - if (keyword != null) { + if (keyword != null) { SearchCriteria ssc = _diskOfferingJoinDao.createSearchCriteria(); ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -2004,26 +1999,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("name", SearchCriteria.Op.SC, ssc); } - if (name != null) { - sc.setParameters("name", "%" + name + "%"); - } - if (id != null) { - sc.setParameters("id", id); + sc.addAnd("id", SearchCriteria.Op.EQ, id); } - if (domainIds != null ){ - sc.setParameters("domainIdIn", domainIds.toArray()); + if (name != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, name); } - - if (includePublicOfferings){ - SearchCriteria spc = _diskOfferingJoinDao.createSearchCriteria(); - spc.addAnd("domainId", SearchCriteria.Op.NULL); - spc.addAnd("systemUse", SearchCriteria.Op.EQ, false); - - sc.addOr("systemUse", SearchCriteria.Op.SC, spc); - } - + // FIXME: disk offerings should search back up the hierarchy for // available disk offerings... /* @@ -2100,10 +2083,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - boolean includePublicOfferings = false; + // boolean includePublicOfferings = false; if ((caller.getType() == Account.ACCOUNT_TYPE_NORMAL || caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { - // For non-root users + // For non-root users. if (isSystem) { throw new InvalidParameterValueException("Only root admins can access system's offering"); } @@ -2119,12 +2102,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - sc.addAnd("domainId", SearchCriteria.Op.IN, domainIds.toArray()); + SearchCriteria spc = _srvOfferingJoinDao.createSearchCriteria(); + + spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); + spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where + sc.addAnd("domainId", SearchCriteria.Op.SC, spc); - // include also public offering if no keyword, name and id specified - if ( keyword == null && name == null && id == null ){ - includePublicOfferings = true; - } } else { // for root users @@ -2167,24 +2150,18 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (isSystem != null) { + // note that for non-root users, isSystem is always false when control comes to here sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem); } if (name != null) { - sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); + sc.addAnd("name", SearchCriteria.Op.EQ, name); } if (vmTypeStr != null) { sc.addAnd("vm_type", SearchCriteria.Op.EQ, vmTypeStr); } - if (includePublicOfferings){ - SearchCriteria spc = _srvOfferingJoinDao.createSearchCriteria(); - spc.addAnd("domainId", SearchCriteria.Op.NULL); - spc.addAnd("systemUse", SearchCriteria.Op.EQ, false); - sc.addOr("systemUse", SearchCriteria.Op.SC, spc); - } - return _srvOfferingJoinDao.searchAndCount(sc, searchFilter); } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 2137c003912..e3e305350b1 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -276,6 +276,7 @@ public enum Config { VmwareRootDiskControllerType("Advanced", ManagementServer.class, String.class, "vmware.root.disk.controller", "ide", "Specify the default disk controller for root volumes, valid values are scsi, ide", null), VmwareSystemVmNicDeviceType("Advanced", ManagementServer.class, String.class, "vmware.systemvm.nic.device.type", "E1000", "Specify the default network device type for system VMs, valid values are E1000, PCNet32, Vmxnet2, Vmxnet3", null), VmwareRecycleHungWorker("Advanced", ManagementServer.class, Boolean.class, "vmware.recycle.hung.wokervm", "false", "Specify whether or not to recycle hung worker VMs", null), + VmwareEnableNestedVirtualization("Advanced", ManagementServer.class, Boolean.class, "vmware.nested.virtualization", "false", "When set to true this will enable nested virtualization when this is supported by the hypervisor", null), // Midonet MidoNetAPIServerAddress("Network", ManagementServer.class, String.class, "midonet.apiserver.address", "http://localhost:8081", "Specify the address at which the Midonet API server can be contacted (if using Midonet)", null), 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 c5f65e9d0fc..d7faf19fd28 --- 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. diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index ceeae1ee910..fce3c010df4 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; } @@ -2698,6 +2680,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 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 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 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 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 csvTagsToList(String tags) { List tagsList = new ArrayList(); @@ -3957,14 +4082,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public boolean deleteAccountSpecificVirtualRanges(long accountId) { + public boolean releaseAccountSpecificVirtualRanges(long accountId) { List 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; } diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig deleted file mode 100755 index 134d59d0065..00000000000 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig +++ /dev/null @@ -1,298 +0,0 @@ -// 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.consoleproxy; - -import java.util.Map; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.GetVncPortAnswer; -import com.cloud.agent.api.GetVncPortCommand; -import com.cloud.agent.api.StartupProxyCommand; -import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.info.ConsoleProxyInfo; -import com.cloud.keystore.KeystoreManager; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.component.ManagerBase; -import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.dao.ConsoleProxyDao; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; - -@Local(value = { ConsoleProxyManager.class }) -public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager { - private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class); - - @Inject - protected HostDao _hostDao; - @Inject - protected UserVmDao _userVmDao; - private String _instance; - protected String _consoleProxyUrlDomain; - @Inject - private VMInstanceDao _instanceDao; - private ConsoleProxyListener _listener; - protected int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; - protected int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; - protected boolean _sslEnabled = false; - @Inject - AgentManager _agentMgr; - @Inject - VirtualMachineManager _itMgr; - @Inject - protected ConsoleProxyDao _cpDao; - @Inject - protected KeystoreManager _ksMgr; - - @Inject ConfigurationDao _configDao; - - public class AgentBasedAgentHook extends AgentHookBase { - - public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, - KeystoreManager ksMgr, AgentManager agentMgr) { - super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); - } - - @Override - protected HostVO findConsoleProxyHost(StartupProxyCommand cmd) { - return _hostDao.findByGuid(cmd.getGuid()); - } - - } - - public int getVncPort(VMInstanceVO vm) { - if (vm.getHostId() == null) { - return -1; - } - GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getHostName())); - return (answer == null || !answer.getResult()) ? -1 : answer.getPort(); - } - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - - if (s_logger.isInfoEnabled()) { - s_logger.info("Start configuring AgentBasedConsoleProxyManager"); - } - - Map configs = _configDao.getConfiguration("management-server", params); - String value = configs.get("consoleproxy.url.port"); - if (value != null) { - _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); - } - - value = configs.get("consoleproxy.port"); - if (value != null) { - _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); - } - - value = configs.get("consoleproxy.sslEnabled"); - if (value != null && value.equalsIgnoreCase("true")) { - _sslEnabled = true; - } - - _instance = configs.get("instance.name"); - - _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); - - _listener = - new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr)); - _agentMgr.registerForHostEvents(_listener, true, true, false); - - if (s_logger.isInfoEnabled()) { - s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled); - } - return true; - } - - HostVO findHost(VMInstanceVO vm) { - return _hostDao.findById(vm.getHostId()); - } - - @Override - public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { - UserVmVO userVm = _userVmDao.findById(userVmId); - if (userVm == null) { - s_logger.warn("User VM " + userVmId + " no longer exists, return a null proxy for user vm:" + userVmId); - return null; - } - - HostVO host = findHost(userVm); - if (host != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Assign embedded console proxy running at " + host.getName() + " to user vm " + userVmId + " with public IP " - + host.getPublicIpAddress()); - } - - // only private IP, public IP, host id have meaningful values, rest - // of all are place-holder values - String publicIp = host.getPublicIpAddress(); - if (publicIp == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Host " + host.getName() + "/" + host.getPrivateIpAddress() - + " does not have public interface, we will return its private IP for cosole proxy."); - } - publicIp = host.getPrivateIpAddress(); - } - - int urlPort = _consoleProxyUrlPort; - - if (host.getProxyPort() != null && host.getProxyPort().intValue() > 0) { - urlPort = host.getProxyPort().intValue(); - } - - return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort, _consoleProxyUrlDomain); - } else { - s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable."); - } - return null; - } - - - - - @Override - public ConsoleProxyVO startProxy(long proxyVmId) { - return null; - } - - @Override - public boolean destroyProxy(long proxyVmId) { - return false; - } - - @Override - public boolean rebootProxy(long proxyVmId) { - return false; - } - - @Override - public boolean stopProxy(long proxyVmId) { - return false; - } - - @Override - public void setManagementState(ConsoleProxyManagementState state) { - } - - @Override - public ConsoleProxyManagementState getManagementState() { - return null; - } - - @Override - public void resumeLastManagementState() { - } - - @Override - public String getName() { - return _name; - } -<<<<<<< HEAD - - @Override - public Long convertToId(String vmName) { - if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { - return null; - } - return VirtualMachineName.getConsoleProxyId(vmName); - } - - @Override - public ConsoleProxyVO findByName(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConsoleProxyVO findById(long id) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConsoleProxyVO persist(ConsoleProxyVO vm) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { - // TODO Auto-generated method stub - } - - @Override - public void finalizeExpunge(ConsoleProxyVO proxy) { - } - - @Override - public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { - //not supported - throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType()); - } - - - @Override - public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { - //not supported - throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); - } - - @Override - public void prepareStop(VirtualMachineProfile profile) { - } -} -======= -} ->>>>>>> QuickCloud: refactor to avoid copy paste of authentication and startup code diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 86bceddeeb9..d4e4e095716 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 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 vlanIds = new ArrayList(); List 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 vlanDbIds = new ArrayList(); + List 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 vlanSearch = _vlanDao.createSearchBuilder(); vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ); diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java old mode 100644 new mode 100755 index 75d8bc176eb..e9627d7a410 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -89,7 +89,9 @@ import com.cloud.offerings.NetworkOfferingServiceMapVO; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; +import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.user.Account; +import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.AdapterBase; @@ -181,7 +183,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { NicSecondaryIpDao _nicSecondaryIpDao; @Inject ApplicationLoadBalancerRuleDao _appLbRuleDao; - + @Inject + private ProjectAccountDao _projectAccountDao; private final HashMap _systemNetworks = new HashMap(5); static Long _privateOfferingId = null; @@ -1013,7 +1016,10 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { Set supportedProviders = new HashSet(); if (service != null) { - supportedProviders.addAll(s_serviceToImplementedProvidersMap.get(service)); + List providers = s_serviceToImplementedProvidersMap.get(service); + if (providers != null && !providers.isEmpty()) { + supportedProviders.addAll(providers); + } } else { for (List pList : s_serviceToImplementedProvidersMap.values()) { supportedProviders.addAll(pList); @@ -1475,10 +1481,20 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { public void checkNetworkPermissions(Account owner, Network network) { // Perform account permission check if (network.getGuestType() != Network.GuestType.Shared) { - List networkMap = _networksDao.listBy(owner.getId(), network.getId()); - if (networkMap == null || networkMap.isEmpty()) { - throw new PermissionDeniedException("Unable to use network with id= " + network.getUuid() + ", permission denied"); + AccountVO networkOwner = _accountDao.findById(network.getAccountId()); + if(networkOwner == null) + throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", network does not have an owner"); + if(owner.getType() != Account.ACCOUNT_TYPE_PROJECT && networkOwner.getType() == Account.ACCOUNT_TYPE_PROJECT){ + if(!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())){ + throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + } + }else{ + List networkMap = _networksDao.listBy(owner.getId(), network.getId()); + if (networkMap == null || networkMap.isEmpty()) { + throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + } } + } else { if (!isNetworkAvailableInDomain(network.getId(), owner.getDomainId())) { throw new PermissionDeniedException("Shared network id=" + network.getUuid() + " is not available in domain id=" + owner.getDomainId()); diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index c8fa66e1843..c8550cddd77 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -733,15 +733,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"); diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 82bca5194bf..c9c3f9c3722 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -1181,29 +1181,17 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - ClusterDetailsVO memory_detail = _clusterDetailsDao.findDetail(cluster.getId(),"memoryOvercommitRatio"); - if( memory_detail == null){ - if (memoryovercommitratio.compareTo(1f) > 0){ - memory_detail = new ClusterDetailsVO(cluster.getId(),"memoryOvercommitRatio",Float.toString(memoryovercommitratio)); - _clusterDetailsDao.persist(memory_detail); - } - } - else { + if (memoryovercommitratio != null) { + ClusterDetailsVO memory_detail = _clusterDetailsDao.findDetail(cluster.getId(),"memoryOvercommitRatio"); memory_detail.setValue(Float.toString(memoryovercommitratio)); _clusterDetailsDao.update(memory_detail.getId(),memory_detail); } - ClusterDetailsVO cpu_detail = _clusterDetailsDao.findDetail(cluster.getId(),"cpuOvercommitRatio"); - if( cpu_detail == null){ - if (cpuovercommitratio.compareTo(1f) > 0){ - cpu_detail = new ClusterDetailsVO(cluster.getId(),"cpuOvercommitRatio",Float.toString(cpuovercommitratio)); - _clusterDetailsDao.persist(cpu_detail); - } - } - else { + if (cpuovercommitratio != null) { + ClusterDetailsVO cpu_detail = _clusterDetailsDao.findDetail(cluster.getId(),"cpuOvercommitRatio"); cpu_detail.setValue(Float.toString(cpuovercommitratio)); _clusterDetailsDao.update(cpu_detail.getId(),cpu_detail); - } + } if (doUpdate) { diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 8dc27aebae8..a505cf25032 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -169,8 +169,10 @@ import org.apache.cloudstack.api.command.admin.user.LockUserCmd; import org.apache.cloudstack.api.command.admin.user.RegisterCmd; import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; 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.ListVlanIpRangesCmd; +import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; @@ -2343,6 +2345,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); diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index fe714c530b9..e74c49124f7 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."); } } diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java index a98ae0ff7bd..f2951bc8d91 100644 --- a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java @@ -41,7 +41,7 @@ public interface AffinityGroupVMMapDao extends GenericDao findByVmIdType(long instanceId, String type); void updateMap(Long vmId, List affinityGroupIds); } diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java index abc2a2bd59c..e03e73c6320 100644 --- a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java @@ -140,11 +140,11 @@ public class AffinityGroupVMMapDaoImpl extends GenericDaoBase findByVmIdType(long instanceId, String type) { SearchCriteria sc = ListByVmIdType.create(); sc.setParameters("instanceId", instanceId); sc.setJoinParameters("groupSearch", "type", type); - return findOneBy(sc); + return listBy(sc); } @Override diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java new file mode 100755 index 00000000000..ee98d53c922 --- /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 ipAddressList = new ArrayList(); + 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 accountVlanMaps = new ArrayList(); + 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 ipAddressList = new ArrayList(); + 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 ipAddressList = new ArrayList(); + 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 ipAddressList = new ArrayList(); + 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 accountVlanMaps = new ArrayList(); + 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 accountVlanMaps = new ArrayList(); + 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 ipAddressList = new ArrayList(); + 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; + } + } +} 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 b0063fa2e2e..a03e361d8c1 --- 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; + } } diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java b/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java index c6a0755744c..fb294697cc6 100644 --- a/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java +++ b/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java @@ -42,6 +42,7 @@ import com.cloud.dc.dao.AccountVlanMapDaoImpl; import com.cloud.dc.dao.ClusterDaoImpl; import com.cloud.dc.dao.DataCenterDaoImpl; import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; +import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao; import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl; import com.cloud.dc.dao.DataCenterVnetDaoImpl; import com.cloud.dc.dao.DcDetailsDaoImpl; @@ -51,6 +52,7 @@ import com.cloud.dc.dao.PodVlanMapDaoImpl; import com.cloud.dc.dao.VlanDaoImpl; import com.cloud.domain.dao.DomainDaoImpl; import com.cloud.event.EventUtils; +import com.cloud.event.dao.EventDao; import com.cloud.event.dao.EventDaoImpl; import com.cloud.event.dao.UsageEventDaoImpl; import com.cloud.host.dao.HostDaoImpl; @@ -122,15 +124,15 @@ import com.cloud.vm.dao.VMInstanceDaoImpl; UserAccountJoinDaoImpl.class, CapacityDaoImpl.class, SnapshotDaoImpl.class, HostDaoImpl.class, VMInstanceDaoImpl.class, HostTransferMapDaoImpl.class, PortForwardingRulesDaoImpl.class, PrivateIpDaoImpl.class, UsageEventDaoImpl.class, PodVlanMapDaoImpl.class, DiskOfferingDaoImpl.class, - DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class, + DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DcDetailsDaoImpl.class, NicSecondaryIpDaoImpl.class, UserIpv6AddressDaoImpl.class, S3DaoImpl.class, UserDaoImpl.class, NicDaoImpl.class, NetworkDomainDaoImpl.class, HostDetailsDaoImpl.class, HostTagsDaoImpl.class, ClusterDaoImpl.class, FirewallRulesDaoImpl.class, FirewallRulesCidrsDaoImpl.class, PhysicalNetworkDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class, PhysicalNetworkServiceProviderDaoImpl.class, LoadBalancerDaoImpl.class, NetworkServiceMapDaoImpl.class, PrimaryDataStoreDaoImpl.class, StoragePoolDetailsDaoImpl.class, AffinityGroupServiceImpl.class, - ComponentContext.class, AffinityGroupProcessor.class, UserVmVO.class, EventUtils.class, UserVmVO.class, - EventDaoImpl.class }, includeFilters = { @Filter(value = AffinityApiTestConfiguration.Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false) + ComponentContext.class, AffinityGroupProcessor.class, UserVmVO.class, EventUtils.class, UserVmVO.class + }, includeFilters = { @Filter(value = AffinityApiTestConfiguration.Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false) public class AffinityApiTestConfiguration { @Bean @@ -308,6 +310,11 @@ public class AffinityApiTestConfiguration { public NetworkOfferingDao networkOfferingDao() { return Mockito.mock(NetworkOfferingDao.class); } + + @Bean + public EventDao eventDao() { + return Mockito.mock(EventDao.class); + } @Bean public NetworkDao networkDao() { @@ -319,6 +326,11 @@ public class AffinityApiTestConfiguration { return Mockito.mock(NetworkOfferingServiceMapDao.class); } + @Bean + public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() { + return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); + } + public static class Library implements TypeFilter { @Override diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java index 86cf0174579..a5e6d15bf0b 100644 --- a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java +++ b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java @@ -21,9 +21,7 @@ import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.*; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -31,19 +29,20 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.cloud.event.EventUtils; +import com.cloud.event.EventVO; +import com.cloud.event.dao.EventDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceInUseException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.AccountManagerImpl; import com.cloud.user.AccountVO; import com.cloud.user.UserContext; -import com.cloud.user.UserContextInitializer; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; import com.cloud.vm.UserVmVO; @@ -75,11 +74,17 @@ public class AffinityApiUnitTest { @Inject AffinityGroupVMMapDao _affinityGroupVMMapDao; + @Inject + AffinityGroupDao _affinityGroupDao; + @Inject EventUtils _eventUtils; @Inject AccountDao _accountDao; + + @Inject + EventDao _eventDao; private static long domainId = 5L; @@ -102,6 +107,14 @@ public class AffinityApiUnitTest { when(_acctMgr.finalizeOwner((Account) anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct); when(_processor.getType()).thenReturn("mock"); when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct); + + AffinityGroupVO group = new AffinityGroupVO("group1", "mock", "mock group", domainId, 200L); + Mockito.when(_affinityGroupDao.persist(Mockito.any(AffinityGroupVO.class))).thenReturn(group); + Mockito.when(_affinityGroupDao.findById(Mockito.anyLong())).thenReturn(group); + Mockito.when(_affinityGroupDao.findByAccountAndName(Mockito.anyLong(), Mockito.anyString())).thenReturn(group); + Mockito.when(_affinityGroupDao.lockRow(Mockito.anyLong(), anyBoolean())).thenReturn(group); + Mockito.when(_affinityGroupDao.expunge(Mockito.anyLong())).thenReturn(true); + Mockito.when(_eventDao.persist(Mockito.any(EventVO.class))).thenReturn(new EventVO()); } @Test diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java index 895a5d4416d..f1163ef35ee 100644 --- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java +++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java @@ -41,6 +41,7 @@ import com.cloud.dc.dao.AccountVlanMapDaoImpl; import com.cloud.dc.dao.ClusterDaoImpl; import com.cloud.dc.dao.DataCenterDaoImpl; import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; +import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao; import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl; import com.cloud.dc.dao.DataCenterVnetDaoImpl; import com.cloud.dc.dao.DcDetailsDaoImpl; @@ -135,7 +136,6 @@ import com.cloud.vm.dao.VMInstanceDaoImpl; DiskOfferingDaoImpl.class, DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, - DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DcDetailsDaoImpl.class, @@ -319,6 +319,11 @@ public class ChildTestConfiguration { return Mockito.mock(NetworkOfferingServiceMapDao.class); } + @Bean + public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() { + return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); + } + public static class Library implements TypeFilter { @Override diff --git a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java index 67fae3349c1..cbb6c00e397 100644 --- a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java +++ b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java @@ -49,7 +49,6 @@ import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.UserContext; -import com.cloud.user.UserContextInitializer; import com.cloud.user.UserVO; import com.cloud.utils.component.ComponentContext; diff --git a/test/integration/smoke/test_ScaleVm.py b/test/integration/smoke/test_ScaleVm.py index 710d2add7b6..64fe4dc9aa4 100644 --- a/test/integration/smoke/test_ScaleVm.py +++ b/test/integration/smoke/test_ScaleVm.py @@ -91,7 +91,7 @@ class Services: "sleep": 60, "timeout": 10, #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', + "ostype": 'CentOS 5.3 (64-bit)', # CentOS 5.3 (64-bit) } @@ -164,7 +164,7 @@ class TestScaleVm(cloudstackTestCase): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "basic", "multicluster", "storagemotion", "xenserver"]) + @attr(tags = ["xenserver", "advanced", "basic"]) def test_01_scale_vm(self): """Test scale virtual machine """ diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py new file mode 100644 index 00000000000..a7aad6b795c --- /dev/null +++ b/test/integration/smoke/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 = ["simulator", "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 + diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 2d5292b8426..5403adb99df 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -83,6 +83,7 @@ known_categories = { 'Configuration': 'Configuration', 'Capabilities': 'Configuration', 'Pod': 'Pod', + 'PublicIpRange': 'Network', 'Zone': 'Zone', 'NetworkOffering': 'Network Offering', 'NetworkACL': 'Network ACL', diff --git a/tools/build/build_docs.sh b/tools/build/build_docs.sh index 8bb63e30e87..62617a3df9d 100755 --- a/tools/build/build_docs.sh +++ b/tools/build/build_docs.sh @@ -19,22 +19,25 @@ sourcedir=~/incubator-cloudstack/ common_content_dir=/usr/share/publican/Common_Content publican_path=/usr/bin/publican +output_format="html,pdf" usage(){ echo "usage: $0 [-s source dir] [-c publican common content] [-p path to publican]" echo " -s sets the source directory (defaults to $sourcedir)" echo " -c sets the public common content directory (defaults to $common_content_dir)" echo " -p sets the path to the publican binary (defaults to $publican_path)" + echo " -f sets the output format (defaults to $output_format)" echo " -h" } -while getopts v:s:c:p:h opt +while getopts v:s:c:p:f:h opt do case "$opt" in v) version="$OPTARG";; s) sourcedir="$OPTARG";; c) common_content_dir="$OPTARG";; p) publican_path="$OPTARG";; + f) output_format="$OPTARG";; h) usage exit 0;; \?) @@ -48,8 +51,13 @@ if [ ! -x "$publican_path" ]; then exit 1 fi +if [ ! -d "$sourcedir/docs" ]; then + echo "$sourcedir/docs doesn't seem to exist? Maybe set -s?" + exit 1 +fi + cd $sourcedir/docs cp -R /usr/share/publican/Common_Content . ln -s $sourcedir/docs/publican-cloudstack Common_Content/cloudstack -publican build --config=publican-installation.cfg --formats html,pdf --langs en-US --common_content=$sourcedir/docs/Common_Content +publican build --config=publican-installation.cfg --formats $output_format --langs en-US --common_content=$sourcedir/docs/Common_Content rm -r Common_Content \ No newline at end of file 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 d27ab3b2903..3df68ab7853 --- 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""" diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index 10057a62a4a..ec5e21b7d4c 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -55,6 +55,12 @@ actions: { add: { label: 'label.add.region', + preFilter: function(args) { + if(isAdmin()) + return true; + else + return false; + }, messages: { notification: function() { return 'label.add.region'; } }, @@ -98,10 +104,9 @@ $.ajax({ url: createURL('listRegions&listAll=true'), success: function(json) { - var regions = json.listregionsresponse.region - - args.response.success({ - data: regions ? regions : [] + var items = json.listregionsresponse.region; + args.response.success({ + data: items }); }, error: function(json) { @@ -193,6 +198,7 @@ var region = json.listregionsresponse.region args.response.success({ + actionFilter: regionActionfilter, data: region ? region[0] : {} }); }, @@ -382,4 +388,14 @@ } } }; + + var regionActionfilter = function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("edit"); + allowedActions.push("remove"); + } + return allowedActions; + } + })(cloudStack);