diff --git a/api/src/com/cloud/async/AsyncJob.java b/api/src/com/cloud/async/AsyncJob.java index ccdc40620b7..47f9b574e23 100644 --- a/api/src/com/cloud/async/AsyncJob.java +++ b/api/src/com/cloud/async/AsyncJob.java @@ -35,6 +35,7 @@ public interface AsyncJob extends Identity, InternalIdentity { Host, StoragePool, IpAddress, + PortableIpAddress, SecurityGroup, PhysicalNetwork, TrafficType, diff --git a/api/src/com/cloud/configuration/ConfigurationService.java b/api/src/com/cloud/configuration/ConfigurationService.java index fdbd9d6bb0b..381fcad95cc 100644 --- a/api/src/com/cloud/configuration/ConfigurationService.java +++ b/api/src/com/cloud/configuration/ConfigurationService.java @@ -39,6 +39,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd; 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.region.CreatePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.DeletePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.ListPortableIpRangesCmd; 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; @@ -56,6 +59,8 @@ import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; public interface ConfigurationService { @@ -278,4 +283,12 @@ public interface ConfigurationService { * @return */ boolean isOfferingForVpc(NetworkOffering offering); + + PortableIpRange createPortableIpRange(CreatePortableIpRangeCmd cmd) throws ConcurrentOperationException; + + boolean deletePortableIpRange(DeletePortableIpRangeCmd cmd); + + List listPortableIpRanges(ListPortableIpRangesCmd cmd); + + List listPortableIps(long id); } diff --git a/api/src/com/cloud/deploy/DeploymentPlanner.java b/api/src/com/cloud/deploy/DeploymentPlanner.java index eb56a591f6b..769da39f3ff 100644 --- a/api/src/com/cloud/deploy/DeploymentPlanner.java +++ b/api/src/com/cloud/deploy/DeploymentPlanner.java @@ -213,6 +213,13 @@ public interface DeploymentPlanner extends Adapter { _hostIds.add(hostId); } + public void addHostList(Collection hostList) { + if (_hostIds == null) { + _hostIds = new HashSet(); + } + _hostIds.addAll(hostList); + } + public boolean shouldAvoid(Host host) { if (_dcIds != null && _dcIds.contains(host.getDataCenterId())) { return true; diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index ee7f5b7d89f..fcac8e8e65d 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -92,6 +92,8 @@ public class EventTypes { public static final String EVENT_PROXY_STOP = "PROXY.STOP"; public static final String EVENT_PROXY_REBOOT = "PROXY.REBOOT"; public static final String EVENT_PROXY_HA = "PROXY.HA"; + public static final String EVENT_PROXY_SCALE = "PROXY.SCALE"; + // VNC Console Events public static final String EVENT_VNC_CONNECT = "VNC.CONNECT"; @@ -100,6 +102,8 @@ public class EventTypes { // Network Events public static final String EVENT_NET_IP_ASSIGN = "NET.IPASSIGN"; public static final String EVENT_NET_IP_RELEASE = "NET.IPRELEASE"; + public static final String EVENT_PORTABLE_IP_ASSIGN = "PORTABLE.IPASSIGN"; + public static final String EVENT_PORTABLE_IP_RELEASE = "PORTABLEIPRELEASE"; public static final String EVENT_NET_RULE_ADD = "NET.RULEADD"; public static final String EVENT_NET_RULE_DELETE = "NET.RULEDELETE"; public static final String EVENT_NET_RULE_MODIFY = "NET.RULEMODIFY"; @@ -213,6 +217,7 @@ public class EventTypes { public static final String EVENT_SSVM_STOP = "SSVM.STOP"; public static final String EVENT_SSVM_REBOOT = "SSVM.REBOOT"; public static final String EVENT_SSVM_HA = "SSVM.HA"; + public static final String EVENT_SSVM_SCALE = "SSVM.SCALE"; // Service Offerings public static final String EVENT_SERVICE_OFFERING_CREATE = "SERVICE.OFFERING.CREATE"; @@ -429,6 +434,9 @@ public class EventTypes { public static final String EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE = "GUESTVLANRANGE.RELEASE"; + public static final String EVENT_PORTABLE_IP_RANGE_CREATE = "PORTABLE.IP.RANGE.CREATE"; + public static final String EVENT_PORTABLE_IP_RANGE_DELETE = "PORTABLE.IP.RANGE.DELETE"; + static { // TODO: need a way to force author adding event types to declare the entity details as well, with out braking diff --git a/api/src/com/cloud/exception/InsufficientServerCapacityException.java b/api/src/com/cloud/exception/InsufficientServerCapacityException.java index af34e579943..8f889fee4c5 100755 --- a/api/src/com/cloud/exception/InsufficientServerCapacityException.java +++ b/api/src/com/cloud/exception/InsufficientServerCapacityException.java @@ -27,6 +27,8 @@ public class InsufficientServerCapacityException extends InsufficientCapacityExc private static final long serialVersionUID = SerialVersionUID.InsufficientServerCapacityException; + private boolean affinityGroupsApplied = false; + public InsufficientServerCapacityException(String msg, Long clusterId) { this(msg, Cluster.class, clusterId); } @@ -34,4 +36,13 @@ public class InsufficientServerCapacityException extends InsufficientCapacityExc public InsufficientServerCapacityException(String msg, Class scope, Long id) { super(msg, scope, id); } + + public InsufficientServerCapacityException(String msg, Class scope, Long id, boolean affinityGroupsApplied) { + super(msg, scope, id); + this.affinityGroupsApplied = affinityGroupsApplied; + } + + public boolean isAffinityApplied() { + return affinityGroupsApplied; + } } diff --git a/api/src/com/cloud/network/IpAddress.java b/api/src/com/cloud/network/IpAddress.java index c48e8b97ca8..de11a6de79b 100644 --- a/api/src/com/cloud/network/IpAddress.java +++ b/api/src/com/cloud/network/IpAddress.java @@ -81,7 +81,9 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity Long getVpcId(); String getVmIp(); - + + boolean isPortable(); + Long getNetworkId(); } diff --git a/api/src/com/cloud/network/NetworkMigrationResponder.java b/api/src/com/cloud/network/NetworkMigrationResponder.java new file mode 100644 index 00000000000..6283cc54128 --- /dev/null +++ b/api/src/com/cloud/network/NetworkMigrationResponder.java @@ -0,0 +1,70 @@ +// 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.network; + +import com.cloud.deploy.DeployDestination; +import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +/** + * NetworkGuru and NetworkElements that implement this interface + * will be called during Virtual Machine migration. + */ +public interface NetworkMigrationResponder { + /** + * Prepare for migration. + * + * This method will be called per nic before the vm migration. + * @param nic + * @param network + * @param vm + * @param dest + * @param context + * @return true when operation was successful. + */ + public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context); + + /** + * Cancel for migration preparation. + * + * This method will be called per nic when the entire vm migration + * process failed and need to release the resouces that was + * allocated at the migration preparation. + * @param nic destination nic + * @param network destination network + * @param vm destination vm profile + * @param src The context nic migrates from. + * @param dst The context nic migrates to. + */ + public void rollbackMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst); + + /** + * Commit the migration resource. + * + * This method will be called per nic when the entire vm migration + * process was successful. This is useful to release the resource of + * source deployment where vm has left. + * @param nic source nic + * @param network source network + * @param vm source vm profile + * @param src the context nic migrates from. + * @param dst the context nic migrates to. + */ + public void commitMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst); +} diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 2e50c53d8bb..59702a2864e 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -52,6 +52,11 @@ public interface NetworkService { boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; + IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, + InsufficientAddressCapacityException, ConcurrentOperationException; + + boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; + Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java index d637da638ac..b554719f188 100644 --- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java +++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java @@ -32,7 +32,7 @@ public interface RemoteAccessVpnService { RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, long networkId) throws NetworkRuleConflictException; - void destroyRemoteAccessVpn(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; + void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException; VpnUser addVpnUser(long vpnOwnerId, String userName, String password); diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index 518a6480c03..3ff78424e8a 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.cloud.exception.*; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; @@ -34,11 +35,7 @@ import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.ListAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.ListCapacityCmd; import org.apache.cloudstack.api.command.admin.resource.UploadCustomCertificateCmd; -import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; -import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; -import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; -import org.apache.cloudstack.api.command.admin.systemvm.StopSystemVmCmd; -import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.*; import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd; @@ -64,10 +61,6 @@ import com.cloud.configuration.Configuration; import com.cloud.dc.Pod; import com.cloud.dc.Vlan; import com.cloud.domain.Domain; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InternalErrorException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.Host; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorCapabilities; @@ -391,4 +384,5 @@ public interface ManagementService { List listDeploymentPlanners(); + VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException, ConcurrentOperationException; } diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java index 0a0660ad493..7d459b99a9e 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -461,6 +461,6 @@ public interface UserVmService { UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException; - boolean upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; + UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 8d7739c13e1..1e9435f6a8e 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -114,6 +114,7 @@ public class ApiConstants { public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; public static final String IS_EXTRACTABLE = "isextractable"; public static final String IS_FEATURED = "isfeatured"; + public static final String IS_PORTABLE = "isportable"; public static final String IS_PUBLIC = "ispublic"; public static final String IS_PERSISTENT = "ispersistent"; public static final String IS_READY = "isready"; @@ -158,6 +159,7 @@ public class ApiConstants { public static final String POLICY_ID = "policyid"; public static final String PORT = "port"; public static final String PORTAL = "portal"; + public static final String PORTABLE_IP_ADDRESS = "portableipaddress"; public static final String PORT_FORWARDING_SERVICE_ID = "portforwardingserviceid"; public static final String PRIVATE_INTERFACE = "privateinterface"; public static final String PRIVATE_IP = "privateip"; @@ -312,6 +314,7 @@ public class ApiConstants { public static final String ACCEPT = "accept"; public static final String SORT_KEY = "sortkey"; public static final String ACCOUNT_DETAILS = "accountdetails"; + public static final String SERVICE_OFFERING_DETAILS = "serviceofferingdetails"; public static final String SERVICE_PROVIDER_LIST = "serviceproviderlist"; public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist"; public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability"; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index dd2bd58a6d2..8cc9eaf785f 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -36,6 +36,8 @@ import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; import org.apache.cloudstack.api.response.*; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.usage.Usage; import com.cloud.async.AsyncJob; @@ -363,7 +365,12 @@ public interface ResponseGenerator { Long getAffinityGroupId(String name, long entityOwnerId); + PortableIpRangeResponse createPortableIPRangeResponse(PortableIpRange range); + + PortableIpResponse createPortableIPResponse(PortableIp portableIp); + InternalLoadBalancerElementResponse createInternalLbElementResponse(VirtualRouterProvider result); IsolationMethodResponse createIsolationMethodResponse(IsolationType method); + } diff --git a/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java index d55ccd7dd11..c6ca9bc673b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java @@ -17,13 +17,11 @@ package org.apache.cloudstack.api.command.admin.cluster; -import java.util.ArrayList; -import java.util.List; - +import com.cloud.exception.DiscoveryException; import com.cloud.exception.InvalidParameterValueException; -import org.apache.cloudstack.api.*; -import org.apache.log4j.Logger; - +import com.cloud.exception.ResourceInUseException; +import com.cloud.org.Cluster; +import com.cloud.user.Account; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -36,10 +34,8 @@ import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; -import com.cloud.exception.DiscoveryException; -import com.cloud.exception.ResourceInUseException; -import com.cloud.org.Cluster; -import com.cloud.user.Account; +import java.util.ArrayList; +import java.util.List; @APICommand(name = "addCluster", description="Adds a new cluster", responseObject=ClusterResponse.class) public class AddClusterCmd extends BaseCmd { @@ -86,10 +82,10 @@ public class AddClusterCmd extends BaseCmd { private String vsmipaddress; @Parameter (name=ApiConstants.CPU_OVERCOMMIT_RATIO, type = CommandType.STRING, required = false , description = "value of the cpu overcommit ratio, defaults to 1") - private String cpuovercommitRatio; + private String cpuOvercommitRatio; - @Parameter(name = ApiConstants.MEMORY_OVERCOMMIT_RATIO, type = CommandType.STRING, required = false ,description = "value of the default ram overcommit ratio, defaults to 1") - private String memoryovercommitratio; + @Parameter(name = ApiConstants.MEMORY_OVERCOMMIT_RATIO, type = CommandType.STRING, required = false, description = "value of the default memory overcommit ratio, defaults to 1") + private String memoryOvercommitRatio; @Parameter(name = ApiConstants.VSWITCH_TYPE_GUEST_TRAFFIC, type = CommandType.STRING, required = false, description = "Type of virtual switch used for guest traffic in the cluster. Allowed values are, vmwaresvs (for VMware standard vSwitch) and vmwaredvs (for VMware distributed vSwitch)") private String vSwitchTypeGuestTraffic; @@ -186,15 +182,15 @@ public class AddClusterCmd extends BaseCmd { } public Float getCpuOvercommitRatio (){ - if(cpuovercommitRatio != null){ - return Float.parseFloat(cpuovercommitRatio); + if(cpuOvercommitRatio != null){ + return Float.parseFloat(cpuOvercommitRatio); } return 1.0f; } - public Float getMemoryOvercommitRaito (){ - if (memoryovercommitratio != null){ - return Float.parseFloat(memoryovercommitratio); + public Float getMemoryOvercommitRatio(){ + if (memoryOvercommitRatio != null){ + return Float.parseFloat(memoryOvercommitRatio); } return 1.0f; } @@ -202,8 +198,8 @@ public class AddClusterCmd extends BaseCmd { @Override public void execute(){ try { - if ((getMemoryOvercommitRaito().compareTo(1f) < 0) | (getCpuOvercommitRatio().compareTo(1f) < 0)) { - throw new InvalidParameterValueException("Cpu and ram overcommit ratios should not be less than 1"); + if (getMemoryOvercommitRatio().compareTo(1f) < 0 || getCpuOvercommitRatio().compareTo(1f) < 0) { + throw new InvalidParameterValueException("cpu and memory overcommit ratios should be greater than or equal to one"); } List result = _resourceService.discoverCluster(this); ListResponse response = new ListResponse(); 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 c5130587ec5..a14f9055211 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 @@ -57,7 +57,7 @@ public class UpdateClusterCmd extends BaseCmd { @Parameter(name=ApiConstants.CPU_OVERCOMMIT_RATIO, type = CommandType.STRING, description = "Value of cpu overcommit ratio") private String cpuovercommitratio; - @Parameter(name=ApiConstants.MEMORY_OVERCOMMIT_RATIO, type = CommandType.STRING, description = "Value of ram overcommit ratio") + @Parameter(name=ApiConstants.MEMORY_OVERCOMMIT_RATIO, type = CommandType.STRING, description = "Value of memory overcommit ratio") private String memoryovercommitratio; @@ -129,13 +129,13 @@ public class UpdateClusterCmd extends BaseCmd { } if (getMemoryOvercommitRaito() !=null){ if ((getMemoryOvercommitRaito().compareTo(1f) < 0)) { - throw new InvalidParameterValueException("Memory overcommit ratio should be greater than or equal to one"); + throw new InvalidParameterValueException("Memory overcommit ratio should be greater than or equal to one"); } } if (getCpuOvercommitRatio() !=null){ if (getCpuOvercommitRatio().compareTo(1f) < 0) { - throw new InvalidParameterValueException("Cpu overcommit ratio should be greater than or equal to one"); + throw new InvalidParameterValueException("Cpu overcommit ratio should be greater than or equal to one"); } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java index e6e45cc7246..b2d77b85dd2 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java @@ -45,7 +45,7 @@ public class FindHostsForMigrationCmd extends BaseListCmd { ///////////////////////////////////////////////////// @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = UserVmResponse.class, - required=false, description="find hosts to which this VM can be migrated and flag the hosts with enough " + + required=true, description="find hosts to which this VM can be migrated and flag the hosts with enough " + "CPU/RAM to host the VM") private Long virtualMachineId; diff --git a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index c155b706fc0..4c54a4e5ec6 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -16,6 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.admin.offering; +import java.util.Collection; +import java.util.Map; + import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -87,6 +90,9 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "The deployment planner heuristics used to deploy a VM of this offering. If null, value of global config vm.deployment.planner is used") private String deploymentPlanner; + @Parameter(name = ApiConstants.SERVICE_OFFERING_DETAILS, type = CommandType.MAP, description = "details for planner, used to store specific parameters") + private Map details; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -155,6 +161,16 @@ public class CreateServiceOfferingCmd extends BaseCmd { return deploymentPlanner; } + public Map getDetails() { + if (details == null || details.isEmpty()) { + return null; + } + + Collection paramsCollection = details.values(); + Map params = (Map)(paramsCollection.toArray())[0]; + return params; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java new file mode 100644 index 00000000000..78e4c94ed4c --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java @@ -0,0 +1,156 @@ +// 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.region; + +import javax.inject.Inject; + +import com.cloud.async.AsyncJob; +import com.cloud.dc.Vlan; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceAllocationException; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCreateCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.PortableIpRangeResponse; +import org.apache.cloudstack.api.response.RegionResponse; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; +import org.apache.cloudstack.region.PortableIpRange; +import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.region.RegionService; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; + +@APICommand(name = "createPortableIpRange", responseObject=PortableIpRangeResponse.class, description="adds a range of portable public IP's to a region", since="4.2.0") +public class CreatePortableIpRangeCmd extends BaseAsyncCreateCmd { + + public static final Logger s_logger = Logger.getLogger(CreatePortableIpRangeCmd.class.getName()); + + private static final String s_name = "createportableiprangeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, entityType = RegionResponse.class, required=true, description="Id of the Region") + private Integer regionId; + + @Parameter(name=ApiConstants.START_IP, type=CommandType.STRING, required=true, description="the beginning IP address in the portable IP range") + private String startIp; + + @Parameter(name=ApiConstants.END_IP, type=CommandType.STRING, required=true, description="the ending IP address in the portable IP range") + private String endIp; + + @Parameter(name=ApiConstants.GATEWAY, type=CommandType.STRING, required=true, description="the gateway for the portable IP range") + private String gateway; + + @Parameter(name=ApiConstants.NETMASK, type=CommandType.STRING, required=true, description="the netmask of the portable IP range") + private String netmask; + + @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="VLAN id, if not specified defaulted to untagged") + private String vlan; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Integer getRegionId() { + return regionId; + } + + public String getStartIp() { + return startIp; + } + + public String getEndIp() { + return endIp; + } + + public String getVlan() { + return vlan; + } + + public String getGateway() { + return gateway; + } + + public String getNetmask() { + return netmask; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + PortableIpRange portableIpRange = _entityMgr.findById(PortableIpRange.class, getEntityId()); + PortableIpRangeResponse response = null; + if (portableIpRange != null) { + response = _responseGenerator.createPortableIPRangeResponse(portableIpRange); + } + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public void create() throws ResourceAllocationException { + try { + PortableIpRange portableIpRange = _configService.createPortableIpRange(this); + if (portableIpRange != null) { + this.setEntityId(portableIpRange.getId()); + this.setEntityUuid(portableIpRange.getUuid()); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create portable public IP range"); + } + } catch (ConcurrentOperationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_PORTABLE_IP_RANGE_CREATE; + } + + @Override + public String getEventDescription() { + return "creating a portable public ip range in region: " + getRegionId(); + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.PortableIpAddress; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java new file mode 100644 index 00000000000..856e8efa210 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java @@ -0,0 +1,93 @@ +// 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.region; + +import javax.inject.Inject; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.PortableIpRangeResponse; +import org.apache.cloudstack.api.response.RegionResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.region.RegionService; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; + +@APICommand(name = "deletePortableIpRange", description="deletes a range of portable public IP's associated with a region", responseObject=SuccessResponse.class) +public class DeletePortableIpRangeCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DeletePortableIpRangeCmd.class.getName()); + + private static final String s_name = "deleteportablepublicipresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, required=true, entityType = PortableIpRangeResponse.class, description="Id of the portable 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.deletePortableIpRange(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete portable ip range"); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_PORTABLE_IP_RANGE_DELETE; + } + + @Override + public String getEventDescription() { + return "deleting a portable public ip range"; + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.PortableIpAddress; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java new file mode 100644 index 00000000000..75bcce00acf --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java @@ -0,0 +1,109 @@ +// 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.region; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.PortableIpRangeResponse; +import org.apache.cloudstack.api.response.PortableIpResponse; +import org.apache.cloudstack.api.response.RegionResponse; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; +import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.region.RegionService; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; + +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = "listPortableIpRanges", description="list portable IP ranges", responseObject=PortableIpRangeResponse.class) +public class ListPortableIpRangesCmd extends BaseListCmd { + + public static final Logger s_logger = Logger.getLogger(ListPortableIpRangesCmd.class.getName()); + + private static final String s_name = "listportableipresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, required=false, description="Id of a Region") + private Integer regionId; + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, required=false, entityType = PortableIpRangeResponse.class, description="Id of the portable ip range") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Integer getRegionIdId() { + return regionId; + } + + public Long getPortableIpRangeId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + ListResponse response = new ListResponse(); + List responses = new ArrayList(); + List portableIpRanges = new ArrayList(); + + portableIpRanges = _configService.listPortableIpRanges(this); + if (portableIpRanges != null && !portableIpRanges.isEmpty()) { + for (PortableIpRange range : portableIpRanges) { + PortableIpRangeResponse rangeResponse = _responseGenerator.createPortableIPRangeResponse(range); + + List portableIps = _configService.listPortableIps(range.getId()); + if (portableIps != null && !portableIps.isEmpty()) { + List portableIpResponses = new ArrayList(); + for (PortableIp portableIP: portableIps) { + PortableIpResponse portableIpresponse = _responseGenerator.createPortableIPResponse(portableIP); + portableIpResponses.add(portableIpresponse); + } + rangeResponse.setPortableIpResponses(portableIpResponses); + } + + rangeResponse.setObjectName("portableiprange"); + responses.add(rangeResponse); + } + } + response.setResponses(responses, portableIpRanges.size()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java new file mode 100644 index 00000000000..a077e246a46 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java @@ -0,0 +1,131 @@ +// 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.systemvm; + +import com.cloud.event.EventTypes; +import com.cloud.exception.*; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.SystemVmResponse; +import org.apache.log4j.Logger; + +import com.cloud.offering.ServiceOffering; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.vm.VirtualMachine; + +@APICommand(name = "scaleSystemVm", responseObject=SystemVmResponse.class, description="Scale the service offering for a system vm (console proxy or secondary storage). " + + "The system vm must be in a \"Stopped\" state for " + + "this command to take effect.") +public class ScaleSystemVMCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); + private static final String s_name = "changeserviceforsystemvmresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=SystemVmResponse.class, + required=true, description="The ID of the system vm") + private Long id; + + @Parameter(name=ApiConstants.SERVICE_OFFERING_ID, type=CommandType.UUID, entityType=ServiceOfferingResponse.class, + required=true, description="the service offering ID to apply to the system vm") + private Long serviceOfferingId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public Long getServiceOfferingId() { + return serviceOfferingId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = UserContext.current().getCaller(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public void execute(){ + UserContext.current().setEventDetails("SystemVm Id: "+getId()); + + ServiceOffering serviceOffering = _configService.getServiceOffering(serviceOfferingId); + if (serviceOffering == null) { + throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId); + } + + VirtualMachine result = null; + try { + result = _mgr.upgradeSystemVM(this); + } catch (ResourceUnavailableException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); + } catch (ConcurrentOperationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } catch (ManagementServerException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } catch (VirtualMachineMigrationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } + if (result != null) { + SystemVmResponse response = _responseGenerator.createSystemVmResponse(result); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to scale system vm"); + } + } + + @Override + public String getEventType() { + VirtualMachine.Type type = _mgr.findSystemVMTypeById(getId()); + if(type == VirtualMachine.Type.ConsoleProxy){ + return EventTypes.EVENT_PROXY_SCALE; + } + else{ + return EventTypes.EVENT_SSVM_SCALE; + } + } + + @Override + public String getEventDescription() { + return "scaling system vm: " + getId() + " to service offering: " + getServiceOfferingId(); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index 28fbae4437a..f37e82060fb 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -66,6 +66,14 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { "be associated with") private Long vpcId; + @Parameter(name=ApiConstants.IS_PORTABLE, type = BaseCmd.CommandType.BOOLEAN, description = "should be set to true " + + "if public IP is required to be transferable across zones, if not specified defaults to false") + private Boolean isPortable; + + @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, entityType = RegionResponse.class, + required=false, description="region ID from where portable ip is to be associated.") + private Integer regionId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -107,6 +115,18 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { return vpcId; } + public boolean isPortable() { + if (isPortable == null) { + return false; + } else { + return isPortable; + } + } + + public Integer getRegionId() { + return regionId; + } + public Long getNetworkId() { if (vpcId != null) { return null; @@ -196,7 +216,13 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException{ try { - IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId()); + IpAddress ip = null; + + if (!isPortable()) { + ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId()); + } else { + ip = _networkService.allocatePortableIP(_accountService.getAccount(getEntityOwnerId()), 1, getZoneId(), getNetworkId(), getVpcId()); + } if (ip != null) { this.setEntityId(ip.getId()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java index 827111902ff..41691ea86d0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java @@ -74,7 +74,12 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public void execute() throws InsufficientAddressCapacityException{ UserContext.current().setEventDetails("Ip Id: " + getIpAddressId()); - boolean result = _networkService.releaseIpAddress(getIpAddressId()); + boolean result = false; + if (!isPortable(id)) { + result = _networkService.releaseIpAddress(getIpAddressId()); + } else { + result = _networkService.releaseIpAddress(getIpAddressId()); + } if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); @@ -139,4 +144,9 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { public Long getInstanceId() { return getIpAddressId(); } + + private boolean isPortable(long id) { + IpAddress ip = getIpAddress(id); + return ip.isPortable(); + } } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java index e022cc78db0..21d5b2a440e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; @@ -62,6 +63,10 @@ public class ListLoadBalancerRulesCmd extends BaseListTaggedResourcesCmd { @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "the availability zone ID") private Long zoneId; + + @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, + description = "list by network id the rule belongs to") + private Long networkId; // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// @@ -86,6 +91,10 @@ public class ListLoadBalancerRulesCmd extends BaseListTaggedResourcesCmd { public Long getZoneId() { return zoneId; } + + public Long getNetworkId() { + return networkId; + } // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java index 902dbae00aa..2e2e1507229 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java @@ -91,6 +91,12 @@ public class EnableStaticNatCmd extends BaseCmd{ } else { ntwkId = networkId; } + + // in case of portable public IP, network ID passed takes precedence + if (ip.isPortable() && networkId != null ) { + ntwkId = networkId; + } + if (ntwkId == null) { throw new InvalidParameterValueException("Unable to enable static nat for the ipAddress id=" + ipAddressId + " as ip is not associated with any network and no networkId is passed in"); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index b5cf9f9c054..63198a420be 100755 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -51,6 +51,7 @@ import com.cloud.dc.DataCenter.NetworkType; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; @@ -424,9 +425,15 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (InsufficientCapacityException ex) { + StringBuilder message = new StringBuilder(ex.getMessage()); + if (ex instanceof InsufficientServerCapacityException) { + if(((InsufficientServerCapacityException)ex).isAffinityApplied()){ + message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them"); + } + } s_logger.info(ex); - s_logger.info(ex.getMessage(), ex); - throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); + s_logger.info(message.toString(), ex); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString()); } } else { result = _userVmService.getUserVm(getEntityId()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java index 4f2ac750ce5..758d9c1667b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; +import com.cloud.event.EventTypes; import com.cloud.exception.*; import com.cloud.user.Account; import com.cloud.user.UserContext; @@ -26,9 +27,11 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.log4j.Logger; +import java.util.List; + @APICommand(name = "scaleVirtualMachine", description="Scales the virtual machine to a new service offering.", responseObject=SuccessResponse.class) -public class ScaleVMCmd extends BaseCmd { +public class ScaleVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName()); private static final String s_name = "scalevirtualmachineresponse"; @@ -84,7 +87,7 @@ public class ScaleVMCmd extends BaseCmd { @Override public void execute(){ //UserContext.current().setEventDetails("Vm Id: "+getId()); - boolean result; + UserVm result; try { result = _userVmService.upgradeVirtualMachine(this); } catch (ResourceUnavailableException ex) { @@ -100,11 +103,23 @@ public class ScaleVMCmd extends BaseCmd { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } - if (result){ - SuccessResponse response = new SuccessResponse(getCommandName()); + if (result != null){ + List responseList = _responseGenerator.createUserVmResponse("virtualmachine", result); + UserVmResponse response = responseList.get(0); + response.setResponseName(getCommandName()); this.setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to scale vm"); } } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_SCALE; + } + + @Override + public String getEventDescription() { + return "scaling volume: " + getId() + " to service offering: " + getServiceOfferingId(); + } } \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java index 3012780cb81..09b34d4af3c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java @@ -30,10 +30,10 @@ import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.user.Account; import com.cloud.user.UserContext; import com.cloud.uservm.UserVm; @@ -112,7 +112,7 @@ public class StartVMCmd extends BaseAsyncCmd { } @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException { + public void execute() throws ResourceUnavailableException, ResourceAllocationException { try { UserContext.current().setEventDetails("Vm Id: " + getId()); @@ -135,6 +135,16 @@ public class StartVMCmd extends BaseAsyncCmd { } catch (ExecutionException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } catch (InsufficientCapacityException ex) { + StringBuilder message = new StringBuilder(ex.getMessage()); + if (ex instanceof InsufficientServerCapacityException) { + if (((InsufficientServerCapacityException) ex).isAffinityApplied()) { + message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them"); + } + } + s_logger.info(ex); + s_logger.info(message.toString(), ex); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString()); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java index 5b1c5c6b4e6..06c25305a00 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java @@ -84,7 +84,7 @@ public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { @Override public void execute() throws ResourceUnavailableException { - _ravService.destroyRemoteAccessVpn(publicIpId, UserContext.current().getCaller()); + _ravService.destroyRemoteAccessVpnForIp(publicIpId, UserContext.current().getCaller()); } @Override diff --git a/api/src/org/apache/cloudstack/api/response/ClusterResponse.java b/api/src/org/apache/cloudstack/api/response/ClusterResponse.java index cfd772d7115..ef8cca65040 100644 --- a/api/src/org/apache/cloudstack/api/response/ClusterResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ClusterResponse.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; -import java.util.ArrayList; -import java.util.List; - +import com.cloud.org.Cluster; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; -import com.cloud.org.Cluster; -import com.cloud.serializer.Param; -import com.google.gson.annotations.SerializedName; +import java.util.ArrayList; +import java.util.List; @EntityReference(value = Cluster.class) public class ClusterResponse extends BaseResponse { @@ -68,7 +67,7 @@ public class ClusterResponse extends BaseResponse { @SerializedName("cpuovercommitratio") @Param(description = "The cpu overcommit ratio of the cluster") private String cpuovercommitratio; - @SerializedName("memoryovercommitratio") @Param (description = "The ram overcommit ratio of the cluster") + @SerializedName("memoryovercommitratio") @Param (description = "The memory overcommit ratio of the cluster") private String memoryovercommitratio; public String getId() { @@ -162,18 +161,20 @@ public class ClusterResponse extends BaseResponse { public void setCapacitites(ArrayList arrayList) { this.capacitites = arrayList; } - public void setCpuovercommitratio(String cpuovercommitratio){ + + public void setCpuOvercommitRatio(String cpuovercommitratio){ this.cpuovercommitratio= cpuovercommitratio; } - public void setRamovercommitratio (String memoryOvercommitRatio){ - this.memoryovercommitratio= memoryOvercommitRatio; - } - public String getCpuovercommitratio (){ + public String getCpuOvercommitRatio(){ return cpuovercommitratio; } - public String getRamovercommitratio (){ + public void setMemoryOvercommitRatio(String memoryovercommitratio){ + this.memoryovercommitratio= memoryovercommitratio; + } + + public String getMemoryOvercommitRatio(){ return memoryovercommitratio; } } diff --git a/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java b/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java index cede84f931e..e3d5cc6a101 100644 --- a/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java +++ b/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java @@ -115,6 +115,9 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with ip address", responseObject = ResourceTagResponse.class) private List tags; + @SerializedName(ApiConstants.IS_PORTABLE) @Param(description = "is public IP portable across the zones") + private Boolean isPortable; + /* @SerializedName(ApiConstants.JOB_ID) @Param(description="shows the current pending asynchronous job ID. This tag is not returned if no current pending jobs are acting on the volume") private IdentityProxy jobId = new IdentityProxy("async_job"); @@ -247,4 +250,8 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR public void setAssociatedNetworkName(String associatedNetworkName) { this.associatedNetworkName = associatedNetworkName; } + + public void setPortable(Boolean portable) { + this.isPortable = portable; + } } diff --git a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java index 79b01b17ff2..0f180970fc7 100644 --- a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java +++ b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java @@ -57,10 +57,14 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti @SerializedName(ApiConstants.ALGORITHM) @Param(description = "the load balancer algorithm (source, roundrobin, leastconn)") private String algorithm; + + @SerializedName(ApiConstants.NETWORK_ID) + @Param(description = "the id of the guest network the lb rule belongs to") + private String networkId; @SerializedName(ApiConstants.CIDR_LIST) @Param(description="the cidr list to forward traffic from") private String cidrList; - + @SerializedName(ApiConstants.ACCOUNT) @Param(description = "the account of the load balancer rule") private String accountName; @@ -89,6 +93,7 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with load balancer", responseObject = ResourceTagResponse.class) private List tags; + public void setId(String id) { this.id = id; @@ -160,5 +165,9 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti public void setTags(List tags) { this.tags = tags; } + + public void setNetworkId(String networkId) { + this.networkId = networkId; + } } diff --git a/api/src/org/apache/cloudstack/api/response/PortableIpRangeResponse.java b/api/src/org/apache/cloudstack/api/response/PortableIpRangeResponse.java new file mode 100644 index 00000000000..e7a15b8f606 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/PortableIpRangeResponse.java @@ -0,0 +1,93 @@ +// 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.response; + +import java.util.Date; +import java.util.List; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.network.IpAddress; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.region.PortableIpRange; + +@EntityReference(value=PortableIpRange.class) +public class PortableIpRangeResponse extends BaseResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "portable IP range ID") + private String id; + + @SerializedName(ApiConstants.REGION_ID) + @Param(description = "Region Id in which portable ip range is provisioned") + private Integer regionId; + + @SerializedName(ApiConstants.GATEWAY) @Param(description="the gateway of the VLAN IP range") + private String gateway; + + @SerializedName(ApiConstants.NETMASK) @Param(description="the netmask of the VLAN IP range") + private String netmask; + + @SerializedName(ApiConstants.VLAN) @Param(description="the ID or VID of the VLAN.") + private String vlan; + + @SerializedName(ApiConstants.START_IP) @Param(description="the start ip of the portable IP range") + private String startIp; + + @SerializedName(ApiConstants.END_IP) @Param(description="the end ip of the portable IP range") + private String endIp; + + @SerializedName(ApiConstants.PORTABLE_IP_ADDRESS) + @Param(description="List of portable IP and association with zone/network/vpc details that are part of GSLB rule", responseObject = PortableIpResponse.class) + private List portableIpResponses; + + public void setId(String id) { + this.id = id; + } + + public void setRegionId(int regionId) { + this.regionId = regionId; + } + + public void setStartIp(String startIp) { + this.startIp = startIp; + } + + public void setEndIp(String endIp) { + this.endIp = endIp; + } + + public void setNetmask(String netmask) { + this.netmask = netmask; + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } + + public void setVlan(String vlan) { + this.vlan = vlan; + } + + public void setPortableIpResponses(List portableIpResponses) { + this.portableIpResponses = portableIpResponses; + } +} diff --git a/api/src/org/apache/cloudstack/api/response/PortableIpResponse.java b/api/src/org/apache/cloudstack/api/response/PortableIpResponse.java new file mode 100644 index 00000000000..0ccbcc3e5f6 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/PortableIpResponse.java @@ -0,0 +1,106 @@ +// 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.response; + +import java.util.Date; +import java.util.List; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.network.IpAddress; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; + +@EntityReference(value=PortableIp.class) +public class PortableIpResponse extends BaseResponse { + + @SerializedName(ApiConstants.REGION_ID) + @Param(description = "Region Id in which global load balancer is created") + private Integer regionId; + + @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="public IP address") + private String ipAddress; + + @SerializedName(ApiConstants.ZONE_ID) @Param(description="the ID of the zone the public IP address belongs to") + private String zoneId; + + @SerializedName(ApiConstants.NETWORK_ID) @Param(description="the ID of the Network where ip belongs to") + private String networkId; + + @SerializedName(ApiConstants.VPC_ID) @Param(description="VPC the ip belongs to") + private String vpcId; + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network this belongs to") + private String physicalNetworkId; + + @SerializedName(ApiConstants.ACCOUNT_ID) @Param(description="the account ID the portable IP address is associated with") + private String accountId; + + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID the portable IP address is associated with") + private String domainId; + + @SerializedName("allocated") @Param(description="date the portal IP address was acquired") + private Date allocated; + + @SerializedName(ApiConstants.STATE) @Param(description="State of the ip address. Can be: Allocatin, Allocated and Releasing") + private String state; + + public void setRegionId(Integer regionId) { + this.regionId = regionId; + } + + public void setAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public void setAssociatedDataCenterId(String zoneId) { + this.zoneId = zoneId; + } + + public void setAssociatedWithNetworkId(String networkId) { + this.networkId = networkId; + } + + public void setAssociatedWithVpcId(String vpcId) { + this.vpcId = vpcId; + } + + public void setPhysicalNetworkId(String physicalNetworkId) { + this.physicalNetworkId = physicalNetworkId; + } + + public void setAllocatedToAccountId(String accountId) { + this.accountId = accountId; + } + + public void setAllocatedInDomainId(String domainId) { + this.domainId = domainId; + } + + public void setAllocatedTime(Date allocatedTimetime) { + this.allocated = allocatedTimetime; + } + + public void setState(String state) { + this.state = state; + } +} diff --git a/api/src/org/apache/cloudstack/region/PortableIp.java b/api/src/org/apache/cloudstack/region/PortableIp.java new file mode 100644 index 00000000000..b95071e2456 --- /dev/null +++ b/api/src/org/apache/cloudstack/region/PortableIp.java @@ -0,0 +1,58 @@ +// 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.region; + +import java.util.Date; + +import com.cloud.utils.net.Ip; +import org.apache.cloudstack.api.InternalIdentity; + +public interface PortableIp extends InternalIdentity { + + enum State { + Allocating, // The IP Address is being propagated to other network elements and is not ready for use yet. + Allocated, // The IP address is in used. + Releasing, // The IP address is being released for other network elements and is not ready for allocation. + Free // The IP address is ready to be allocated. + } + + Long getAllocatedToAccountId(); + + Long getAllocatedInDomainId(); + + Date getAllocatedTime(); + + State getState(); + + int getRegionId(); + + Long getAssociatedDataCenterId(); + + Long getAssociatedWithNetworkId(); + + Long getAssociatedWithVpcId(); + + Long getPhysicalNetworkId(); + + String getAddress(); + + String getVlan(); + + String getNetmask(); + + String getGateway(); +} diff --git a/api/src/org/apache/cloudstack/region/PortableIpRange.java b/api/src/org/apache/cloudstack/region/PortableIpRange.java new file mode 100644 index 00000000000..413a540f92a --- /dev/null +++ b/api/src/org/apache/cloudstack/region/PortableIpRange.java @@ -0,0 +1,38 @@ +// 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.region; + +import org.apache.cloudstack.acl.InfrastructureEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface PortableIpRange extends InfrastructureEntity, InternalIdentity, Identity { + + public final static String UNTAGGED = "untagged"; + + public String getVlanTag(); + + public String getGateway(); + + public String getNetmask(); + + public int getRegionId(); + + public String getIpRange(); + +} diff --git a/api/test/org/apache/cloudstack/api/command/test/ScaleVMCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/ScaleVMCmdTest.java index 8a28290e04b..bb022986e2d 100644 --- a/api/test/org/apache/cloudstack/api/command/test/ScaleVMCmdTest.java +++ b/api/test/org/apache/cloudstack/api/command/test/ScaleVMCmdTest.java @@ -24,11 +24,18 @@ import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd; +import org.apache.cloudstack.api.response.SwiftResponse; +import org.apache.cloudstack.api.response.UserVmResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; +import static org.mockito.Matchers.anyInt; + + +import java.util.LinkedList; +import java.util.List; public class ScaleVMCmdTest extends TestCase{ @@ -58,19 +65,34 @@ public class ScaleVMCmdTest extends TestCase{ public void testCreateSuccess() { UserVmService userVmService = Mockito.mock(UserVmService.class); + UserVm userVm = Mockito.mock(UserVm.class); + try { Mockito.when( userVmService.upgradeVirtualMachine(scaleVMCmd)) - .thenReturn(true); + .thenReturn(userVm); }catch (Exception e){ Assert.fail("Received exception when success expected " +e.getMessage()); } - scaleVMCmd._userVmService = userVmService; - responseGenerator = Mockito.mock(ResponseGenerator.class); - + ResponseGenerator responseGenerator = Mockito.mock(ResponseGenerator.class); scaleVMCmd._responseGenerator = responseGenerator; + + UserVmResponse userVmResponse = Mockito.mock(UserVmResponse.class); + //List list = Mockito.mock(UserVmResponse.class); + //list.add(userVmResponse); + //LinkedList mockedList = Mockito.mock(LinkedList.class); + //Mockito.when(mockedList.get(0)).thenReturn(userVmResponse); + + List list = new LinkedList(); + list.add(userVmResponse); + + Mockito.when(responseGenerator.createUserVmResponse("virtualmachine", userVm)).thenReturn( + list); + + scaleVMCmd._userVmService = userVmService; + scaleVMCmd.execute(); } @@ -83,7 +105,7 @@ public class ScaleVMCmdTest extends TestCase{ try { Mockito.when( userVmService.upgradeVirtualMachine(scaleVMCmd)) - .thenReturn(false); + .thenReturn(null); }catch (Exception e){ Assert.fail("Received exception when success expected " +e.getMessage()); } diff --git a/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java b/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java index f108a20e5b4..5aac3960d02 100644 --- a/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java +++ b/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java @@ -19,15 +19,14 @@ package com.cloud.bridge.persist.dao; import javax.ejb.Local; import org.apache.log4j.Logger; -import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.springframework.stereotype.Component; import com.cloud.bridge.model.CloudStackUserVO; -import com.cloud.bridge.util.EncryptionSecretKeyCheckerUtil; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; +import com.cloud.utils.crypt.DBEncryptionUtil; @Component @Local(value={CloudStackUserDao.class}) @@ -51,13 +50,8 @@ public class CloudStackUserDaoImpl extends GenericDaoBase use the keys to see if the account actually exists @@ -666,17 +678,23 @@ public class EC2RestServlet extends HttpServlet { String[] volumeId = request.getParameterValues( "VolumeId" ); if ( null != volumeId && 0 < volumeId.length ) EC2request.setId( volumeId[0] ); - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - VolumeId"); + } String[] instanceId = request.getParameterValues( "InstanceId" ); if ( null != instanceId && 0 < instanceId.length ) EC2request.setInstanceId( instanceId[0] ); - else { response.sendError(530, "Missing InstanceId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } String[] device = request.getParameterValues( "Device" ); if ( null != device && 0 < device.length ) EC2request.setDevice( device[0] ); - else { response.sendError(530, "Missing Device parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Device"); + } // -> execute the request AttachVolumeResponse EC2response = EC2SoapServiceImpl.toAttachVolumeResponse( ServiceProvider.getInstance().getEC2Engine().attachVolume( EC2request )); @@ -694,7 +712,9 @@ public class EC2RestServlet extends HttpServlet { String[] groupName = request.getParameterValues( "GroupName" ); if ( null != groupName && 0 < groupName.length ) EC2request.setName( groupName[0] ); - else { response.sendError(530, "Missing GroupName parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupName"); + } // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol int nCount = 1, mCount; @@ -757,8 +777,7 @@ public class EC2RestServlet extends HttpServlet { } while( true ); if (1 == nCount) { - response.sendError(530, "At least one IpPermissions required" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - IpPermissions"); } // -> execute the request @@ -775,7 +794,9 @@ public class EC2RestServlet extends HttpServlet { String[] groupName = request.getParameterValues( "GroupName" ); if ( null != groupName && 0 < groupName.length ) EC2request.setName( groupName[0] ); - else { response.sendError(530, "Missing GroupName parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter 'Groupname'"); + } // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol int nCount = 1; @@ -837,8 +858,9 @@ public class EC2RestServlet extends HttpServlet { } while( true ); - if (1 == nCount) { response.sendError(530, "At least one IpPermissions required" ); return; } - + if (1 == nCount) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - IpPermissions"); + } // -> execute the request AuthorizeSecurityGroupIngressResponse EC2response = EC2SoapServiceImpl.toAuthorizeSecurityGroupIngressResponse( @@ -853,7 +875,9 @@ public class EC2RestServlet extends HttpServlet { String[] volumeId = request.getParameterValues( "VolumeId" ); if ( null != volumeId && 0 < volumeId.length ) EC2request.setId(volumeId[0]); - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter 'VolumeId'"); + } String[] instanceId = request.getParameterValues( "InstanceId" ); if ( null != instanceId && 0 < instanceId.length ) @@ -875,7 +899,9 @@ public class EC2RestServlet extends HttpServlet { String[] volumeId = request.getParameterValues( "VolumeId" ); if ( null != volumeId && 0 < volumeId.length ) EC2request.setId(volumeId[0]); - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - VolumeId"); + } // -> execute the request DeleteVolumeResponse EC2response = EC2SoapServiceImpl.toDeleteVolumeResponse( ServiceProvider.getInstance().getEC2Engine().deleteVolume( EC2request )); @@ -889,7 +915,9 @@ public class EC2RestServlet extends HttpServlet { String[] zoneName = request.getParameterValues( "AvailabilityZone" ); if ( null != zoneName && 0 < zoneName.length ) EC2request.setZoneName( zoneName[0] ); - else { response.sendError(530, "Missing AvailabilityZone parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing parameter - AvailabilityZone"); + } String[] size = request.getParameterValues( "Size" ); String[] snapshotId = request.getParameterValues("SnapshotId"); @@ -907,9 +935,9 @@ public class EC2RestServlet extends HttpServlet { } else if (useSnapshot && !useSize) { EC2request.setSnapshotId(snapshotId[0]); } else if (useSize && useSnapshot) { - response.sendError(530, "Size and SnapshotId parameters are mutually exclusive" ); return; + throw new EC2ServiceException( ClientError.InvalidParameterCombination, "Parameters 'Size' and 'SnapshotId' are mutually exclusive"); } else { - response.sendError(530, "Size or SnapshotId has to be specified" ); return; + throw new EC2ServiceException( ClientError.MissingParamter, "Parameter 'Size' or 'SnapshotId' has to be specified"); } @@ -926,12 +954,15 @@ public class EC2RestServlet extends HttpServlet { String[] name = request.getParameterValues( "GroupName" ); if ( null != name && 0 < name.length ) groupName = name[0]; - else { response.sendError(530, "Missing GroupName parameter" ); return; } - + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupName"); + } String[] desc = request.getParameterValues( "GroupDescription" ); if ( null != desc && 0 < desc.length ) groupDescription = desc[0]; - else { response.sendError(530, "Missing GroupDescription parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupDescription"); + } // -> execute the request CreateSecurityGroupResponse EC2response = EC2SoapServiceImpl.toCreateSecurityGroupResponse( ServiceProvider.getInstance().getEC2Engine().createSecurityGroup( groupName, groupDescription )); @@ -945,7 +976,9 @@ public class EC2RestServlet extends HttpServlet { String[] name = request.getParameterValues( "GroupName" ); if ( null != name && 0 < name.length ) groupName = name[0]; - else { response.sendError(530, "Missing GroupName parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupName"); + } // -> execute the request DeleteSecurityGroupResponse EC2response = EC2SoapServiceImpl.toDeleteSecurityGroupResponse( ServiceProvider.getInstance().getEC2Engine().deleteSecurityGroup( groupName )); @@ -959,7 +992,9 @@ public class EC2RestServlet extends HttpServlet { String[] snapSet = request.getParameterValues( "SnapshotId" ); if ( null != snapSet && 0 < snapSet.length ) snapshotId = snapSet[0]; - else { response.sendError(530, "Missing SnapshotId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SnapshotId"); + } // -> execute the request DeleteSnapshotResponse EC2response = EC2SoapServiceImpl.toDeleteSnapshotResponse( ServiceProvider.getInstance().getEC2Engine().deleteSnapshot( snapshotId )); @@ -973,7 +1008,9 @@ public class EC2RestServlet extends HttpServlet { String[] volSet = request.getParameterValues( "VolumeId" ); if ( null != volSet && 0 < volSet.length ) volumeId = volSet[0]; - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - VolumeId"); + } // -> execute the request EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); @@ -988,7 +1025,9 @@ public class EC2RestServlet extends HttpServlet { String[] imageId = request.getParameterValues( "ImageId" ); if ( null != imageId && 0 < imageId.length ) image.setId( imageId[0] ); - else { response.sendError(530, "Missing ImageId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); + } // -> execute the request DeregisterImageResponse EC2response = EC2SoapServiceImpl.toDeregisterImageResponse( ServiceProvider.getInstance().getEC2Engine().deregisterImage( image )); @@ -1002,16 +1041,25 @@ public class EC2RestServlet extends HttpServlet { String[] instanceId = request.getParameterValues( "InstanceId" ); if ( null != instanceId && 0 < instanceId.length ) EC2request.setInstanceId( instanceId[0] ); - else { response.sendError(530, "Missing InstanceId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } String[] name = request.getParameterValues( "Name" ); if ( null != name && 0 < name.length ) EC2request.setName( name[0] ); - else { response.sendError(530, "Missing Name parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Name"); + } String[] description = request.getParameterValues( "Description" ); - if ( null != description && 0 < description.length ) + if ( null != description && 0 < description.length ) { + if (description[0].length() > 255) + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Length of the value of parameter Description should be less than 255"); EC2request.setDescription( description[0] ); + } + // -> execute the request CreateImageResponse EC2response = EC2SoapServiceImpl.toCreateImageResponse( ServiceProvider.getInstance().getEC2Engine().createImage( EC2request )); @@ -1025,16 +1073,23 @@ public class EC2RestServlet extends HttpServlet { String[] location = request.getParameterValues( "ImageLocation" ); if ( null != location && 0 < location.length ) EC2request.setLocation( location[0] ); - else { response.sendError(530, "Missing ImageLocation parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing parameter - ImageLocation"); + } String[] cloudRedfined = request.getParameterValues( "Architecture" ); if ( null != cloudRedfined && 0 < cloudRedfined.length ) EC2request.setArchitecture( cloudRedfined[0] ); - else { response.sendError(530, "Missing Architecture parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Architecture"); + } String[] name = request.getParameterValues( "Name" ); if ( null != name && 0 < name.length ) EC2request.setName( name[0] ); + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Name"); + } String[] description = request.getParameterValues( "Description" ); if ( null != description && 0 < description.length ) @@ -1053,9 +1108,8 @@ public class EC2RestServlet extends HttpServlet { if ( imageId != null && imageId.length > 0 ) ec2request.setImageId( imageId[0]); else { - response.sendError(530, "Missing ImageId parameter" ); - return; - } + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); + } String[] description = request.getParameterValues( "Description.Value" ); if ( description != null && description.length > 0 ) { @@ -1067,8 +1121,8 @@ public class EC2RestServlet extends HttpServlet { if (ec2request.getLaunchPermissionSet().length > 0) ec2request.setAttribute(ImageAttribute.launchPermission); else { - response.sendError(530, "Missing Attribute parameter - Description/LaunchPermission should be provided" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing required parameter - Description/LaunchPermission should be provided"); } } @@ -1120,8 +1174,7 @@ public class EC2RestServlet extends HttpServlet { if ( imageId != null && imageId.length > 0) ec2request.setImageId(imageId[0]); else { - response.sendError(530, "Missing ImageId parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); } String[] attribute = request.getParameterValues( "Attribute" ); @@ -1129,12 +1182,11 @@ public class EC2RestServlet extends HttpServlet { if (attribute[0].equalsIgnoreCase("launchPermission")) ec2request.setAttribute(ImageAttribute.launchPermission); else { - response.sendError(501, "Unsupported Attribute - only launchPermission supported" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing required parameter - Description/LaunchPermission should be provided"); } } else { - response.sendError(530, "Missing Attribute parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Attribute"); } EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission(); @@ -1155,12 +1207,13 @@ public class EC2RestServlet extends HttpServlet { String[] imageId = request.getParameterValues( "ImageId" ); if ( null != imageId && 0 < imageId.length ) EC2request.setTemplateId( imageId[0] ); - else { response.sendError(530, "Missing ImageId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); + } String[] minCount = request.getParameterValues( "MinCount" ); if ( minCount == null || minCount.length < 1) { - response.sendError(530, "Missing MinCount parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - MinCount"); } else if ( Integer.parseInt(minCount[0]) < 1) { throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MinCount should be greater than 0"); @@ -1170,8 +1223,7 @@ public class EC2RestServlet extends HttpServlet { String[] maxCount = request.getParameterValues( "MaxCount" ); if ( maxCount == null || maxCount.length < 1) { - response.sendError(530, "Missing MaxCount parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - MaxCount"); } else if ( Integer.parseInt(maxCount[0]) < 1) { throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MaxCount should be greater than 0"); @@ -1235,7 +1287,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } // -> execute the request RebootInstancesResponse EC2response = EC2SoapServiceImpl.toRebootInstancesResponse( ServiceProvider.getInstance().getEC2Engine().rebootInstances(EC2request)); @@ -1259,7 +1313,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } // -> execute the request StartInstancesResponse EC2response = EC2SoapServiceImpl.toStartInstancesResponse( ServiceProvider.getInstance().getEC2Engine().startInstances(EC2request)); @@ -1283,7 +1339,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } String[] force = request.getParameterValues("Force"); if ( force != null) { @@ -1312,7 +1370,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } // -> execute the request EC2request.setDestroyInstances( true ); @@ -1349,7 +1409,8 @@ public class EC2RestServlet extends HttpServlet { } // -> execute the request - DescribeAvailabilityZonesResponse EC2response = EC2SoapServiceImpl.toDescribeAvailabilityZonesResponse( ServiceProvider.getInstance().getEC2Engine().handleRequest( EC2request )); + DescribeAvailabilityZonesResponse EC2response = EC2SoapServiceImpl.toDescribeAvailabilityZonesResponse( + ServiceProvider.getInstance().getEC2Engine().describeAvailabilityZones( EC2request )); serializeResponse(response, EC2response); } @@ -1366,6 +1427,15 @@ public class EC2RestServlet extends HttpServlet { if (null != value && 0 < value.length) EC2request.addImageSet( value[0] ); } } + // add filters + EC2Filter[] filterSet = extractFilters( request ); + if ( filterSet != null ) { + EC2ImageFilterSet ifs = new EC2ImageFilterSet(); + for( int i=0; i < filterSet.length; i++ ) { + ifs.addFilter(filterSet[i]); + } + EC2request.setFilterSet( ifs ); + } // -> execute the request EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); DescribeImagesResponse EC2response = EC2SoapServiceImpl.toDescribeImagesResponse( engine.describeImages( EC2request )); @@ -1380,8 +1450,7 @@ public class EC2RestServlet extends HttpServlet { if (imageId != null && imageId.length > 0) ec2request.setImageId(imageId[0]); else { - response.sendError(530, "Missing ImageId parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); } String[] attribute = request.getParameterValues( "Attribute" ); @@ -1391,12 +1460,11 @@ public class EC2RestServlet extends HttpServlet { else if (attribute[0].equalsIgnoreCase("launchPermission")) ec2request.setAttribute(ImageAttribute.launchPermission); else { - response.sendError(501, "Unsupported Attribute - description and launchPermission supported" ); - return; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Only values supported for paramter Attribute are - Description/LaunchPermission"); } } else { - response.sendError(530, "Missing Attribute parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Attribute"); } DescribeImageAttributeResponse EC2response = EC2SoapServiceImpl.toDescribeImageAttributeResponse( ServiceProvider.getInstance().getEC2Engine().describeImageAttribute( ec2request )); @@ -1477,9 +1545,8 @@ public class EC2RestServlet extends HttpServlet { EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); String publicIp = request.getParameter( "PublicIp" ); - if (publicIp == null) { - response.sendError(530, "Missing PublicIp parameter"); - return; + if (publicIp == null) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicIp"); } EC2ReleaseAddress ec2Request = new EC2ReleaseAddress(); @@ -1498,13 +1565,11 @@ public class EC2RestServlet extends HttpServlet { String publicIp = request.getParameter( "PublicIp" ); if (null == publicIp) { - response.sendError(530, "Missing PublicIp parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicIp"); } String instanceId = request.getParameter( "InstanceId" ); if (null == instanceId) { - response.sendError(530, "Missing InstanceId parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); } EC2AssociateAddress ec2Request = new EC2AssociateAddress(); @@ -1524,8 +1589,7 @@ public class EC2RestServlet extends HttpServlet { String publicIp = request.getParameter( "PublicIp" ); if (null == publicIp) { - response.sendError(530, "Missing PublicIp parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicIp"); } EC2DisassociateAddress ec2Request = new EC2DisassociateAddress(); @@ -1573,27 +1637,20 @@ public class EC2RestServlet extends HttpServlet { private void describeInstanceAttribute( HttpServletRequest request, HttpServletResponse response ) throws ADBException, XMLStreamException, IOException { EC2DescribeInstances EC2request = new EC2DescribeInstances(); - String instanceType = null; + String[] instanceId = request.getParameterValues( "InstanceId" ); + if ( instanceId != null && instanceId.length > 0) + EC2request.addInstanceId( instanceId[0] ); + else + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); - // -> we are only handling queries about the "Attribute=instanceType" - Enumeration names = request.getParameterNames(); - while( names.hasMoreElements()) { - String key = (String)names.nextElement(); - if (key.startsWith("Attribute")) { - String[] value = request.getParameterValues( key ); - if (null != value && 0 < value.length && value[0].equalsIgnoreCase( "instanceType" )) { - instanceType = value[0]; - break; - } + String[] attribute = request.getParameterValues( "Attribute" ); + if (attribute != null && attribute.length > 0) { + if ( !attribute[0].equalsIgnoreCase("instanceType") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Only value supported for paramter Attribute is 'instanceType'"); } - } - if ( null != instanceType ) { - String[] value = request.getParameterValues( "InstanceId" ); - EC2request.addInstanceId( value[0] ); - } - else { - response.sendError(501, "Unsupported - only instanceType supported" ); - return; + } else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Attribute"); } // -> execute the request @@ -1601,6 +1658,38 @@ public class EC2RestServlet extends HttpServlet { serializeResponse(response, EC2response); } + private void modifyInstanceAttribute(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2ModifyInstanceAttribute ec2Request = new EC2ModifyInstanceAttribute(); + + String[] instanceId = request.getParameterValues( "InstanceId" ); + if ( instanceId != null && instanceId.length > 0 ) + ec2Request.setInstanceId(instanceId[0]); + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } + + String[] instanceType = request.getParameterValues( "InstanceType.Value" ); + String[] userData = request.getParameterValues( "UserData.Value" ); + + if ( instanceType != null && userData != null ) { + throw new EC2ServiceException( ClientError.InvalidParameterCombination, "Only one attribute can be" + + " specified at a time"); + } + if ( instanceType != null && instanceType.length > 0 ) { + ec2Request.setInstanceType(instanceType[0]); + } else if ( userData != null && userData.length > 0 ) { + ec2Request.setUserData(userData[0]); + } else { + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing parameter - InstanceType/UserData should be provided"); + } + + // -> execute the request + ModifyInstanceAttributeResponse EC2response = EC2SoapServiceImpl.toModifyInstanceAttributeResponse( + ServiceProvider.getInstance().getEC2Engine().modifyInstanceAttribute( ec2Request )); + serializeResponse(response, EC2response); + } private void describeSnapshots( HttpServletRequest request, HttpServletResponse response ) throws ADBException, XMLStreamException, IOException @@ -1629,7 +1718,8 @@ public class EC2RestServlet extends HttpServlet { // -> execute the request EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); - DescribeSnapshotsResponse EC2response = EC2SoapServiceImpl.toDescribeSnapshotsResponse( engine.handleRequest( EC2request )); + DescribeSnapshotsResponse EC2response = EC2SoapServiceImpl.toDescribeSnapshotsResponse( + engine.describeSnapshots( EC2request )); serializeResponse(response, EC2response); } @@ -1661,7 +1751,9 @@ public class EC2RestServlet extends HttpServlet { } // -> execute the request - DescribeVolumesResponse EC2response = EC2SoapServiceImpl.toDescribeVolumesResponse( ServiceProvider.getInstance().getEC2Engine().handleRequest( EC2request )); + EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); + DescribeVolumesResponse EC2response = EC2SoapServiceImpl.toDescribeVolumesResponse( + ServiceProvider.getInstance().getEC2Engine().describeVolumes( EC2request ), engine); serializeResponse(response, EC2response); } @@ -1755,10 +1847,13 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { String keyName = request.getParameter("KeyName"); + if ( keyName == null ) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - KeyName"); + } + String publicKeyMaterial = request.getParameter("PublicKeyMaterial"); - if (keyName==null && publicKeyMaterial==null) { - response.sendError(530, "Missing parameter"); - return; + if ( publicKeyMaterial == null ) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicKeyMaterial"); } if (!publicKeyMaterial.contains(" ")) @@ -1780,9 +1875,8 @@ public class EC2RestServlet extends HttpServlet { private void createKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { String keyName = request.getParameter("KeyName"); - if (keyName==null) { - response.sendError(530, "Missing KeyName parameter"); - return; + if (keyName==null) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - KeyName"); } EC2CreateKeyPair ec2Request = new EC2CreateKeyPair(); @@ -1799,8 +1893,7 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { String keyName = request.getParameter("KeyName"); if (keyName==null) { - response.sendError(530, "Missing KeyName parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - KeyName"); } EC2DeleteKeyPair ec2Request = new EC2DeleteKeyPair(); @@ -1815,8 +1908,7 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { String instanceId = request.getParameter("InstanceId"); if (instanceId==null) { - response.sendError(530, "Missing InstanceId parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); } GetPasswordDataResponse EC2Response = EC2SoapServiceImpl.toGetPasswordData( @@ -1824,6 +1916,81 @@ public class EC2RestServlet extends HttpServlet { serializeResponse(response, EC2Response); } + private void createTags(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2Tags ec2Request = createTagsRequest(request, response); + if (ec2Request == null) return; + CreateTagsResponse EC2Response = EC2SoapServiceImpl.toCreateTagsResponse( + ServiceProvider.getInstance().getEC2Engine().modifyTags( ec2Request, "create")); + serializeResponse(response, EC2Response); + } + + private void deleteTags(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2Tags ec2Request = createTagsRequest(request, response); + if (ec2Request == null) return; + DeleteTagsResponse EC2Response = EC2SoapServiceImpl.toDeleteTagsResponse( + ServiceProvider.getInstance().getEC2Engine().modifyTags( ec2Request, "delete")); + serializeResponse(response, EC2Response); + } + + private EC2Tags createTagsRequest(HttpServletRequest request, HttpServletResponse response) + throws IOException { + EC2Tags ec2Request = new EC2Tags(); + ArrayList resourceIdList = new ArrayList(); + Map resourceTagList = new HashMap(); + + int nCount = 1; + do { + String[] resourceIds = request.getParameterValues( "ResourceId." + nCount ); + if (resourceIds != null && resourceIds.length > 0) + resourceIdList.add(resourceIds[0]); + else break; + nCount++; + } while (true); + if ( resourceIdList.isEmpty() ) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ResourceId"); + } + ec2Request = EC2SoapServiceImpl.toResourceTypeAndIds(ec2Request, resourceIdList); + + nCount = 1; + do { + String[] tagKey = request.getParameterValues( "Tag." + nCount + ".Key" ); + if ( tagKey != null && tagKey.length > 0 ) { + String[] tagValue = request.getParameterValues( "Tag." + nCount + ".Value" ); + if ( tagValue != null && tagValue.length > 0 ) { + resourceTagList.put(tagKey[0], tagValue[0]); + } else + resourceTagList.put(tagKey[0], null); + } else break; + nCount++; + } while (true); + if ( resourceTagList.isEmpty() ) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ResourceTag"); + } + ec2Request = EC2SoapServiceImpl.toResourceTag(ec2Request, resourceTagList); + + return ec2Request; + } + + private void describeTags(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2DescribeTags ec2Request = new EC2DescribeTags(); + + EC2Filter[] filterSet = extractFilters( request ); + if (null != filterSet) { + EC2TagsFilterSet tfs = new EC2TagsFilterSet(); + for( int i=0; i < filterSet.length; i++ ) + tfs.addFilter( filterSet[i] ); + ec2Request.setFilterSet( tfs ); + } + DescribeTagsResponse EC2Response = EC2SoapServiceImpl.toDescribeTagsResponse( + ServiceProvider.getInstance().getEC2Engine().describeTags( ec2Request)); + serializeResponse(response, EC2Response); + } + + + /** * This function implements the EC2 REST authentication algorithm. It uses the given * "AWSAccessKeyId" parameter to look up the Cloud.com account holder's secret key which is @@ -1843,69 +2010,76 @@ public class EC2RestServlet extends HttpServlet { String[] awsAccess = request.getParameterValues( "AWSAccessKeyId" ); if ( null != awsAccess && 0 < awsAccess.length ) cloudAccessKey = awsAccess[0]; - else { response.sendError(530, "Missing AWSAccessKeyId parameter" ); return false; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - AWSAccessKeyId"); + } String[] clientSig = request.getParameterValues( "Signature" ); if ( null != clientSig && 0 < clientSig.length ) signature = clientSig[0]; - else { response.sendError(530, "Missing Signature parameter" ); return false; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Signature"); + } String[] method = request.getParameterValues( "SignatureMethod" ); if ( null != method && 0 < method.length ) { sigMethod = method[0]; if (!sigMethod.equals( "HmacSHA256" ) && !sigMethod.equals( "HmacSHA1" )) { - response.sendError(531, "Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1" ); - return false; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1"); } + } else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SignatureMethod"); } - else { response.sendError(530, "Missing SignatureMethod parameter" ); return false; } String[] version = request.getParameterValues( "Version" ); if ( null != version && 0 < version.length ) { if (!version[0].equals( wsdlVersion )) { - response.sendError(531, "Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion ); - return false; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion); } + } else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Version"); } - else { response.sendError(530, "Missing Version parameter" ); return false; } String[] sigVersion = request.getParameterValues( "SignatureVersion" ); if ( null != sigVersion && 0 < sigVersion.length ) { if (!sigVersion[0].equals( "2" )) { - response.sendError(531, "Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2" ); - return false; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2"); } } - else { response.sendError(530, "Missing SignatureVersion parameter" ); return false; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SignatureVersion"); + } // -> can have only one but not both { Expires | Timestamp } headers String[] expires = request.getParameterValues( "Expires" ); if ( null != expires && 0 < expires.length ) { // -> contains the date and time at which the signature included in the request EXPIRES - if (hasSignatureExpired( expires[0] )) { - response.sendError(531, "Expires parameter indicates signature has expired: " + expires[0] ); - return false; + if (hasSignatureExpired( expires[0] )) { //InvalidSecurity.RequestHasExpired + throw new EC2ServiceException( ClientError.InvalidSecurity_RequestHasExpired, + "Expires parameter indicates signature has expired: " + expires[0]); } } else { // -> contains the date and time at which the request is SIGNED String[] time = request.getParameterValues( "Timestamp" ); if ( null == time || 0 == time.length ) { - response.sendError(530, "Missing Timestamp and Expires parameter, one is required" ); - return false; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter -" + + " Timestamp/Expires"); } } // [B] Use the access key to get the users secret key from the cloud DB cloudSecretKey = userDao.getSecretKeyByAccessKey( cloudAccessKey ); if ( cloudSecretKey == null ) { - logger.debug("No Secret key found for Access key '" + cloudAccessKey + "' in the the EC2 service"); - throw new EC2ServiceException( ClientError.AuthFailure, "No Secret key found for Access key '" + cloudAccessKey + - "' in the the EC2 service" ); + logger.debug( "Access key '" + cloudAccessKey + "' not found in the the EC2 service "); + throw new EC2ServiceException( ClientError.AuthFailure, "Access key '" + cloudAccessKey + "' not found in the the EC2 service "); } // [C] Verify the signature @@ -1949,8 +2123,9 @@ public class EC2RestServlet extends HttpServlet { UserContext.current().initContext( cloudAccessKey, cloudSecretKey, cloudAccessKey, "REST request", null ); return true; } - else throw new PermissionDeniedException("Invalid signature"); - } + else throw new EC2ServiceException( ClientError.SignatureDoesNotMatch, + "The request signature calculated does not match the signature provided by the user."); + } /** * We check this to reduce replay attacks. @@ -2043,8 +2218,9 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { OutputStream os = response.getOutputStream(); response.setStatus(200); - response.setContentType("text/xml; charset=UTF-8"); + response.setContentType("text/xml"); XMLStreamWriter xmlWriter = xmlOutFactory.createXMLStreamWriter( os ); + xmlWriter.writeStartDocument("UTF-8","1.0"); MTOMAwareXMLSerializer MTOMWriter = new MTOMAwareXMLSerializer( xmlWriter ); MTOMWriter.setDefaultNamespace("http://ec2.amazonaws.com/doc/" + wsdlVersion + "/"); EC2Response.serialize( null, factory, MTOMWriter ); diff --git a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java index cebac0b159e..f6ac9711a0d 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java +++ b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java @@ -18,7 +18,10 @@ package com.cloud.bridge.service; import java.util.ArrayList; import java.util.Calendar; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; import org.apache.commons.codec.binary.Base64; @@ -48,7 +51,9 @@ import com.cloud.bridge.service.core.ec2.EC2DescribeInstances; import com.cloud.bridge.service.core.ec2.EC2DescribeInstancesResponse; import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs; import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairsResponse; +import com.cloud.bridge.service.core.ec2.EC2ImageFilterSet; import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission; +import com.cloud.bridge.service.core.ec2.EC2ModifyInstanceAttribute; import com.cloud.bridge.service.core.ec2.EC2ResourceTag; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroupsResponse; @@ -92,7 +97,6 @@ import com.cloud.bridge.service.core.ec2.EC2Volume; import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet; import com.cloud.bridge.service.exception.EC2ServiceException; import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; -import com.cloud.bridge.service.exception.EC2ServiceException.ServerError; import com.cloud.bridge.util.EC2RestAuth; @@ -210,87 +214,103 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public CreateTagsResponse createTags(CreateTags createTags) { EC2Tags request = new EC2Tags(); + ArrayList resourceIdList = new ArrayList(); + Map resourceTagList = new HashMap(); + CreateTagsType ctt = createTags.getCreateTags(); ResourceIdSetType resourceIds = ctt.getResourcesSet(); ResourceTagSetType resourceTags = ctt.getTagSet(); - request = toResourceTypeAndIds(resourceIds); - //add resource tag's to the request - if (resourceTags != null) { - ResourceTagSetItemType[] items = resourceTags.getItem(); - if (items != null) { - for( int i=0; i < items.length; i++ ) { - EC2TagKeyValue param1 = new EC2TagKeyValue(); - param1.setKey(items[i].getKey()); - param1.setValue(items[i].getValue()); - request.addResourceTag(param1); - } - } + + ResourceIdSetItemType[] resourceIdItems = resourceIds.getItem(); + if (resourceIdItems != null) { + for( int i=0; i < resourceIdItems.length; i++ ) + resourceIdList.add(resourceIdItems[i].getResourceId()); } + request = toResourceTypeAndIds(request, resourceIdList); + + //add resource tag's to the request + ResourceTagSetItemType[] resourceTagItems = resourceTags.getItem(); + if (resourceTagItems != null) { + for( int i=0; i < resourceTagItems.length; i++ ) + resourceTagList.put(resourceTagItems[i].getKey(), resourceTagItems[i].getValue()); + } + request = toResourceTag(request, resourceTagList); + return toCreateTagsResponse( engine.modifyTags( request, "create")); } public DeleteTagsResponse deleteTags(DeleteTags deleteTags) { EC2Tags request = new EC2Tags(); + ArrayList resourceIdList = new ArrayList(); + Map resourceTagList = new HashMap(); + DeleteTagsType dtt = deleteTags.getDeleteTags(); ResourceIdSetType resourceIds = dtt.getResourcesSet(); DeleteTagsSetType resourceTags = dtt.getTagSet(); - request = toResourceTypeAndIds(resourceIds); - //add resource tag's to the request - if (resourceTags != null) { - DeleteTagsSetItemType[] items = resourceTags.getItem(); - if (items != null) { - for( int i=0; i < items.length; i++ ) { - EC2TagKeyValue param1 = new EC2TagKeyValue(); - param1.setKey(items[i].getKey()); - if (items[i].getValue() != null) - param1.setValue(items[i].getValue()); - request.addResourceTag(param1); - } - } + + ResourceIdSetItemType[] resourceIdItems = resourceIds.getItem(); + + if (resourceIdItems != null) { + for( int i=0; i < resourceIdItems.length; i++ ) + resourceIdList.add(resourceIdItems[i].getResourceId()); } + request = toResourceTypeAndIds(request, resourceIdList); + + //add resource tag's to the request + DeleteTagsSetItemType[] resourceTagItems = resourceTags.getItem(); + if (resourceTagItems != null) { + for( int i=0; i < resourceTagItems.length; i++ ) + resourceTagList.put(resourceTagItems[i].getKey(), resourceTagItems[i].getValue()); + } + request = toResourceTag(request, resourceTagList); + return toDeleteTagsResponse( engine.modifyTags( request, "delete")); } - private EC2Tags toResourceTypeAndIds(ResourceIdSetType resourceIds) { - EC2Tags request = new EC2Tags(); - //add resource-type and resource-id's to the request - if (resourceIds != null) { - ResourceIdSetItemType[] items = resourceIds.getItem(); - List resourceTypeList = new ArrayList(); - if (items != null) { - for( int i=0; i < items.length; i++ ) { - if (!items[i].getResourceId().contains(":") || items[i].getResourceId().split(":").length != 2) { - throw new EC2ServiceException( ClientError.InvalidResourceId_Format, - "Invalid Format. ResourceId format is resource-type:resource-uuid"); - } - String resourceType = items[i].getResourceId().split(":")[0]; - if (resourceTypeList.isEmpty()) - resourceTypeList.add(resourceType); - else { - Boolean existsInList = false; - for (String addedResourceType : resourceTypeList) { - if (addedResourceType.equalsIgnoreCase(resourceType)) { - existsInList = true; - break; - } - } - if (!existsInList) - resourceTypeList.add(resourceType); - } - } - for (String resourceType : resourceTypeList){ - EC2TagTypeId param1 = new EC2TagTypeId(); - param1.setResourceType(resourceType); - for( int i=0; i < items.length; i++ ) { - String[] resourceTag = items[i].getResourceId().split(":"); - if (resourceType.equals(resourceTag[0])) - param1.addResourceId(resourceTag[1]); - } - request.addResourceType(param1); - } + public static EC2Tags toResourceTypeAndIds( EC2Tags request, ArrayList resourceIdList ) { + List resourceTypeList = new ArrayList(); + for (String resourceId : resourceIdList) { + if (!resourceId.contains(":") || resourceId.split(":").length != 2) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Invalid usage. ResourceId format is resource-type:resource-uuid"); } + String resourceType = resourceId.split(":")[0]; + if (resourceTypeList.isEmpty()) + resourceTypeList.add(resourceType); + else { + Boolean existsInList = false; + for (String addedResourceType : resourceTypeList) { + if (addedResourceType.equalsIgnoreCase(resourceType)) { + existsInList = true; + break; + } + } + if (!existsInList) + resourceTypeList.add(resourceType); + } + } + for (String resourceType : resourceTypeList) { + EC2TagTypeId param1 = new EC2TagTypeId(); + param1.setResourceType(resourceType); + for (String resourceId : resourceIdList) { + String[] resourceTag = resourceId.split(":"); + if (resourceType.equals(resourceTag[0])) + param1.addResourceId(resourceTag[1]); + } + request.addResourceType(param1); + } + return request; + } + + public static EC2Tags toResourceTag( EC2Tags request, Map resourceTagList ) { + Set resourceTagKeySet = resourceTagList.keySet(); + for (String resourceTagKey : resourceTagKeySet) { + EC2TagKeyValue param1 = new EC2TagKeyValue(); + param1.setKey(resourceTagKey); + param1.setValue(resourceTagList.get(resourceTagKey)); + request.addResourceTag(param1); } return request; } @@ -336,7 +356,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { request.setFilterSet( toAvailabiltyZonesFilterSet(fst)); } - return toDescribeAvailabilityZonesResponse( engine.handleRequest( request )); + return toDescribeAvailabilityZonesResponse( engine.describeAvailabilityZones( request )); } /** @@ -388,7 +408,10 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { for( int i=0; i < items3.length; i++ ) request.addOwnersSet( items3[i].getOwner()); } } - + FilterSetType fst = dit.getFilterSet(); + if ( fst != null) { + request.setFilterSet(toImageFilterSet(fst)); + } return toDescribeImagesResponse( engine.describeImages( request )); } @@ -399,11 +422,11 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { EmptyElementType instanceType = diag.getInstanceType(); // -> toEC2DescribeInstances - if (null != instanceType) { - request.addInstanceId( diat.getInstanceId()); + if (null != instanceType) { + request.addInstanceId( diat.getInstanceId()); return toDescribeInstanceAttributeResponse( engine.describeInstances( request )); } - throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - only instanceType supported"); + throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - only instanceType supported"); } @@ -526,7 +549,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { request = toSnapshotFilterSet( request, fst, timeFilters ); } - return toDescribeSnapshotsResponse(engine.handleRequest(request)); + return toDescribeSnapshotsResponse(engine.describeSnapshots(request)); } public DescribeTagsResponse describeTags(DescribeTags decsribeTags) { @@ -565,7 +588,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { request = toVolumeFilterSet( request, fst, timeFilters ); } - return toDescribeVolumesResponse( engine.handleRequest( request )); + return toDescribeVolumesResponse( engine.describeVolumes( request ), engine); } public DetachVolumeResponse detachVolume(DetachVolume detachVolume) { @@ -606,6 +629,26 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - can only modify image description or launchPermission"); } + public ModifyInstanceAttributeResponse modifyInstanceAttribute(ModifyInstanceAttribute modifyInstanceAttribute) { + EC2ModifyInstanceAttribute request = new EC2ModifyInstanceAttribute(); + + ModifyInstanceAttributeType modifyInstanceAttribute2 = modifyInstanceAttribute.getModifyInstanceAttribute(); + ModifyInstanceAttributeTypeChoice_type0 mia = modifyInstanceAttribute2.getModifyInstanceAttributeTypeChoice_type0(); + + request.setInstanceId(modifyInstanceAttribute2.getInstanceId()); + + // we only support instanceType and userData + if (mia.getInstanceType() != null) { + request.setInstanceType(mia.getInstanceType().getValue()); + } else if (mia.getUserData() != null) { + request.setUserData(mia.getUserData().getValue()); + } else { + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing required parameter - InstanceType/UserData should be provided"); + } + return toModifyInstanceAttributeResponse(engine.modifyInstanceAttribute(request)); + } + private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request, String operation){ EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission(); @@ -835,26 +878,20 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { response.setUnmonitorInstancesResponse( param1 ); return response; } - - - public static DescribeImageAttributeResponse toDescribeImageAttributeResponse(EC2DescribeImagesResponse engineResponse) { - DescribeImageAttributeResponse response = new DescribeImageAttributeResponse(); - DescribeImageAttributeResponseType param1 = new DescribeImageAttributeResponseType(); - - EC2Image[] imageSet = engineResponse.getImageSet(); - if ( 0 < imageSet.length ) { - DescribeImageAttributeResponseTypeChoice_type0 param2 = new DescribeImageAttributeResponseTypeChoice_type0(); - NullableAttributeValueType param3 = new NullableAttributeValueType(); - param3.setValue( imageSet[0].getDescription()); - param2.setDescription( param3 ); - param1.setDescribeImageAttributeResponseTypeChoice_type0( param2 ); - param1.setImageId( imageSet[0].getId()); - } - - param1.setRequestId( UUID.randomUUID().toString()); - response.setDescribeImageAttributeResponse( param1 ); - return response; - } + + /** + * @param modifyInstanceAttribute + * @return + */ + public static ModifyInstanceAttributeResponse toModifyInstanceAttributeResponse(Boolean status) { + ModifyInstanceAttributeResponse miat = new ModifyInstanceAttributeResponse(); + + ModifyInstanceAttributeResponseType param = new ModifyInstanceAttributeResponseType(); + param.set_return(status); + param.setRequestId(UUID.randomUUID().toString()); + miat.setModifyInstanceAttributeResponse(param); + return miat; + } public static DescribeImageAttributeResponse toDescribeImageAttributeResponse(EC2ImageAttributes engineResponse) { DescribeImageAttributeResponse response = new DescribeImageAttributeResponse(); @@ -929,7 +966,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { DescribeImagesResponseItemType param3 = new DescribeImagesResponseItemType(); param3.setImageId( images[i].getId()); param3.setImageLocation( "" ); - param3.setImageState( (images[i].getIsReady() ? "available" : "unavailable" )); + param3.setImageState( images[i].getState()); param3.setImageOwnerId(ownerId); param3.setIsPublic( images[i].getIsPublic()); @@ -941,16 +978,14 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { String description = images[i].getDescription(); param3.setDescription( (null == description ? "" : description)); - - if (null == description) param3.setArchitecture( "" ); - else if (-1 != description.indexOf( "x86_64" )) param3.setArchitecture( "x86_64" ); - else if (-1 != description.indexOf( "i386" )) param3.setArchitecture( "i386" ); - else param3.setArchitecture( "" ); - - param3.setImageType( "machine" ); + + param3.setArchitecture( images[i].getArchitecture()); + + param3.setImageType( images[i].getImageType()); param3.setKernelId( "" ); param3.setRamdiskId( "" ); param3.setPlatform( "" ); + param3.setHypervisor( images[i].getHypervisor()); StateReasonType param6 = new StateReasonType(); param6.setCode( "" ); @@ -1268,8 +1303,29 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { return tfs; } + private EC2ImageFilterSet toImageFilterSet( FilterSetType fst ) { + EC2ImageFilterSet ifs = new EC2ImageFilterSet(); + + FilterType[] items = fst.getItem(); + if (items != null) { + for (FilterType item : items) { + EC2Filter oneFilter = new EC2Filter(); + String filterName = item.getName(); + oneFilter.setName( filterName ); + + ValueSetType vft = item.getValueSet(); + ValueType[] valueItems = vft.getItem(); + for (ValueType valueItem : valueItems) { + oneFilter.addValueEncoded( valueItem.getValue()); + } + ifs.addFilter( oneFilter ); + } + } + return ifs; + } + // toMethods - public static DescribeVolumesResponse toDescribeVolumesResponse( EC2DescribeVolumesResponse engineResponse ) + public static DescribeVolumesResponse toDescribeVolumesResponse( EC2DescribeVolumesResponse engineResponse, EC2Engine engine ) { DescribeVolumesResponse response = new DescribeVolumesResponse(); DescribeVolumesResponseType param1 = new DescribeVolumesResponseType(); @@ -1300,8 +1356,8 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { AttachmentSetItemResponseType param5 = new AttachmentSetItemResponseType(); param5.setVolumeId(vol.getId().toString()); param5.setInstanceId(vol.getInstanceId().toString()); - String devicePath = engine.cloudDeviceIdToDevicePath( vol.getHypervisor(), vol.getDeviceId()); - param5.setDevice( devicePath ); + String devicePath = engine.cloudDeviceIdToDevicePath( vol.getHypervisor(), vol.getDeviceId()); + param5.setDevice( devicePath ); param5.setStatus(vol.getAttachmentState()); if (vol.getAttached() == null) { param5.setAttachTime( cal ); @@ -1834,7 +1890,10 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { param1.setVolumeId( engineResponse.getId().toString()); Long volSize = new Long( engineResponse.getSize()); param1.setSize( volSize.toString()); - param1.setSnapshotId( "" ); + if (engineResponse.getSnapshotId() != null) + param1.setSnapshotId( engineResponse.getSnapshotId() ); + else + param1.setSnapshotId( "" ); param1.setAvailabilityZone( engineResponse.getZoneName()); if ( null != engineResponse.getState()) param1.setStatus( engineResponse.getState()); @@ -2461,10 +2520,6 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public ImportVolumeResponse importVolume(ImportVolume importVolume) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } - - public ModifyInstanceAttributeResponse modifyInstanceAttribute(ModifyInstanceAttribute modifyInstanceAttribute) { - throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); - } public ModifySnapshotAttributeResponse modifySnapshotAttribute(ModifySnapshotAttribute modifySnapshotAttribute) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java index 1823b26218c..153fdde86df 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java @@ -26,6 +26,9 @@ import java.util.Map; import org.apache.log4j.Logger; +import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; + public class EC2AddressFilterSet { protected final static Logger logger = Logger.getLogger(EC2KeyPairFilterSet.class); @@ -43,16 +46,9 @@ public class EC2AddressFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) { - // Changing this to silently ignore - logger.error("Unsupported filter [" + filterName + "] - 1"); - return; - } - - if (null != value && value.equalsIgnoreCase( "null" )) { - logger.error("Unsupported filter [" + filterName + "] - 2"); - return; - } + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java index aa3897a4bf6..7dba8ab009e 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java @@ -26,6 +26,7 @@ import java.util.Map; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2AvailabilityZonesFilterSet { @@ -43,11 +44,9 @@ public class EC2AvailabilityZonesFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeImages.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeImages.java index 9c51b68df7f..96f2a85ffe2 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeImages.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeImages.java @@ -24,6 +24,7 @@ public class EC2DescribeImages { private List executableBySet = new ArrayList();; // a list of strings identifying users private List imageSet = new ArrayList(); // a list of AMI id's private List ownersSet = new ArrayList(); // a list of AMI owner id's + private EC2ImageFilterSet ifs = null; public EC2DescribeImages() { } @@ -51,4 +52,13 @@ public class EC2DescribeImages { public String[] getOwnersSet() { return ownersSet.toArray(new String[0]); } + + public EC2ImageFilterSet getFilterSet() { + return ifs; + } + + public void setFilterSet( EC2ImageFilterSet param ) { + ifs = param; + } + } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java index e92f845f2b1..1859bb807e4 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java @@ -25,12 +25,11 @@ import java.security.SignatureException; import java.sql.SQLException; import java.text.ParseException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.UUID; import javax.inject.Inject; @@ -67,7 +66,6 @@ import com.cloud.stack.models.CloudStackPasswordData; import com.cloud.stack.models.CloudStackResourceLimit; import com.cloud.stack.models.CloudStackResourceTag; import com.cloud.stack.models.CloudStackSecurityGroup; -import com.cloud.stack.models.CloudStackSecurityGroupIngress; import com.cloud.stack.models.CloudStackSnapshot; import com.cloud.stack.models.CloudStackTemplate; import com.cloud.stack.models.CloudStackTemplatePermission; @@ -227,7 +225,7 @@ public class EC2Engine extends ManagerBase { return true; } catch(Exception e) { logger.error("Validate account failed!"); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new EC2ServiceException(ClientError.AuthFailure, "User not authorised"); } } @@ -247,8 +245,9 @@ public class EC2Engine extends ManagerBase { return false; } catch( Exception e ) { logger.error( "EC2 CreateSecurityGroup - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return false; } /** @@ -266,8 +265,9 @@ public class EC2Engine extends ManagerBase { return false; } catch( Exception e ) { logger.error( "EC2 DeleteSecurityGroup - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return false; } /** @@ -276,19 +276,19 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeSecurityGroupsResponse describeSecurityGroups(EC2DescribeSecurityGroups request) - { + public EC2DescribeSecurityGroupsResponse describeSecurityGroups(EC2DescribeSecurityGroups request) { + EC2DescribeSecurityGroupsResponse response = new EC2DescribeSecurityGroupsResponse(); try { - EC2DescribeSecurityGroupsResponse response = listSecurityGroups( request.getGroupSet()); + response = listSecurityGroups( request.getGroupSet()); EC2GroupFilterSet gfs = request.getFilterSet(); - - if ( null == gfs ) - return response; - else return gfs.evaluate( response ); + if ( gfs != null ) { + response = gfs.evaluate( response ); + } } catch( Exception e ) { logger.error( "EC2 DescribeSecurityGroups - ", e); - throw new EC2ServiceException(ServerError.InternalError, "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -300,7 +300,6 @@ public class EC2Engine extends ManagerBase { */ public boolean revokeSecurityGroup( EC2AuthorizeRevokeSecurityGroup request ) { - if (null == request.getName()) throw new EC2ServiceException(ServerError.InternalError, "Name is a required parameter"); try { String[] groupSet = new String[1]; groupSet[0] = request.getName(); @@ -310,6 +309,9 @@ public class EC2Engine extends ManagerBase { EC2DescribeSecurityGroupsResponse response = listSecurityGroups( groupSet ); EC2SecurityGroup[] groups = response.getGroupSet(); + if ( groups.length == 0 ) { + throw new Exception("Unable to find security group name"); + } for (EC2SecurityGroup group : groups) { EC2IpPermission[] perms = group.getIpPermissionSet(); @@ -320,17 +322,16 @@ public class EC2Engine extends ManagerBase { } if (null == ruleId) - throw new EC2ServiceException(ClientError.InvalidGroup_NotFound, "Cannot find matching ruleid."); - + throw new Exception("Specified Ip permission is invalid"); CloudStackInfoResponse resp = getApi().revokeSecurityGroupIngress(ruleId); if (resp != null) { return resp.getSuccess(); } - return false; } catch( Exception e ) { logger.error( "EC2 revokeSecurityGroupIngress" + " - " + e.getMessage()); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); - } + handleException(e); + } + return false; } /** @@ -338,10 +339,7 @@ public class EC2Engine extends ManagerBase { * * @param request - ip permission parameters */ - public boolean authorizeSecurityGroup(EC2AuthorizeRevokeSecurityGroup request ) - { - if (null == request.getName()) throw new EC2ServiceException(ServerError.InternalError, "Name is a required parameter"); - + public boolean authorizeSecurityGroup(EC2AuthorizeRevokeSecurityGroup request ) { EC2IpPermission[] items = request.getIpPermissionSet(); try { @@ -374,7 +372,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error( "EC2 AuthorizeSecurityGroupIngress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } return true; } @@ -444,13 +442,14 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeSnapshotsResponse handleRequest( EC2DescribeSnapshots request ) + public EC2DescribeSnapshotsResponse describeSnapshots( EC2DescribeSnapshots request ) { + EC2DescribeSnapshotsResponse response = new EC2DescribeSnapshotsResponse(); EC2SnapshotFilterSet sfs = request.getFilterSet(); EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet(); try { - EC2DescribeSnapshotsResponse response = listSnapshots( request.getSnapshotSet(), + response = listSnapshots( request.getSnapshotSet(), getResourceTags(tagKeyValueSet)); if (response == null) { return new EC2DescribeSnapshotsResponse(); @@ -475,17 +474,14 @@ public class EC2Engine extends ManagerBase { } snap.setVolumeSize(size); } - if ( null == sfs ) - return response; - else return sfs.evaluate( response ); - } catch( EC2ServiceException error ) { - logger.error( "EC2 DescribeSnapshots - ", error); - throw error; - + if (sfs != null) { + response = sfs.evaluate( response ); + } } catch( Exception e ) { logger.error( "EC2 DescribeSnapshots - ", e); - throw new EC2ServiceException(ServerError.InternalError, "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -495,14 +491,12 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Snapshot createSnapshot( String volumeId ) { + EC2Snapshot ec2Snapshot = new EC2Snapshot(); try { - CloudStackSnapshot snap = getApi().createSnapshot(volumeId, null, null, null); if (snap == null) { - throw new EC2ServiceException(ServerError.InternalError, "Unable to create snapshot!"); + throw new Exception("Unable to create snapshot"); } - EC2Snapshot ec2Snapshot = new EC2Snapshot(); - ec2Snapshot.setId(snap.getId()); ec2Snapshot.setName(snap.getName()); ec2Snapshot.setType(snap.getSnapshotType()); @@ -518,12 +512,11 @@ public class EC2Engine extends ManagerBase { Long sizeInGB = vols.get(0).getSize().longValue()/1073741824; ec2Snapshot.setVolumeSize(sizeInGB); } - - return ec2Snapshot; } catch( Exception e ) { logger.error( "EC2 CreateSnapshot - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return ec2Snapshot; } /** @@ -543,8 +536,9 @@ public class EC2Engine extends ManagerBase { return false; } catch(Exception e) { logger.error( "EC2 DeleteSnapshot - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } @@ -595,15 +589,11 @@ public class EC2Engine extends ManagerBase { } return false; } - } catch (Exception e) { logger.error( "EC2 modifyImageAttribute - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } - return false; - - } public EC2ImageAttributes describeImageAttribute(EC2DescribeImageAttribute request) { @@ -632,7 +622,7 @@ public class EC2Engine extends ManagerBase { } catch (Exception e) { logger.error( "EC2 describeImageAttribute - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } return imageAtts; @@ -646,18 +636,18 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2PasswordData getPasswordData(String instanceId) { + EC2PasswordData passwdData = new EC2PasswordData(); try { CloudStackPasswordData resp = getApi().getVMPassword(instanceId); - EC2PasswordData passwdData = new EC2PasswordData(); if (resp != null) { passwdData.setInstanceId(instanceId); passwdData.setEncryptedPassword(resp.getEncryptedpassword()); } - return passwdData; } catch(Exception e) { logger.error("EC2 GetPasswordData - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return passwdData; } /** @@ -667,18 +657,17 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeKeyPairsResponse describeKeyPairs( EC2DescribeKeyPairs request ) { + EC2DescribeKeyPairsResponse response = new EC2DescribeKeyPairsResponse(); try { - EC2DescribeKeyPairsResponse response = listKeyPairs(request.getKeyNames()); + response = listKeyPairs(request.getKeyNames()); EC2KeyPairFilterSet kfs = request.getKeyFilterSet(); - - if (kfs == null) - return response; - else - return kfs.evaluate(response); + if (kfs != null) + response = kfs.evaluate(response); } catch(Exception e) { logger.error("EC2 DescribeKeyPairs - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -688,17 +677,18 @@ public class EC2Engine extends ManagerBase { * @return */ public boolean deleteKeyPair( EC2DeleteKeyPair request ) { + CloudStackInfoResponse resp = new CloudStackInfoResponse(); + String keyPairName = request.getKeyName(); try { - CloudStackInfoResponse resp = getApi().deleteSSHKeyPair(request.getKeyName(), null, null); + resp = getApi().deleteSSHKeyPair(keyPairName, null, null); if (resp == null) { throw new Exception("Ivalid CloudStack API response"); } - - return resp.getSuccess(); } catch(Exception e) { logger.error("EC2 DeleteKeyPair - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return resp.getSuccess(); } /** @@ -708,22 +698,21 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2SSHKeyPair createKeyPair(EC2CreateKeyPair request) { + String keyPairName = request.getKeyName(); + EC2SSHKeyPair response = new EC2SSHKeyPair(); try { - CloudStackKeyPair resp = getApi().createSSHKeyPair(request.getKeyName(), null, null); + CloudStackKeyPair resp = getApi().createSSHKeyPair(keyPairName, null, null); if (resp == null) { throw new Exception("Ivalid CloudStack API response"); } - - EC2SSHKeyPair response = new EC2SSHKeyPair(); response.setFingerprint(resp.getFingerprint()); response.setKeyName(resp.getName()); response.setPrivateKey(resp.getPrivatekey()); - - return response; } catch (Exception e) { logger.error("EC2 CreateKeyPair - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -733,22 +722,20 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2SSHKeyPair importKeyPair( EC2ImportKeyPair request ) { + EC2SSHKeyPair response = new EC2SSHKeyPair(); try { CloudStackKeyPair resp = getApi().registerSSHKeyPair(request.getKeyName(), request.getPublicKeyMaterial()); if (resp == null) { throw new Exception("Ivalid CloudStack API response"); } - - EC2SSHKeyPair response = new EC2SSHKeyPair(); response.setFingerprint(resp.getFingerprint()); response.setKeyName(resp.getName()); response.setPrivateKey(resp.getPrivatekey()); - - return response; } catch (Exception e) { logger.error("EC2 ImportKeyPair - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -758,18 +745,17 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeAddressesResponse describeAddresses( EC2DescribeAddresses request ) { + EC2DescribeAddressesResponse response = new EC2DescribeAddressesResponse(); try { - EC2DescribeAddressesResponse response = listAddresses(request.getPublicIpsSet()); + response = listAddresses(request.getPublicIpsSet()); EC2AddressFilterSet afs = request.getFilterSet(); - - if (afs ==null) - return response; - else - return afs.evaluate(response); + if (afs != null) + response = afs.evaluate(response); } catch(Exception e) { logger.error("EC2 DescribeAddresses - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -782,7 +768,7 @@ public class EC2Engine extends ManagerBase { try { List cloudIps = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null); if (cloudIps == null) - throw new EC2ServiceException(ServerError.InternalError, "Specified ipAddress doesn't exist"); + throw new Exception("Specified ipAddress doesn't exist"); CloudStackIpAddress cloudIp = cloudIps.get(0); CloudStackInfoResponse resp = getApi().disassociateIpAddress(cloudIp.getId()); if (resp != null) { @@ -790,7 +776,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error("EC2 ReleaseAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } return false; } @@ -805,13 +791,13 @@ public class EC2Engine extends ManagerBase { try { List cloudIps = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null); if (cloudIps == null) - throw new EC2ServiceException(ServerError.InternalError, "Specified ipAddress doesn't exist"); + throw new Exception("Specified ipAddress doesn't exist"); CloudStackIpAddress cloudIp = cloudIps.get(0); List vmList = getApi().listVirtualMachines(null, null, true, null, null, null, null, request.getInstanceId(), null, null, null, null, null, null, null, null, null); if (vmList == null || vmList.size() == 0) { - throw new EC2ServiceException(ServerError.InternalError, "Specified instance-id doesn't exist"); + throw new Exception("Instance not found"); } CloudStackUserVm cloudVm = vmList.get(0); @@ -821,7 +807,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error( "EC2 AssociateAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } return false; } @@ -836,7 +822,7 @@ public class EC2Engine extends ManagerBase { try { List cloudIps = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null); if (cloudIps == null) - throw new EC2ServiceException(ServerError.InternalError, "Specified ipAddress doesn't exist"); + throw new Exception("Specified ipAddress doesn't exist"); CloudStackIpAddress cloudIp = cloudIps.get(0); CloudStackInfoResponse resp = getApi().disableStaticNat(cloudIp.getId()); @@ -845,7 +831,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error( "EC2 DisassociateAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } return false; } @@ -856,10 +842,9 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2Address allocateAddress() - { + public EC2Address allocateAddress() { + EC2Address ec2Address = new EC2Address(); try { - EC2Address ec2Address = new EC2Address(); // this gets our networkId CloudStackAccount caller = getCurrentAccount(); @@ -881,12 +866,11 @@ public class EC2Engine extends ManagerBase { } else { ec2Address.setIpAddress(resp.getIpAddress()); } - - return ec2Address; } catch(Exception e) { logger.error( "EC2 AllocateAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return ec2Address; } /** @@ -896,25 +880,26 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeImagesResponse describeImages(EC2DescribeImages request) - { + public EC2DescribeImagesResponse describeImages(EC2DescribeImages request) { EC2DescribeImagesResponse images = new EC2DescribeImagesResponse(); - try { String[] templateIds = request.getImageSet(); + EC2ImageFilterSet ifs = request.getFilterSet(); - if ( 0 == templateIds.length ) { - return listTemplates(null, images); + if ( templateIds.length == 0 ) { + images = listTemplates(null, images); + } else { + for (String s : templateIds) { + images = listTemplates(s, images); + } } - for (String s : templateIds) { - images = listTemplates(s, images); - } - return images; - + if (ifs != null) + return ifs.evaluate(images); } catch( Exception e ) { logger.error( "EC2 DescribeImages - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return images; } /** @@ -934,10 +919,9 @@ public class EC2Engine extends ManagerBase { */ public EC2CreateImageResponse createImage(EC2CreateImage request) { - EC2CreateImageResponse response = null; + EC2CreateImageResponse response = new EC2CreateImageResponse(); boolean needsRestart = false; String volumeId = null; - try { // [A] Creating a template from a VM volume should be from the ROOT volume // Also for this to work the VM must be in a Stopped state so we 'reboot' it if its not @@ -950,7 +934,7 @@ public class EC2Engine extends ManagerBase { if (vmState.equalsIgnoreCase( "running" ) || vmState.equalsIgnoreCase( "starting" )) { needsRestart = true; if (!stopVirtualMachine( request.getInstanceId() )) - throw new EC2ServiceException(ClientError.IncorrectState, "CreateImage - instance must be in a stopped state"); + throw new Exception("Instance must be in a stopped state"); } volumeId = vol.getId(); break; @@ -971,25 +955,22 @@ public class EC2Engine extends ManagerBase { CloudStackTemplate resp = getApi().createTemplate((request.getDescription() == null ? "" : request.getDescription()), request.getName(), osTypeId, null, null, null, null, null, null, volumeId); if (resp == null || resp.getId() == null) { - throw new EC2ServiceException(ServerError.InternalError, "An upexpected error occurred."); + throw new Exception("Image couldn't be created"); } //if template was created succesfully, create the new image response - response = new EC2CreateImageResponse(); response.setId(resp.getId()); // [C] If we stopped the virtual machine now we need to restart it if (needsRestart) { - if (!startVirtualMachine( request.getInstanceId() )) - throw new EC2ServiceException(ServerError.InternalError, - "CreateImage - restarting instance " + request.getInstanceId() + " failed"); + if (!startVirtualMachine( request.getInstanceId() )) + throw new Exception("Failed to start the stopped instance"); } - return response; - } catch( Exception e ) { logger.error( "EC2 CreateImage - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -998,13 +979,9 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2CreateImageResponse registerImage(EC2RegisterImage request) - { + public EC2CreateImageResponse registerImage(EC2RegisterImage request) { + EC2CreateImageResponse image = new EC2CreateImageResponse(); try { - CloudStackAccount caller = getCurrentAccount(); - if (null == request.getName()) - throw new EC2ServiceException(ClientError.Unsupported, "Missing parameter - name"); - List templates = getApi().registerTemplate((request.getDescription() == null ? request.getName() : request.getDescription()), request.getFormat(), request.getHypervisor(), request.getName(), toOSTypeId(request.getOsTypeName()), request.getLocation(), toZoneId(request.getZoneName(), null), null, null, null, null, null, null, null, null, null); @@ -1012,17 +989,16 @@ public class EC2Engine extends ManagerBase { // technically we will only ever register a single template... for (CloudStackTemplate template : templates) { if (template != null && template.getId() != null) { - EC2CreateImageResponse image = new EC2CreateImageResponse(); image.setId(template.getId().toString()); return image; } } } - return null; } catch( Exception e ) { logger.error( "EC2 RegisterImage - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return image; } /** @@ -1040,8 +1016,9 @@ public class EC2Engine extends ManagerBase { return resp.getSuccess(); } catch( Exception e ) { logger.error( "EC2 DeregisterImage - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } /** @@ -1051,14 +1028,16 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeInstancesResponse describeInstances(EC2DescribeInstances request ) { + EC2DescribeInstancesResponse response = new EC2DescribeInstancesResponse(); try { EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet(); - return listVirtualMachines( request.getInstancesSet(), request.getFilterSet(), + response = listVirtualMachines( request.getInstancesSet(), request.getFilterSet(), getResourceTags(tagKeyValueSet)); } catch( Exception e ) { logger.error( "EC2 DescribeInstances - " ,e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -1067,22 +1046,18 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeAvailabilityZonesResponse handleRequest(EC2DescribeAvailabilityZones request) { + public EC2DescribeAvailabilityZonesResponse describeAvailabilityZones(EC2DescribeAvailabilityZones request) { + EC2DescribeAvailabilityZonesResponse availableZones = new EC2DescribeAvailabilityZonesResponse(); try { - EC2DescribeAvailabilityZonesResponse availableZones = listZones(request.getZoneSet(), null); + availableZones = listZones(request.getZoneSet(), null); EC2AvailabilityZonesFilterSet azfs = request.getFilterSet(); - if ( null == azfs ) - return availableZones; - else - return azfs.evaluate(availableZones); - } catch( EC2ServiceException error ) { - logger.error( "EC2 DescribeAvailabilityZones - ", error); - throw error; - + if ( azfs != null ) + availableZones = azfs.evaluate(availableZones); } catch( Exception e ) { logger.error( "EC2 DescribeAvailabilityZones - " ,e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return availableZones; } /** @@ -1091,7 +1066,7 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeVolumesResponse handleRequest( EC2DescribeVolumes request ) { + public EC2DescribeVolumesResponse describeVolumes( EC2DescribeVolumes request ) { EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse(); EC2VolumeFilterSet vfs = request.getFilterSet(); EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet(); @@ -1103,14 +1078,13 @@ public class EC2Engine extends ManagerBase { for (String s : volumeIds) volumes = listVolumes(s, null, volumes, getResourceTags(tagKeyValueSet) ); } - - if ( null == vfs ) - return volumes; - else return vfs.evaluate( volumes ); + if ( vfs != null ) + volumes = vfs.evaluate( volumes ); } catch( Exception e ) { logger.error( "EC2 DescribeVolumes - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return volumes; } /** @@ -1120,10 +1094,9 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Volume attachVolume( EC2Volume request ) { + EC2Volume resp = new EC2Volume(); try { request.setDeviceId(mapDeviceToCloudDeviceId(request.getDevice())); - EC2Volume resp = new EC2Volume(); - CloudStackVolume vol = getApi().attachVolume(request.getId(), request.getInstanceId(), request.getDeviceId()); if(vol != null) { resp.setAttached(vol.getAttached()); @@ -1140,13 +1113,12 @@ public class EC2Engine extends ManagerBase { resp.setVMState(vol.getVirtualMachineState()); resp.setAttachmentState(mapToAmazonVolumeAttachmentState(vol.getVirtualMachineState())); resp.setZoneName(vol.getZoneName()); - return resp; } - throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occurred." ); } catch( Exception e ) { - logger.error( "EC2 AttachVolume 2 - ", e); - throw new EC2ServiceException( ServerError.InternalError, e.getMessage() != null ? e.getMessage() : e.toString()); - } + logger.error( "EC2 AttachVolume - ", e); + handleException(e); + } + return resp; } /** @@ -1156,10 +1128,27 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Volume detachVolume(EC2Volume request) { + EC2Volume resp = new EC2Volume(); try { - CloudStackVolume vol = getApi().detachVolume(null, request.getId(), null); - EC2Volume resp = new EC2Volume(); + // verifying if instanceId and deviceId provided is valid + EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse(); + volumes = listVolumes(request.getId(), null, volumes, null); + if (volumes != null) { + EC2Volume[] volumeSet = volumes.getVolumeSet(); + if (request.getInstanceId() != null) { + if ( !request.getInstanceId().equalsIgnoreCase(volumeSet[0].getInstanceId()) ) + throw new Exception("Volume is not attached to the Instance"); + } + if (request.getDevice() != null) { + String devicePath = null; + if ( volumeSet[0].getDeviceId() != null ) + devicePath = cloudDeviceIdToDevicePath( volumeSet[0].getHypervisor(), volumeSet[0].getDeviceId()); + if ( !request.getDevice().equalsIgnoreCase(devicePath) ) + throw new Exception("Volume is not attached to the Device"); + } + } + CloudStackVolume vol = getApi().detachVolume(null , request.getId(), null); if(vol != null) { resp.setAttached(vol.getAttached()); resp.setCreated(vol.getCreated()); @@ -1174,14 +1163,12 @@ public class EC2Engine extends ManagerBase { resp.setType(vol.getVolumeType()); resp.setVMState(vol.getVirtualMachineState()); resp.setZoneName(vol.getZoneName()); - return resp; } - - throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occurred." ); } catch( Exception e ) { logger.error( "EC2 DetachVolume - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); - } + handleException(e); + } + return resp; } /** @@ -1191,9 +1178,8 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Volume createVolume( EC2CreateVolume request ) { + EC2Volume resp = new EC2Volume(); try { - - CloudStackAccount caller = getCurrentAccount(); // -> put either snapshotid or diskofferingid on the request String snapshotId = request.getSnapshotId(); Long size = request.getSize(); @@ -1212,7 +1198,6 @@ public class EC2Engine extends ManagerBase { // // -> no volume name is given in the Amazon request but is required in the cloud API CloudStackVolume vol = getApi().createVolume(UUID.randomUUID().toString(), null, diskOfferingId, null, size, snapshotId, toZoneId(request.getZoneName(), null)); if (vol != null) { - EC2Volume resp = new EC2Volume(); resp.setAttached(vol.getAttached()); resp.setCreated(vol.getCreated()); // resp.setDevice(); @@ -1227,13 +1212,12 @@ public class EC2Engine extends ManagerBase { resp.setVMState(vol.getVirtualMachineState()); resp.setAttachmentState("detached"); resp.setZoneName(vol.getZoneName()); - return resp; } - return null; } catch( Exception e ) { logger.error( "EC2 CreateVolume - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); - } + handleException(e); + } + return resp; } /** @@ -1247,14 +1231,12 @@ public class EC2Engine extends ManagerBase { CloudStackInfoResponse resp = getApi().deleteVolume(request.getId()); if(resp != null) { request.setState("deleted"); - return request; } - - throw new EC2ServiceException(ServerError.InternalError, "An unexpected error occurred."); } catch( Exception e ) { - logger.error( "EC2 DeleteVolume 2 - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); - } + logger.error( "EC2 DeleteVolume - ", e); + handleException(e); + } + return request; } /** @@ -1291,9 +1273,9 @@ public class EC2Engine extends ManagerBase { return true; } catch (Exception e){ logger.error( "EC2 Create/Delete Tags - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? - e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } /** @@ -1303,11 +1285,11 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeTagsResponse describeTags (EC2DescribeTags request) { + EC2DescribeTagsResponse tagResponse = new EC2DescribeTagsResponse(); try { - EC2DescribeTagsResponse tagResponse = new EC2DescribeTagsResponse(); + tagResponse = new EC2DescribeTagsResponse(); List resourceTagList = getApi().listTags(null, null, null, true, null); - List tagList = new ArrayList(); if (resourceTagList != null && resourceTagList.size() > 0) { for (CloudStackResourceTag resourceTag: resourceTagList) { EC2ResourceTag tag = new EC2ResourceTag(); @@ -1321,14 +1303,13 @@ public class EC2Engine extends ManagerBase { } EC2TagsFilterSet tfs = request.getFilterSet(); - if (tfs == null) - return tagResponse; - else - return tfs.evaluate(tagResponse); + if (tfs != null) + tagResponse = tfs.evaluate(tagResponse); } catch(Exception e) { logger.error("EC2 DescribeTags - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return tagResponse; } /** @@ -1358,13 +1339,14 @@ public class EC2Engine extends ManagerBase { // -> if some specified VMs where not found we have to tell the caller if (instanceSet.length != vms.length) - throw new EC2ServiceException(ClientError.InvalidAMIID_NotFound, "One or more instanceIds do not exist, other instances rebooted."); + throw new Exception("One or more instanceIds do not exist, other instances rebooted."); return true; } catch( Exception e ) { logger.error( "EC2 RebootInstances - ", e ); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } /** @@ -1380,15 +1362,13 @@ public class EC2Engine extends ManagerBase { int countCreated = 0; try { - CloudStackAccount caller = getCurrentAccount(); - // ugly... canCreateInstances = calculateAllowedInstances(); if (-1 == canCreateInstances) canCreateInstances = request.getMaxCount(); if (canCreateInstances < request.getMinCount()) { logger.info( "EC2 RunInstances - min count too big (" + request.getMinCount() + "), " + canCreateInstances + " left to allocate"); - throw new EC2ServiceException(ClientError.InstanceLimitExceeded ,"Only " + canCreateInstances + " instance(s) left to allocate"); + throw new Exception("Min Count is greater than the number of instances left to allocate"); } if ( canCreateInstances < request.getMaxCount()) @@ -1404,7 +1384,7 @@ public class EC2Engine extends ManagerBase { CloudStackServiceOfferingVO svcOffering = getCSServiceOfferingId(instanceType); if(svcOffering == null){ logger.info("No ServiceOffering found to be defined by name, please contact the administrator "+instanceType ); - throw new EC2ServiceException(ClientError.Unsupported, "instanceType: [" + instanceType + "] not found!"); + throw new Exception("instanceType not found"); } // zone stuff @@ -1413,7 +1393,7 @@ public class EC2Engine extends ManagerBase { List zones = getApi().listZones(null, null, zoneId, null); if (zones == null || zones.size() == 0) { logger.info("EC2 RunInstances - zone [" + request.getZoneName() + "] not found!"); - throw new EC2ServiceException(ClientError.InvalidZone_NotFound, "ZoneId [" + request.getZoneName() + "] not found!"); + throw new Exception("zone not found"); } // we choose first zone? CloudStackZone zone = zones.get(0); @@ -1454,7 +1434,7 @@ public class EC2Engine extends ManagerBase { vm.setIpAddress(resp.getIpAddress()); vm.setAccountName(resp.getAccountName()); vm.setDomainId(resp.getDomainId()); - vm.setHypervisor(resp.getHypervisor()); + vm.setHypervisor( mapToAmazonHypervisorType(resp.getHypervisor()) ); vm.setServiceOffering( svcOffering.getName()); vm.setKeyPairName(resp.getKeyPairName()); instances.addInstance(vm); @@ -1463,19 +1443,17 @@ public class EC2Engine extends ManagerBase { logger.error("Failed to deploy VM number: "+ (i+1) +" due to error: "+e.getMessage()); break; } - } - + } if (0 == countCreated) { // TODO, we actually need to destroy left-over VMs when the exception is thrown - throw new EC2ServiceException(ServerError.InternalError, "Failed to deploy instances" ); + throw new Exception("Insufficient Instance Capacity"); } logger.debug("Could deploy "+ countCreated + " VM's successfully"); - - return instances; } catch( Exception e ) { logger.error( "EC2 RunInstances - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return instances; } /** @@ -1511,11 +1489,11 @@ public class EC2Engine extends ManagerBase { } instances.addInstance(vm); } - return instances; } catch( Exception e ) { logger.error( "EC2 StartInstances - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return instances; } /** @@ -1562,11 +1540,48 @@ public class EC2Engine extends ManagerBase { instances.addInstance(vm); } } - return instances; } catch( Exception e ) { logger.error( "EC2 StopInstances - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() + ", might already be destroyed" : "An unexpected error occurred."); + handleException(e); } + return instances; + } + + /** + * @param request + * @return + * @throws Exception + */ + public boolean modifyInstanceAttribute(EC2ModifyInstanceAttribute request) { + boolean status = true; + String instanceId = request.getInstanceId(); + try { + // AWS requires VM to be in stopped state to modify 'InstanceType' and 'UserData' + EC2DescribeInstancesResponse vmResponse = new EC2DescribeInstancesResponse(); + vmResponse = lookupInstances(instanceId, vmResponse, null); + EC2Instance[] instances = vmResponse.getInstanceSet(); + if ( !instances[0].getState().equalsIgnoreCase("stopped")) { + throw new Exception("Cannot modify, instance should be in stopped state"); + } + + if (request.getInstanceType() != null) { + String instanceType = request.getInstanceType(); + CloudStackServiceOfferingVO svcOffering = getCSServiceOfferingId(instanceType); + if (svcOffering == null) + throw new Exception("instanceType not found"); + CloudStackUserVm userVm = getApi().changeServiceForVirtualMachine(instanceId, svcOffering.getId()); + status = (userVm != null); + } + if (status != false && request.getUserData() != null) { + CloudStackUserVm userVm = getApi().updateVirtualMachine(instanceId, null, null, null, + null, request.getUserData()); + status = (userVm != null); + } + } catch (Exception e) { + logger.error("ModifyInstanceAttribute - ", e); + handleException(e); + } + return status; } /** @@ -1715,7 +1730,7 @@ public class EC2Engine extends ManagerBase { zones = listZones(interestedZones, domainId); if (zones == null || zones.getAvailabilityZoneSet().length == 0) - throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unknown zoneName value - " + zoneName); + throw new Exception("Unknown zoneName value"); EC2AvailabilityZone[] zoneSet = zones.getAvailabilityZoneSet(); return zoneSet[0].getId(); @@ -1727,15 +1742,22 @@ public class EC2Engine extends ManagerBase { * */ - private CloudStackServiceOfferingVO getCSServiceOfferingId(String instanceType){ + private CloudStackServiceOfferingVO getCSServiceOfferingId(String instanceType) throws Exception { try { - if (null == instanceType) instanceType = "m1.small"; + // list of valid values for AWS EC2 instanceType + String[] validInstanceTypes = {"t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge", + "c1.medium", "c1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", + "m3.xlarge", "m3.2xlarge", "hi1.4xlarge", "cc1.4xlarge", "cg1.4xlarge", "cc2.8xlarge"}; + if (instanceType == null) + instanceType = "m1.small"; // default value + else if ( !Arrays.asList(validInstanceTypes).contains(instanceType)) { + throw new Exception("Specified instance type is invalid"); + } return scvoDao.getSvcOfferingByName(instanceType); - } catch(Exception e) { logger.error( "Error while retrieving ServiceOffering information by name - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception("No ServiceOffering found to be defined by name"); } } @@ -1747,7 +1769,7 @@ public class EC2Engine extends ManagerBase { * @return A valid value for the Amazon defined instanceType * @throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException */ - private String serviceOfferingIdToInstanceType( String serviceOfferingId ){ + private String serviceOfferingIdToInstanceType( String serviceOfferingId ) throws Exception { try{ CloudStackServiceOfferingVO offering = scvoDao.getSvcOfferingById(serviceOfferingId); //dao.getSvcOfferingById(serviceOfferingId); @@ -1758,8 +1780,8 @@ public class EC2Engine extends ManagerBase { return offering.getName(); } catch(Exception e) { - logger.error( "sError while retrieving ServiceOffering information by id - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + logger.error( "Error while retrieving ServiceOffering information by id - ", e); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -1780,7 +1802,7 @@ public class EC2Engine extends ManagerBase { return null; } catch(Exception e) { logger.error( "List OS Types - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -1856,7 +1878,7 @@ public class EC2Engine extends ManagerBase { ec2Vm.setIpAddress(cloudVm.getIpAddress()); ec2Vm.setAccountName(cloudVm.getAccountName()); ec2Vm.setDomainId(cloudVm.getDomainId()); - ec2Vm.setHypervisor(cloudVm.getHypervisor()); + ec2Vm.setHypervisor( mapToAmazonHypervisorType(cloudVm.getHypervisor()) ); ec2Vm.setRootDeviceType(cloudVm.getRootDeviceType()); ec2Vm.setRootDeviceId(cloudVm.getRootDeviceId()); ec2Vm.setServiceOffering(serviceOfferingIdToInstanceType(cloudVm.getServiceOfferingId().toString())); @@ -1894,7 +1916,7 @@ public class EC2Engine extends ManagerBase { }else{ if(instanceId != null){ //no such instance found - throw new EC2ServiceException(ServerError.InternalError, "Instance:" + instanceId + " not found"); + throw new Exception("Instance not found"); } } return instances; @@ -1911,7 +1933,7 @@ public class EC2Engine extends ManagerBase { * @return the same object passed in as the "images" parameter modified with one or more * EC2Image objects loaded. */ - private EC2DescribeImagesResponse listTemplates( String templateId, EC2DescribeImagesResponse images ) throws EC2ServiceException { + private EC2DescribeImagesResponse listTemplates( String templateId, EC2DescribeImagesResponse images ) throws Exception { try { List result = new ArrayList(); @@ -1951,8 +1973,22 @@ public class EC2Engine extends ManagerBase { ec2Image.setDescription(temp.getDisplayText()); ec2Image.setOsTypeId(temp.getOsTypeId().toString()); ec2Image.setIsPublic(temp.getIsPublic()); - ec2Image.setIsReady(temp.getIsReady()); + ec2Image.setState( temp.getIsReady() ? "available" : "pending"); ec2Image.setDomainId(temp.getDomainId()); + if ( temp.getHyperVisor().equalsIgnoreCase("xenserver")) + ec2Image.setHypervisor("xen"); + else if ( temp.getHyperVisor().equalsIgnoreCase("ovm")) + ec2Image.setHypervisor( "ovm"); // valid values for hypervisor is 'ovm' and 'xen' + else + ec2Image.setHypervisor(""); + if (temp.getDisplayText() == null) + ec2Image.setArchitecture(""); + else if (temp.getDisplayText().indexOf( "x86_64" ) != -1) + ec2Image.setArchitecture("x86_64"); + else if (temp.getDisplayText().indexOf( "i386" ) != -1) + ec2Image.setArchitecture("i386"); + else + ec2Image.setArchitecture(""); List resourceTags = temp.getTags(); for(CloudStackKeyValue resourceTag : resourceTags) { EC2TagKeyValue param = new EC2TagKeyValue(); @@ -1967,7 +2003,7 @@ public class EC2Engine extends ManagerBase { return images; } catch(Exception e) { logger.error( "List Templates - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2018,7 +2054,7 @@ public class EC2Engine extends ManagerBase { return groupSet; } catch(Exception e) { logger.error( "List Security Groups - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2050,7 +2086,7 @@ public class EC2Engine extends ManagerBase { return keyPairSet; } catch(Exception e) { logger.error( "List Keypairs - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2083,7 +2119,7 @@ public class EC2Engine extends ManagerBase { return addressSet; } catch(Exception e) { logger.error( "List Addresses - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception(e.getMessage() != null ? e.getMessage() : e.toString()); } } @@ -2130,7 +2166,7 @@ public class EC2Engine extends ManagerBase { return snapshotSet; } catch(Exception e) { logger.error( "List Snapshots - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception(e.getMessage() != null ? e.getMessage() : e.toString()); } } @@ -2280,7 +2316,7 @@ public class EC2Engine extends ManagerBase { } // if we get this far and haven't returned already return an error - throw new EC2ServiceException(ServerError.InternalError, "Unable to find an appropriate network for account " + caller.getName()); + throw new Exception("Unable to find an appropriate network for account "); } /** @@ -2326,12 +2362,12 @@ public class EC2Engine extends ManagerBase { /** * Finds the defaultZone marked for the account */ - private String getDefaultZoneId(String accountId) { + private String getDefaultZoneId(String accountId) throws Exception { try { return accDao.getDefaultZoneId(accountId); } catch(Exception e) { logger.error( "Error while retrieving Account information by id - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception("Unable to retrieve account account information"); } } @@ -2382,7 +2418,7 @@ public class EC2Engine extends ManagerBase { * @param device string * @return deviceId value */ - private String mapDeviceToCloudDeviceId( String device ) + private String mapDeviceToCloudDeviceId( String device ) throws Exception { if (device.equalsIgnoreCase( "/dev/sdb" )) return "1"; else if (device.equalsIgnoreCase( "/dev/sdc" )) return "2"; @@ -2411,7 +2447,7 @@ public class EC2Engine extends ManagerBase { else if (device.equalsIgnoreCase( "xvdi" )) return "8"; else if (device.equalsIgnoreCase( "xvdj" )) return "9"; - else throw new EC2ServiceException( ClientError.Unsupported, device + " is not supported" ); + else throw new Exception("Device is not supported"); } /** @@ -2480,6 +2516,21 @@ public class EC2Engine extends ManagerBase { return (resourceType.toLowerCase()); } + /** + * Map CloudStack hypervisor to CloudStack hypervisor + * + * @param CloudStack hypervisor + * @return Amazon hypervisor + */ + private String mapToAmazonHypervisorType( String hypervisor) { + if (hypervisor.equalsIgnoreCase("Xenserver")) + return("xen"); + else if(hypervisor.equalsIgnoreCase("Ovm")) + return("ovm"); + else + return (""); + } + /** * Stop an instance * Wait until one specific VM has stopped @@ -2496,7 +2547,7 @@ public class EC2Engine extends ManagerBase { return resp != null; } catch(Exception e) { logger.error( "StopVirtualMachine - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2515,7 +2566,7 @@ public class EC2Engine extends ManagerBase { return resp != null; } catch(Exception e) { logger.error("StartVirtualMachine - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2544,4 +2595,269 @@ public class EC2Engine extends ManagerBase { } return resourceTags; } + + private void handleException( Exception e) { + String[] error = e.getMessage().split("Error Code - "); + String errorMessage = error[0]; + if (error.length == 2) { // error code has been supplied + int errorCode = Integer.parseInt(error[1]); + if (errorCode == 431) { + if ( errorMessage.contains("Object vm_instance(uuid:") && errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidInstanceID_NotFound, + "Specified Instance ID does not exist"); + } else if ( errorMessage.contains("Unable to find security group by name") || + errorMessage.contains("Unable to find security group") || + ( errorMessage.contains("Object security_group(uuid:") && errorMessage.contains(") does not exist") ) || + errorMessage.contains("Unable to find group by name ") ) { + throw new EC2ServiceException( ClientError.InvalidGroup_NotFound, + "Specified Security Group does not exist"); + } else if ( errorMessage.contains("Invalid port numbers") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified Port value is invalid"); + } else if (errorMessage.contains("Nonexistent account") && errorMessage.contains("when trying to authorize security group rule for security group") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified account doesn't exist"); + } else if ( errorMessage.contains("Nonexistent group") && errorMessage.contains("unable to authorize security group rule") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified source security group doesn't exist"); + } else if ( errorMessage.contains("Invalid protocol") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified protocol is invalid"); + } else if ( errorMessage.contains("is an Invalid CIDR") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified CIDR is invalid"); + }else if ( errorMessage.contains("Nonexistent account") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified Account name is invalid"); + } else if ( errorMessage.contains("Object volumes(uuid:") && errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidVolume_NotFound, + "Specified Volume ID doesn't exist"); + } else if ( errorMessage.contains("Object snapshots(uuid:") && errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidSnapshot_NotFound, + "Specified Snapshot ID doesn't exist"); + } else if ( (errorMessage.contains("A key pair with name '") && errorMessage.contains("' does not exist")) || + (errorMessage.contains("A key pair with name '") && errorMessage.contains("' was not found")) ) { + throw new EC2ServiceException( ClientError.InvalidKeyPair_NotFound, + "Specified Key pair name is invalid"); + } else if ( errorMessage.contains("A key pair with name '") && errorMessage.contains("' already exists") ) { + throw new EC2ServiceException( ClientError.InvalidKeyPair_Duplicate, + "Specified Key pair already exists"); + } else if ( errorMessage.contains("Unknown zoneName value") ) { + throw new EC2ServiceException( ClientError.InvalidZone_NotFound, + "Specified AvailabilityZone name is invalid"); + } else if ( errorMessage.contains("specify a volume that is not attached to any VM") ) { + throw new EC2ServiceException( ClientError.DependencyViolation, + "Specified Volume is attached to a VM"); + } else if ( errorMessage.contains("Object vm_template(uuid: ")&& errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidAMIID_NotFound, + "Specified Image ID does not exist"); + } else if ( errorMessage.contains("unable to find template by id") ) { + throw new EC2ServiceException( ClientError.InvalidAMIID_NotFound, + "Specified Image ID does not exist"); + } else if ( errorMessage.contains("a group with name") && errorMessage.contains("already exists") ) { + throw new EC2ServiceException( ClientError.InvalidGroup_Duplicate, + "Specified Security Group already exists"); + } else if ( errorMessage.contains("specified volume is not attached to a VM") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Specified volume is not in the correct state 'attached' for detachment"); + } else if ( errorMessage.contains("Snapshot with specified snapshotId is not in BackedUp state yet and can't be used for volume creation") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Specified snapshot is not in the correct state 'completed' for volume creation"); + } else if ( errorMessage.contains("Can't delete snapshotshot 4 due to it is not in BackedUp Status") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Specified snapshot is not in the correct state 'completed' for deletion"); + } else if ( errorMessage.contains("Public key is invalid") ) { + throw new EC2ServiceException( ClientError.InvalidKeyPair_Format, + "Format of the specified key is invalid"); + } else if ( errorMessage.contains("Invalid resource type") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified resourceId is invalid"); + } else if ( errorMessage.contains("Unable to find tags by parameters specified") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified resourceTag for the specified resourceId doesn't exist"); + } else if ( errorMessage.contains("Failed to enable static nat for the ip address with specified ipId " + + "as vm with specified vmId is already associated with specified currentIp") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified publicIp is already associated to the specified VM"); + } else if ( errorMessage.contains("Specified IP address id is not associated with any vm Id") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified publicIp is not associated to any VM"); + } else if ( errorMessage.contains("specify a VM that is either running or stopped") ) { + throw new EC2ServiceException( ClientError.IncorrectInstanceState, + "Unable to attach. Specified instances is in an incorrect state"); + } else if ( errorMessage.contains("specify a valid data volume") ) { + throw new EC2ServiceException( ClientError.InvalidVolume_NotFound, + "Specified volume doen't exist"); + } else if ( errorMessage.contains("VolumeId is not in Ready state, but in state Allocated. Cannot take snapshot") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Cannot take snapshot. Specified volume is not in the correct state"); + } else if ( errorMessage.contains("Can't delete snapshot") && errorMessage.contains("it is not in BackedUp Status") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Cannot delete snapshot. Specified snapshot is not in the correct state"); + } else if ( errorMessage.contains("Invalid port range") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "The specified port range is invalid"); + } else if ( errorMessage.contains("specify a valid User VM") ) { + throw new EC2ServiceException( ClientError.InvalidInstanceID_NotFound, + "Specified instance is invalid"); + } else if ( errorMessage.contains("No password for VM with specified id found") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "No password for VM with the specified id found"); + } else if ( errorMessage.contains("make sure the virtual machine is stopped and not in an error state before upgrading") ) { + throw new EC2ServiceException( ClientError.IncorrectInstanceState, + "Unable to modify. Specified instances is not in the correct state 'Stopped'"); + } else if ( errorMessage.contains("Not upgrading vm") && errorMessage.contains("it already has the" + + " requested service offering") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unable to modify. Specified instance already has the requested instanceType"); + } + // Can't enable static, ip address with specified id is a sourceNat ip address ? + else { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "The value supplied for a parameter is invalid"); + } + } + else if (errorCode == 536) { + if ( errorMessage.contains("Cannot delete group when it's in use by virtual machines") ) { + throw new EC2ServiceException( ClientError.InvalidGroup_InUse, + "Group is in use by a virtual machine"); + } else { + throw new EC2ServiceException( ClientError.DependencyViolation, + "Specified resource is in use"); + } + } + else if (errorCode == 531) { + if ( errorMessage.contains("Acct") && errorMessage.contains("does not have permission to launch" + + " instances from Tmpl") ) { + throw new EC2ServiceException( ClientError.AuthFailure, + "User not authorized to operate on the specified AMI"); + } else { + throw new EC2ServiceException( ClientError.AuthFailure, "User not authorized"); + } + } + else if (errorCode == 530) { + if ( errorMessage.contains("deviceId") && errorMessage.contains("is used by VM") ) { + throw new EC2ServiceException( ClientError.InvalidDevice_InUse, + "Specified Device is already being used by the VM"); + } else if (errorMessage.contains("Entity already exists") ){ + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified resource tag already exists"); + } else if ( errorMessage.contains("Template") && errorMessage.contains("has not been completely downloaded") ){ + throw new EC2ServiceException( ClientError.InvalidAMIID_NotFound, + "Specified ImageId is unavailable"); + } else if ( errorMessage.contains("cannot stop VM") && errorMessage.contains("when it is in state Starting") ){ + throw new EC2ServiceException( ClientError.IncorrectInstanceState, + "Unable to stop. One or more of the specified instances is in an incorrect state 'pending'"); + } else if ( errorMessage.contains("Failed to authorize security group ingress rule(s)") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, "Specified Ip-permission is invalid" + + " or the Ip-permission already exists"); + } else if ( errorMessage.contains("Failed to reboot vm instance") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Unable to reboot. One or more of the specified instances is in an incorrect state"); + } else if ( errorMessage.contains("specify a template that is not currently being downloaded") ) { + throw new EC2ServiceException(ClientError.IncorrectState, + "Unable to deregister. Image is not in the correct state 'available'"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } + else if (errorCode == 534) { + if ( errorMessage.contains("Maximum number of resources of type 'volume' for account") + && errorMessage.contains("has been exceeded") ) { + throw new EC2ServiceException( ClientError.VolumeLimitExceeded, + "You have reached the limit on the number of volumes that can be created"); + } else if ( errorMessage.contains("Maximum number of resources of type 'public_ip' for account") + && errorMessage.contains("has been exceeded") ) { + throw new EC2ServiceException( ClientError.AddressLimitExceeded, + "You have reached the limit on the number of elastic ip addresses your account can have"); + } else if ( errorMessage.contains("Unable to apply save userdata entry on router") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "The value supplied for parameter UserData is invalid"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } + else if (errorCode == 533) { + if ( errorMessage.contains("Unable to create a deployment for VM") ) { + throw new EC2ServiceException( ClientError.InsufficientInstanceCapacity, + "There is insufficient capacity available to deploy a VM"); + } else if ( errorMessage.contains("Insufficient address capacity") ) { + throw new EC2ServiceException( ServerError.InsufficientAddressCapacity, + "Not enough available addresses to satisfy your minimum request"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "There is insufficient capacity"); + } + } else if (errorCode == 401) { + if ( errorMessage.contains("Unauthorized") ) { + throw new EC2ServiceException(ClientError.AuthFailure, "User not authorised"); + } else { + throw new EC2ServiceException(ClientError.AuthFailure, "User not authorised"); + } + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } else { + if ( errorMessage.contains("Unknown zoneName value") ) { + throw new EC2ServiceException( ClientError.InvalidZone_NotFound, + "AvailabilityZone name is invalid"); + } else if ( errorMessage.contains("No ServiceOffering found to be defined by name") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, "Specified InstanceType is invalid"); + } else if ( errorMessage.contains("Specified Ip permission is invalid") ) { + throw new EC2ServiceException(ClientError.InvalidPermission_Malformed, "Specified Ip permission is invalid"); + } else if ( errorMessage.contains("One or more instanceIds do not exist, other instances rebooted") ) { + throw new EC2ServiceException(ClientError.InvalidInstanceID_NotFound, + "One or more InstanceId doesn't exist, other instances rebooted"); + } else if ( errorMessage.contains("Device is not supported") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, + "Value specified for parameter Device is invalid"); + } else if ( errorMessage.contains("Volume is not attached to the Instance") ) { + throw new EC2ServiceException(ClientError.InvalidAttachment_NotFound, + "Specified Volume is not attached to the specified Instance"); + } else if ( errorMessage.contains("Volume is not attached to the Device") ) { + throw new EC2ServiceException(ClientError.InvalidAttachment_NotFound, + "Specified Volume is not attached to the specified device"); + } else if ( errorMessage.contains("Unable to create snapshot") ) { + throw new EC2ServiceException(ServerError.InternalError, + "Unable to create snapshot"); + } else if ( errorMessage.contains("Instance must be in stopped state") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Specified instance is not in the correct state 'stopped'"); + } else if ( errorMessage.contains("Image couldn't be created") ) { + throw new EC2ServiceException(ServerError.InternalError, + "Unable to create image"); + } else if ( errorMessage.contains("Failed to start the stopped instance") ) { + throw new EC2ServiceException(ServerError.InternalError, + "Unable to start the instance that was stopped during image creation"); + } else if ( errorMessage.contains("One or more of instanceIds specified is in stopped state") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Unable to reboot. One or more of the specified instances is in an incorrect state 'stopped'"); + } else if ( errorMessage.contains("Specified ipAddress doesn't exist") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, "Specified publicIp doesn't exist"); + } else if ( errorMessage.contains("Min Count is greater than the number of instances left to allocate") ) { + throw new EC2ServiceException(ClientError.InstanceLimitExceeded, + "Specified MinCount parameter is greater than the number of instances you can create"); + } else if ( errorMessage.contains("instanceType not found") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, + "Specified instanceType not found"); + } else if ( errorMessage.contains("zone not found") ) { + throw new EC2ServiceException(ClientError.InvalidZone_NotFound, + "Specified zone doesn't exist"); + } else if ( errorMessage.contains("Both groupId and groupName has been specified") ) { + throw new EC2ServiceException(ClientError.InvalidParameterCombination, + " for EC2 groups either a group ID or a group name is accepted"); + } else if ( errorMessage.contains("Insufficient Instance Capacity") ) { + throw new EC2ServiceException(ServerError.InsufficientInstanceCapacity, "Insufficient Instance Capacity" ); + } else if ( errorMessage.contains("Unable to find security group name") ) { + throw new EC2ServiceException(ClientError.InvalidGroup_NotFound, "Specified Security Group does not exist" ); + } else if ( errorMessage.contains("Instance not found") ) { + throw new EC2ServiceException(ClientError.InvalidInstanceID_NotFound, + "One or more of the specified instanceId not found"); + } else if ( errorMessage.contains("Cannot modify, instance should be in stopped state") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Unable to modify instance attribute. Specified instance is not in the correct state 'stopped'"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } + } } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java index dbc367c109d..bd79041518e 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2GroupFilterSet { @@ -52,11 +53,9 @@ public class EC2GroupFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null")) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Image.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Image.java index 1c30b674f60..8ca9ce7384c 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Image.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Image.java @@ -28,10 +28,13 @@ public class EC2Image { private String name; private String description; private String osTypeId; - private boolean isPublic; - private boolean isReady; + private Boolean isPublic; + private String state; private String accountName; - private String domainId; + private String domainId; + private String hypervisor; + private String architecture; + private String imageType; private List tagsSet; public EC2Image() { @@ -40,9 +43,12 @@ public class EC2Image { description = null; osTypeId = null; isPublic = false; - isReady = false; + state = null; accountName = null; - domainId = null; + domainId = null; + hypervisor = null; + architecture = null; + imageType = "machine"; tagsSet = new ArrayList(); } @@ -78,21 +84,21 @@ public class EC2Image { return this.osTypeId; } - public void setIsPublic( boolean isPublic ) { - this.isPublic = isPublic; - } - - public boolean getIsPublic() { - return this.isPublic; - } + public void setIsPublic( Boolean isPublic ) { + this.isPublic = isPublic; + } - public void setIsReady( boolean isReady ) { - this.isReady = isReady; - } - - public boolean getIsReady() { - return this.isReady; - } + public Boolean getIsPublic() { + return this.isPublic; + } + + public void setState( String state ) { + this.state = state; + } + + public String getState() { + return this.state; + } public String getAccountName() { return accountName; @@ -110,6 +116,25 @@ public class EC2Image { this.domainId = domainId; } + public String getHypervisor() { + return hypervisor; + } + + public void setHypervisor(String hypervisor) { + this.hypervisor = hypervisor; + } + + public String getArchitecture() { + return architecture; + } + + public void setArchitecture(String architecture) { + this.architecture = architecture; + } + + public String getImageType() { + return imageType; + } public void addResourceTag( EC2TagKeyValue param ) { tagsSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java new file mode 100644 index 00000000000..646d20f56c4 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java @@ -0,0 +1,168 @@ +// 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.bridge.service.core.ec2; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; + +public class EC2ImageFilterSet { + protected final static Logger logger = Logger.getLogger(EC2ImageFilterSet.class); + + protected List filterSet = new ArrayList(); + private Map filterTypes = new HashMap(); + + public EC2ImageFilterSet() { + // -> supported filters + filterTypes.put( "architecture", "string" ); + filterTypes.put( "description", "string" ); + filterTypes.put( "hypervisor", "string" ); + filterTypes.put( "image-id", "string" ); + filterTypes.put( "image-type", "string" ); + filterTypes.put( "is-public", "Boolean" ); + filterTypes.put( "name", "string" ); + filterTypes.put( "owner-id", "string" ); + filterTypes.put( "state", "string" ); + filterTypes.put( "tag-key", "string" ); + filterTypes.put( "tag-value", "string" ); + } + + public void addFilter( EC2Filter param ) { + String filterName = param.getName(); + if ( !filterName.startsWith("tag:") ) { + String value = (String) filterTypes.get( filterName ); + if ( value == null || value.equalsIgnoreCase("null")) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } + } + + filterSet.add( param ); + } + + public EC2Filter[] getFilterSet() { + return filterSet.toArray(new EC2Filter[0]); + } + + public EC2DescribeImagesResponse evaluate( EC2DescribeImagesResponse sampleList) throws ParseException { + EC2DescribeImagesResponse resultList = new EC2DescribeImagesResponse(); + + boolean matched; + + EC2Image[] imageSet = sampleList.getImageSet(); + EC2Filter[] filterSet = getFilterSet(); + for (EC2Image image : imageSet) { + matched = true; + for (EC2Filter filter : filterSet) { + if (!filterMatched(image, filter)) { + matched = false; + break; + } + } + if (matched == true) + resultList.addImage(image); + } + return resultList; + } + +private boolean filterMatched( EC2Image image, EC2Filter filter ) throws ParseException { + String filterName = filter.getName(); + String[] valueSet = filter.getValueSet(); + + if ( filterName.equalsIgnoreCase( "architecture" )) + return containsString( image.getArchitecture(), valueSet ); + if ( filterName.equalsIgnoreCase( "description" )) + return containsString( image.getDescription(), valueSet ); + if ( filterName.equalsIgnoreCase( "hypervisor" )) + return containsString( image.getHypervisor(), valueSet ); + if ( filterName.equalsIgnoreCase( "image-id" )) + return containsString( image.getId(), valueSet ); + if ( filterName.equalsIgnoreCase( "image-type" )) + return containsString( image.getImageType(), valueSet ); + if ( filterName.equalsIgnoreCase( "is-public" )) + return image.getIsPublic().toString().equalsIgnoreCase(valueSet[0]); + if ( filterName.equalsIgnoreCase( "name" )) + return containsString( image.getName(), valueSet ); + if ( filterName.equalsIgnoreCase( "owner-id" )) { + String owner = new String( image.getDomainId() + ":" + image.getAccountName()); + return containsString( owner, valueSet ); + } + if ( filterName.equalsIgnoreCase( "state" )) + return containsString( image.getState(), valueSet ); + else if (filterName.equalsIgnoreCase("tag-key")) + { + EC2TagKeyValue[] tagSet = image.getResourceTags(); + for (EC2TagKeyValue tag : tagSet) + if (containsString(tag.getKey(), valueSet)) return true; + return false; + } + else if (filterName.equalsIgnoreCase("tag-value")) + { + EC2TagKeyValue[] tagSet = image.getResourceTags(); + for (EC2TagKeyValue tag : tagSet){ + if (tag.getValue() == null) { + if (containsEmptyValue(valueSet)) return true; + } + else { + if (containsString(tag.getValue(), valueSet)) return true; + } + } + return false; + } + else if (filterName.startsWith("tag:")) + { + String key = filterName.split(":")[1]; + EC2TagKeyValue[] tagSet = image.getResourceTags(); + for (EC2TagKeyValue tag : tagSet){ + if (tag.getKey().equalsIgnoreCase(key)) { + if (tag.getValue() == null) { + if (containsEmptyValue(valueSet)) return true; + } + else { + if (containsString(tag.getValue(), valueSet)) return true; + } + } + } + return false; + } + else return false; + } + + private boolean containsString( String lookingFor, String[] set ) { + if (lookingFor == null) + return false; + + for (String filter: set) { + if (lookingFor.matches( filter )) return true; + } + return false; + } + + private boolean containsEmptyValue( String[] set ) { + for( int i=0; i < set.length; i++ ) { + if (set[i].isEmpty()) return true; + } + return false; + } + +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java index b5b7c7840df..a71d476438f 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java @@ -24,6 +24,7 @@ import java.util.Map; import com.cloud.bridge.service.EC2SoapServiceImpl; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2InstanceFilterSet { @@ -59,11 +60,10 @@ public class EC2InstanceFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java index 2ad005b7dc2..d27972d5eda 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java @@ -25,6 +25,9 @@ import java.util.Map; import org.apache.log4j.Logger; +import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; + public class EC2KeyPairFilterSet { protected final static Logger logger = Logger.getLogger(EC2KeyPairFilterSet.class); @@ -42,16 +45,9 @@ public class EC2KeyPairFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) { - // Changing this to silently ignore - logger.error("Unsupported filter [" + filterName + "] - 1"); - return; - } - - if (null != value && value.equalsIgnoreCase( "null" )) { - logger.error("Unsupported filter [" + filterName + "] - 2"); - return; - } + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ModifyInstanceAttribute.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ModifyInstanceAttribute.java new file mode 100644 index 00000000000..8394e335310 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ModifyInstanceAttribute.java @@ -0,0 +1,64 @@ +// 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.bridge.service.core.ec2; + + +public class EC2ModifyInstanceAttribute { + private String instanceId; + private String instanceType; + private String userData; + + /** + * @return instanceId + */ + public String getInstanceId() { + return instanceId; + } + + /** + * @param instanceId to set + */ + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + /** + * @return instanceType + */ + public String getInstanceType() { + return instanceType; + } + + /** + * @param instanceType to set + */ + public void setInstanceType(String instanceType) { + this.instanceType = instanceType; + } + + /** + * @return userData + */ + public String getUserData() { + return userData; + } + + public void setUserData(String userData) { + this.userData = userData; + } + +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java index d71329701ea..43b27df6c05 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java @@ -72,7 +72,7 @@ public class EC2RegisterImage { if (null != param) { if (!param.contains(":") || param.split(":").length < 4) { throw new EC2ServiceException( ClientError.InvalidParameterValue, "Supported format for " + - "'architecture' is format:zonename:ostypename:hypervisor" ); + "parameter 'architecture' is format:zonename:ostypename:hypervisor" ); } String parts[] = param.split( ":" ); format = parts[0]; @@ -80,9 +80,6 @@ public class EC2RegisterImage { osTypeName = parts[2]; hypervisor = parts[3]; } - else { - throw new EC2ServiceException(ClientError.Unsupported, "Missing Parameter -" + " architecture"); - } } public String getFormat() { diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java index c2bed3ce161..ef395d9818e 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java @@ -27,6 +27,7 @@ import java.util.TimeZone; import com.cloud.bridge.service.UserContext; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; import com.cloud.bridge.util.DateHelper; import com.cloud.bridge.util.EC2RestAuth; @@ -56,12 +57,9 @@ public class EC2SnapshotFilterSet { String filterName = param.getName(); if (!filterName.startsWith("tag:")) { String value = (String) filterTypes.get( filterName ); - - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java index c2d33c39ea1..06edc3870ef 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java @@ -26,6 +26,7 @@ import java.util.Map; import org.apache.log4j.Logger; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2TagsFilterSet { protected final static Logger logger = Logger.getLogger(EC2TagsFilterSet.class); @@ -45,11 +46,9 @@ public class EC2TagsFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java index b8021f3d4ba..af132421474 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java @@ -26,6 +26,7 @@ import java.util.TimeZone; import java.util.Date; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; import com.cloud.bridge.util.EC2RestAuth; @@ -61,11 +62,9 @@ public class EC2VolumeFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java b/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java index e1f515ad2c0..c21e6e9574f 100644 --- a/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java +++ b/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java @@ -26,11 +26,11 @@ public class EC2ServiceException extends RuntimeException { // ServerError & ClientError are correct as of schema version 2010-08-31 public static enum ServerError { - InsufficientAddressCapacity("Server.InsufficientAddressCapacity", 500), - InsufficientInstanceCapacity("Server.InsufficientInstanceCapacity", 500), - InsufficientReservedInstanceCapacity("Server.InsufficientReservedInstanceCapacity", 500), - InternalError("Server.InternalError", 500), - Unavailable("Server.Unavailable", 501); + InsufficientAddressCapacity("Server.InsufficientAddressCapacity", 500), + InsufficientInstanceCapacity("Server.InsufficientInstanceCapacity", 500), + InsufficientReservedInstanceCapacity("Server.InsufficientReservedInstanceCapacity", 500), + InternalError("Server.InternalError", 500), + Unavailable("Server.Unavailable", 501); private String errorString; private int httpErrorCode; @@ -45,58 +45,64 @@ public class EC2ServiceException extends RuntimeException { } public static enum ClientError { - AddressLimitExceeded("Client.AddressLimitExceeded", 400), - AttachmentLimitExceeded("Client.AttachmentLimitExceeded", 400), - AuthFailure("Client.AuthFailure", 400), - Blocked("Client.Blocked", 400), - FilterLimitExceeded("Client.FilterLimitExceeded", 400), - IdempotentParameterMismatch("Client.IdempotentParameterMismatch", 400), - IncorrectState("Client.IncorrectState", 400), - InstanceLimitExceeded("Client.InstanceLimitExceeded", 400), - InsufficientInstanceCapacity("Client.InsufficientInstanceCapacity", 400), - InsufficientReservedInstancesCapacity("Client.InsufficientReservedInstancesCapacity", 400), - InvalidAMIAttributeItemValue("Client.InvalidAMIAttributeItemValue", 400), - InvalidAMIID_Malformed("Client.InvalidAMIID.Malformed", 400), - InvalidAMIID_NotFound("Client.InvalidAMIID.NotFound", 400), - InvalidAMIID_Unavailable("Client.InvalidAMIID.Unavailable", 400), - InvalidAttachment_NotFound("Client.InvalidAttachment.NotFound", 400), - InvalidDevice_InUse("Client.InvalidDevice.InUse", 400), - InvalidGroup_Duplicate("Client.InvalidGroup.Duplicate", 400), - InvalidGroup_InUse("Client.InvalidGroup.InUse", 400), - InvalidGroup_NotFound("Client.InvalidGroup.NotFound", 400), - InvalidGroup_Reserved("Client.InvalidGroup.Reserved", 400), - InvalidInstanceID_Malformed("Client.InvalidInstanceID.Malformed", 400), - InvalidInstanceID_NotFound("Client.InvalidInstanceID.NotFound", 400), - InvalidIPAddress_InUse("Client.InvalidIPAddress.InUse", 400), - InvalidKeyPair_Duplicate("Client.InvalidKeyPair.Duplicate", 400), - InvalidKeyPair_Format("Client.InvalidKeyPair.Format", 400), - InvalidKeyPair_NotFound("Client.InvalidKeyPair.NotFound", 400), - InvalidManifest("Client.InvalidManifest", 400), - InvalidParameterCombination("Client.InvalidParameterCombination", 400), - InvalidParameterValue("Client.InvalidParameterValue", 400), - InvalidPermission_Duplicate("Client.InvalidPermission.Duplicate", 400), - InvalidPermission_Malformed("Client.InvalidPermission.Malformed", 400), - InvalidReservationID_Malformed("Client.InvalidReservationID.Malformed", 400), - InvalidReservationID_NotFound("Client.InvalidReservationID.NotFound", 400), - InvalidResourceId_Format("Client.InvalidResourceId.Format", 400), - InvalidSnapshotID_Malformed("Client.InvalidSnapshotID.Malformed", 400), - InvalidSnapshot_NotFound("Client.InvalidSnapshot.NotFound", 400), - InvalidUserID_Malformed("Client.InvalidUserID.Malformed", 400), - InvalidReservedInstancesId("Client.InvalidReservedInstancesId", 400), - InvalidReservedInstancesOfferingId("Client.InvalidReservedInstancesOfferingId", 400), - InvalidVolumeID_Duplicate("Client.InvalidVolumeID.Duplicate", 400), - InvalidVolumeID_Malformed("Client.InvalidVolumeID.Malformed", 400), - InvalidVolume_NotFound("Client.InvalidVolume.NotFound", 400), - InvalidVolumeID_ZoneMismatch("Client.InvalidVolumeID.ZoneMismatch", 400), - InvalidZone_NotFound("Client.InvalidZone.NotFound", 400), - NonEBSInstance("Client.NonEBSInstance", 400), - PendingVerification("Client.PendingVerification", 400), - PendingSnapshotLimitExceeded("Client.PendingSnapshotLimitExceeded", 400), - ReservedInstancesLimitExceeded("Client.ReservedInstancesLimitExceeded", 400), - SnapshotLimitExceeded("Client.SnapshotLimitExceeded", 400), - UnknownParameter("Client.UnknownParameter", 400), - Unsupported("Client.Unsupported", 400), - VolumeLimitExceeded("Client.VolumeLimitExceeded", 400); + AddressLimitExceeded("Client.AddressLimitExceeded", 400), + AttachmentLimitExceeded("Client.AttachmentLimitExceeded", 400), + AuthFailure("Client.AuthFailure", 400), + Blocked("Client.Blocked", 400), + DependencyViolation("Client.DependencyViolation", 400), + FilterLimitExceeded("Client.FilterLimitExceeded", 400), + IdempotentParameterMismatch("Client.IdempotentParameterMismatch", 400), + IncorrectState("Client.IncorrectState", 400), + IncorrectInstanceState("Client.IncorrectInstanceState", 400), + InstanceLimitExceeded("Client.InstanceLimitExceeded", 400), + InsufficientInstanceCapacity("Client.InsufficientInstanceCapacity", 400), + InsufficientReservedInstancesCapacity("Client.InsufficientReservedInstancesCapacity", 400), + InvalidAMIAttributeItemValue("Client.InvalidAMIAttributeItemValue", 400), + InvalidAMIID_Malformed("Client.InvalidAMIID.Malformed", 400), + InvalidAMIID_NotFound("Client.InvalidAMIID.NotFound", 400), + InvalidAMIID_Unavailable("Client.InvalidAMIID.Unavailable", 400), + InvalidAttachment_NotFound("Client.InvalidAttachment.NotFound", 400), + InvalidDevice_InUse("Client.InvalidDevice.InUse", 400), + InvalidFilter("Client.InvalidFilter", 400), + InvalidGroup_Duplicate("Client.InvalidGroup.Duplicate", 400), + InvalidGroup_InUse("Client.InvalidGroup.InUse", 400), + InvalidGroup_NotFound("Client.InvalidGroup.NotFound", 400), + InvalidGroup_Reserved("Client.InvalidGroup.Reserved", 400), + InvalidInstanceID_Malformed("Client.InvalidInstanceID.Malformed", 400), + InvalidInstanceID_NotFound("Client.InvalidInstanceID.NotFound", 400), + InvalidIPAddress_InUse("Client.InvalidIPAddress.InUse", 400), + InvalidKeyPair_Duplicate("Client.InvalidKeyPair.Duplicate", 400), + InvalidKeyPair_Format("Client.InvalidKeyPair.Format", 400), + InvalidKeyPair_NotFound("Client.InvalidKeyPair.NotFound", 400), + InvalidManifest("Client.InvalidManifest", 400), + InvalidParameterCombination("Client.InvalidParameterCombination", 400), + InvalidParameterValue("Client.InvalidParameterValue", 400), + InvalidPermission_Duplicate("Client.InvalidPermission.Duplicate", 400), + InvalidPermission_Malformed("Client.InvalidPermission.Malformed", 400), + InvalidReservationID_Malformed("Client.InvalidReservationID.Malformed", 400), + InvalidReservationID_NotFound("Client.InvalidReservationID.NotFound", 400), + InvalidSecurity_RequestHasExpired("Client.InvalidSecurity.RequestHasExpired", 400), + InvalidSnapshotID_Malformed("Client.InvalidSnapshotID.Malformed", 400), + InvalidSnapshot_NotFound("Client.InvalidSnapshot.NotFound", 400), + InvalidUserID_Malformed("Client.InvalidUserID.Malformed", 400), + InvalidReservedInstancesId("Client.InvalidReservedInstancesId", 400), + InvalidReservedInstancesOfferingId("Client.InvalidReservedInstancesOfferingId", 400), + InvalidVolumeID_Duplicate("Client.InvalidVolumeID.Duplicate", 400), + InvalidVolumeID_Malformed("Client.InvalidVolumeID.Malformed", 400), + InvalidVolume_NotFound("Client.InvalidVolume.NotFound", 400), + InvalidVolumeID_ZoneMismatch("Client.InvalidVolumeID.ZoneMismatch", 400), + InvalidZone_NotFound("Client.InvalidZone.NotFound", 400), + MissingParamter("Client.MissingParamter", 400), + NonEBSInstance("Client.NonEBSInstance", 400), + PendingVerification("Client.PendingVerification", 400), + PendingSnapshotLimitExceeded("Client.PendingSnapshotLimitExceeded", 400), + SignatureDoesNotMatch("Client.SignatureDoesNotMatch", 400), + ReservedInstancesLimitExceeded("Client.ReservedInstancesLimitExceeded", 400), + ResourceLimitExceeded("Client.ResourceLimitExceeded", 400), + SnapshotLimitExceeded("Client.SnapshotLimitExceeded", 400), + UnknownParameter("Client.UnknownParameter", 400), + Unsupported("Client.UnsupportedOperation", 400), + VolumeLimitExceeded("Client.VolumeLimitExceeded", 400); private String errorString; private int httpErrorCode; diff --git a/awsapi/src/com/cloud/stack/CloudStackClient.java b/awsapi/src/com/cloud/stack/CloudStackClient.java index 5017bd423dd..fa114f5a2cf 100644 --- a/awsapi/src/com/cloud/stack/CloudStackClient.java +++ b/awsapi/src/com/cloud/stack/CloudStackClient.java @@ -103,8 +103,8 @@ public class CloudStackClient { int jobStatus = queryAsyncJobResponse.getAsInt("queryasyncjobresultresponse.jobstatus"); switch(jobStatus) { case 2: - throw new Exception(queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode") + " " + - queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errortext")); + throw new Exception(queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errortext") + " Error Code - " + + queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode") ); case 0 : try { @@ -179,6 +179,7 @@ public class CloudStackClient { if(errorMessage == null){ errorMessage = "CloudStack API call HTTP response error, HTTP status code: " + statusCode; } + errorMessage = errorMessage.concat(" Error Code - " + Integer.toString(statusCode)); throw new IOException(errorMessage); } diff --git a/client/pom.xml b/client/pom.xml index 7fe9e96f672..ca92c7efd12 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -131,6 +131,11 @@ cloud-plugin-planner-user-concentrated-pod ${project.version} + + org.apache.cloudstack + cloud-plugin-planner-implicit-dedication + ${project.version} + org.apache.cloudstack cloud-plugin-host-allocator-random diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 7552b29c1eb..42e20551d5b 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -276,6 +276,8 @@ + + @@ -374,7 +376,7 @@ - + diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index 1b6ee6eb089..6fa9d38baa4 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -251,7 +251,7 @@ - + diff --git a/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java b/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java index d928e0c5b2b..98a957f9a4e 100755 --- a/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java +++ b/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java @@ -28,7 +28,6 @@ public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { public CreateEntityDownloadURLCommand(String installPath, String uuid) { super(); - this.parent = parent; this.installPath = installPath; this.extractLinkUUID = uuid; } diff --git a/core/src/com/cloud/network/DnsMasqConfigurator.java b/core/src/com/cloud/network/DnsMasqConfigurator.java index bbf721d5509..ee8e5fc2e13 100644 --- a/core/src/com/cloud/network/DnsMasqConfigurator.java +++ b/core/src/com/cloud/network/DnsMasqConfigurator.java @@ -110,7 +110,7 @@ import java.util.List; dnsServers = dnsServers+dnsMasqconfigcmd.getDns2()+","; } dnsServers = dnsServers +"*"; - dnsServers = dnsServers.replace(";*", ""); + dnsServers = dnsServers.replace(",*", ""); dnsMasqconf.set(24,"dhcp-option=6,"+dnsServers); return dnsMasqconf.toArray( new String[dnsMasqconf.size()]); } diff --git a/debian/rules b/debian/rules index ff12154db31..48485bb9d9b 100755 --- a/debian/rules +++ b/debian/rules @@ -34,7 +34,7 @@ build: build-indep build-indep: build-indep-stamp build-indep-stamp: configure - mvn package -Pawsapi -DskipTests -Dsystemvm \ + mvn clean package -Pawsapi -DskipTests -Dsystemvm \ -Dcs.replace.properties=replace.properties.tmp \ ${ACS_BUILD_OPTS} touch $@ @@ -80,6 +80,7 @@ install: mkdir -p $(DESTDIR)/$(SYSCONFDIR)/sudoers.d/ mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/webapps/client + mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/webapps7080 mkdir $(DESTDIR)/usr/share/$(PACKAGE)-management/setup mkdir $(DESTDIR)/var/log/$(PACKAGE)/management mkdir $(DESTDIR)/var/cache/$(PACKAGE)/management @@ -153,6 +154,7 @@ install: mkdir $(DESTDIR)/usr/share/$(PACKAGE)-bridge mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi mkdir $(DESTDIR)/usr/share/$(PACKAGE)-bridge/setup + ln -s /usr/share/$(PACKAGE)-bridge/webapps/awsapi $(DESTDIR)/usr/share/$(PACKAGE)-management/webapps7080/awsapi cp -r awsapi/target/cloud-awsapi-$(VERSION)-SNAPSHOT/* $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi install -D awsapi-setup/setup/cloud-setup-bridge $(DESTDIR)/usr/bin/cloudstack-setup-bridge install -D awsapi-setup/setup/cloudstack-aws-api-register $(DESTDIR)/usr/bin/cloudstack-aws-api-register diff --git a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml index 7f156d5dc09..5431fc1cb43 100644 --- a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml +++ b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml @@ -48,6 +48,7 @@ + diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index dca95d37c16..25e1175b148 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -4586,7 +4586,7 @@ under the License. versions of Citrix CloudStack (last version prior to Apache is 3.0.2) and from the releases made while CloudStack was in the Apache Incubator. If you run into any issues during upgrades, please feel free to ask questions on - users@apache.cloudstack.org or dev@apache.cloudstack.org. + users@cloudstack.apache.org or dev@cloudstack.apache.org.
Upgrade from 4.0.x to 4.1.0 This section will guide you from &PRODUCT; 4.0.x versions to &PRODUCT; 4.1.0. @@ -4647,6 +4647,23 @@ under the License. automatically. (If you're unsure, we recommend making a backup of the original components.xml to be on the safe side. + + After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) + +<!-- Security adapters --> +<bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> + <property name="Adapters"> + <list> + <ref bean="PlainTextUserAuthenticator"/> + <ref bean="MD5UserAuthenticator"/> + <ref bean="LDAPUserAuthenticator"/> + </list> + </property> +</bean> + + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + If you are using Ubuntu, follow this procedure to upgrade your packages. If not, skip to step . @@ -5110,6 +5127,23 @@ service cloudstack-agent start node. + + After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) + +<!-- Security adapters --> +<bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> + <property name="Adapters"> + <list> + <ref bean="PlainTextUserAuthenticator"/> + <ref bean="MD5UserAuthenticator"/> + <ref bean="LDAPUserAuthenticator"/> + </list> + </property> +</bean> + + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + Start the first Management Server. Do not start any other Management Server nodes yet. @@ -5688,6 +5722,23 @@ service cloudstack-agent start + + After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) + +<!-- Security adapters --> +<bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> + <property name="Adapters"> + <list> + <ref bean="PlainTextUserAuthenticator"/> + <ref bean="MD5UserAuthenticator"/> + <ref bean="LDAPUserAuthenticator"/> + </list> + </property> +</bean> + + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + If you have made changes to your existing copy of the /etc/cloud/management/db.properties file in your previous-version diff --git a/docs/en-US/added-API-commands-4.2.xml b/docs/en-US/added-API-commands-4.2.xml index 3abb780663e..177c9a0e6ea 100644 --- a/docs/en-US/added-API-commands-4.2.xml +++ b/docs/en-US/added-API-commands-4.2.xml @@ -117,5 +117,21 @@ pagesize; projectid (lists objects by project); regionid; tags (lists resources by tags: key/value pairs) + + createPortableIpAddressRange + Creates portable IP addresses from the portable public IP address pool. + The request parameters are region id, start ip, end ip, netmask, gateway, and + vlan. + + + deletePortableIpAddressRange + Deletes portable IP addresses from the portable public IP address pool. + The request parameters is portable ip address range id. + + + createPortableIpAddressRange + Lists portable IP addresses in the portable public IP address pool. + The request parameters are elastic ip id and region id. +
diff --git a/docs/en-US/images/nvp-add-controller.png b/docs/en-US/images/nvp-add-controller.png new file mode 100644 index 00000000000..e02d31f0a37 Binary files /dev/null and b/docs/en-US/images/nvp-add-controller.png differ diff --git a/docs/en-US/images/nvp-enable-provider.png b/docs/en-US/images/nvp-enable-provider.png new file mode 100644 index 00000000000..0f2d02ddfa9 Binary files /dev/null and b/docs/en-US/images/nvp-enable-provider.png differ diff --git a/docs/en-US/images/nvp-network-offering.png b/docs/en-US/images/nvp-network-offering.png new file mode 100644 index 00000000000..c2d25c48c19 Binary files /dev/null and b/docs/en-US/images/nvp-network-offering.png differ diff --git a/docs/en-US/images/nvp-physical-network-stt.png b/docs/en-US/images/nvp-physical-network-stt.png new file mode 100644 index 00000000000..2ce7853ac54 Binary files /dev/null and b/docs/en-US/images/nvp-physical-network-stt.png differ diff --git a/docs/en-US/images/nvp-vpc-offering-edit.png b/docs/en-US/images/nvp-vpc-offering-edit.png new file mode 100644 index 00000000000..ff235e24cd6 Binary files /dev/null and b/docs/en-US/images/nvp-vpc-offering-edit.png differ diff --git a/docs/en-US/plugin-niciranvp-about.xml b/docs/en-US/plugin-niciranvp-about.xml index 8d2e20e7756..cfab83c73c3 100644 --- a/docs/en-US/plugin-niciranvp-about.xml +++ b/docs/en-US/plugin-niciranvp-about.xml @@ -1,5 +1,5 @@ - %BOOK_ENTITIES; diff --git a/docs/en-US/plugin-niciranvp-devicemanagement.xml b/docs/en-US/plugin-niciranvp-devicemanagement.xml index 57b8eee9d7d..761c39f3179 100644 --- a/docs/en-US/plugin-niciranvp-devicemanagement.xml +++ b/docs/en-US/plugin-niciranvp-devicemanagement.xml @@ -21,27 +21,15 @@ under the License. -->
- Device-management - In &PRODUCT; 4.0.x each Nicira NVP setup is considered a "device" that can be added and removed from a physical network. To complete the configuration of the Nicira NVP plugin a device needs to be added to the physical network using the "addNiciraNVPDevice" API call. The plugin is now enabled on the physical network and any guest networks created on that network will be provisioned using the Nicira NVP Controller. - The plugin introduces a set of new API calls to manage the devices, see below or refer to the API reference. - - addNiciraNvpDevice - - - physicalnetworkid: the UUID of the physical network on which the device is configured - hostname: the IP address of the NVP controller - username: the username for access to the NVP API - password: the password for access to the NVP API - transportzoneuuid: the UUID of the transportzone - - - deleteNiciraNVPDevice - - - nvpdeviceid: the UUID of the device - - - listNiciraNVPDevices - + Device Management + In &PRODUCT; a Nicira NVP setup is considered a "device" that can be added and removed from a physical network. To complete the configuration of the Nicira NVP plugin a device needs to be added to the physical network. Press the "Add NVP Controller" button on the provider panel and enter the configuration details. + + + + + + nvp-physical-network-stt.png: a screenshot of the device configuration popup. + +
diff --git a/docs/en-US/plugin-niciranvp-features.xml b/docs/en-US/plugin-niciranvp-features.xml index c346bfb64e3..e439f1b4923 100644 --- a/docs/en-US/plugin-niciranvp-features.xml +++ b/docs/en-US/plugin-niciranvp-features.xml @@ -22,12 +22,63 @@ -->
Features of the Nicira NVP Plugin - In &PRODUCT; release 4.0.0-incubating this plugin supports the Connectivity service. This service is responsible for creating Layer 2 networks supporting the networks created by Guests. In other words when an tenant creates a new network, instead of the traditional VLAN a logical network will be created by sending the appropriate calls to the Nicira NVP Controller. - The plugin has been tested with Nicira NVP versions 2.1.0, 2.2.0 and 2.2.1 - In &PRODUCT; 4.0.0-incubating only the XenServer hypervisor is supported for use in - combination with Nicira NVP. - In &PRODUCT; 4.1.0-incubating both KVM and XenServer hypervisors are - supported. - In &PRODUCT; 4.0.0-incubating the UI components for this plugin are not complete, - configuration is done by sending commands to the API. + The following table lists the CloudStack network services provided by the Nicira NVP Plugin. + + Supported Services + + + + Network Service + CloudStack version + NVP version + + + + + Virtual Networking + >= 4.0 + >= 2.2.1 + + + Source NAT + >= 4.1 + >= 3.0.1 + + + Static NAT + >= 4.1 + >= 3.0.1 + + + Port Forwarding + >= 4.1 + >= 3.0.1 + + + +
+ The Virtual Networking service was originally called 'Connectivity' in CloudStack 4.0 + The following hypervisors are supported by the Nicira NVP Plugin. + + Supported Hypervisors + + + + Hypervisor + CloudStack version + + + + + XenServer + >= 4.0 + + + KVM + >= 4.1 + + + +
+ Please refer to the Nicira NVP configuration guide on how to prepare the hypervisors for Nicira NVP integration.
diff --git a/docs/en-US/plugin-niciranvp-introduction.xml b/docs/en-US/plugin-niciranvp-introduction.xml index 9c1d42df32d..a06f12317e5 100644 --- a/docs/en-US/plugin-niciranvp-introduction.xml +++ b/docs/en-US/plugin-niciranvp-introduction.xml @@ -22,5 +22,8 @@ -->
Introduction to the Nicira NVP Plugin - The Nicira NVP plugin allows CloudStack to use the Nicira solution for virtualized network as a provider for CloudStack networks and services. + The Nicira NVP plugin adds Nicira NVP as one of the available SDN implementations in + CloudStack. With the plugin an exisiting Nicira NVP setup can be used by CloudStack to + implement isolated guest networks and to provide additional services like routing and + NAT.
diff --git a/docs/en-US/plugin-niciranvp-networkofferings.xml b/docs/en-US/plugin-niciranvp-networkofferings.xml new file mode 100644 index 00000000000..b30437e97ba --- /dev/null +++ b/docs/en-US/plugin-niciranvp-networkofferings.xml @@ -0,0 +1,131 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ Network Offerings + Using the Nicira NVP plugin requires a network offering with Virtual Networking enabled and configured to use the NiciraNvp element. Typical use cases combine services from the Virtual Router appliance and the Nicira NVP plugin. + + Isolated network offering with regular services from the Virtual Router. + + + + Service + Provider + + + + + VPN + VirtualRouter + + + DHCP + VirtualRouter + + + DNS + VirtualRouter + + + Firewall + VirtualRouter + + + Load Balancer + VirtualRouter + + + User Data + VirtualRouter + + + Source NAT + VirtualRouter + + + Static NAT + VirtualRouter + + + Post Forwarding + VirtualRouter + + + Virtual Networking + NiciraNVP + + + +
+ + + + + + nvp-physical-network-stt.png: a screenshot of a network offering. + + + The tag in the network offering should be set to the name of the physical network with the NVP provider. + Isolated network with network services. The virtual router is still required to provide network services like dns and dhcp. + + Isolated network offering with network services + + + + Service + Provider + + + + + DHCP + VirtualRouter + + + DNS + VirtualRouter + + + User Data + VirtualRouter + + + Source NAT + NiciraNVP + + + Static NAT + NiciraNVP + + + Post Forwarding + NiciraNVP + + + Virtual Networking + NiciraNVP + + + +
+ +
diff --git a/docs/en-US/plugin-niciranvp-physicalnet.xml b/docs/en-US/plugin-niciranvp-physicalnet.xml new file mode 100644 index 00000000000..d3202905fb1 --- /dev/null +++ b/docs/en-US/plugin-niciranvp-physicalnet.xml @@ -0,0 +1,37 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ Zone Configuration + &PRODUCT; needs to have at least one physical network with the isolation method set to "STT". This network should be enabled for the Guest traffic type. + The Guest traffic type should be configured with the traffic label that matches the name of + the Integration Bridge on the hypervisor. See the Nicira NVP User Guide for more details + on how to set this up in XenServer or KVM. + + + + + + nvp-physical-network-stt.png: a screenshot of a physical network with the STT isolation type + + +
diff --git a/docs/en-US/plugin-niciranvp-preparations.xml b/docs/en-US/plugin-niciranvp-preparations.xml index 762c941fd13..60725591fda 100644 --- a/docs/en-US/plugin-niciranvp-preparations.xml +++ b/docs/en-US/plugin-niciranvp-preparations.xml @@ -22,17 +22,16 @@ -->
Prerequisites - Before enabling the Nicira NVP plugin the NVP Controller needs to be configured. Please review the NVP User Guide on how to do that. - &PRODUCT; needs to have at least one physical network with the isolation method set to "STT". This network should be enabled for the Guest traffic type. - The Guest traffic type should be configured with the traffic label that matches the name of - the Integration Bridge on the hypervisor. See the Nicira NVP User Guide for more details - on how to set this up in XenServer or KVM. + Before enabling the Nicira NVP plugin the NVP Controller needs to be configured. Please review the NVP User Guide on how to do that. Make sure you have the following information ready: The IP address of the NVP Controller The username to access the API The password to access the API The UUID of the Transport Zone that contains the hypervisors in this Zone - The UUID of the Physical Network that will be used for the Guest networks + + The UUID of the Gateway Service used to provide router and NAT services. + + The gateway service uuid is optional and is used for Layer 3 services only (SourceNat, StaticNat and PortForwarding)
diff --git a/docs/en-US/plugin-niciranvp-provider.xml b/docs/en-US/plugin-niciranvp-provider.xml index 80fb2273238..8694478b483 100644 --- a/docs/en-US/plugin-niciranvp-provider.xml +++ b/docs/en-US/plugin-niciranvp-provider.xml @@ -22,21 +22,15 @@ -->
Enabling the service provider - To allow CloudStack to use the Nicira NVP Plugin the network service provider needs to be enabled on the physical network. The following sequence of API calls will enable the network service provider - - addNetworkServiceProvider - - - name = "NiciraNvp" - physicalnetworkid = <the uuid of the physical network> - - - updateNetworkServiceProvider - - - id = <the provider uuid returned by the previous call> - state = "Enabled" - - - + The Nicira NVP provider is disabled by default. Navigate to the "Network Service Providers" configuration of the physical network with the STT isolation type. Navigate to the Nicira NVP provider and press the "Enable Provider" button. + CloudStack 4.0 does not have the UI interface to configure the Nicira NVP plugin. Configuration needs to be done using the API directly. + + + + + + nvp-physical-network-stt.png: a screenshot of an enabled Nicira NVP provider + + +
\ No newline at end of file diff --git a/docs/en-US/plugin-niciranvp-revisions.xml b/docs/en-US/plugin-niciranvp-revisions.xml index b8e6935c5d1..b58d3336aba 100644 --- a/docs/en-US/plugin-niciranvp-revisions.xml +++ b/docs/en-US/plugin-niciranvp-revisions.xml @@ -40,6 +40,20 @@ + + 1-0 + Wed May 22 2013 + + Hugo + Trippaers + hugo@apache.org + + + + Documentation updated for &PRODUCT; 4.1.0 + + + diff --git a/docs/en-US/plugin-niciranvp-tables.xml b/docs/en-US/plugin-niciranvp-tables.xml index 4f816550b30..615f3494c09 100644 --- a/docs/en-US/plugin-niciranvp-tables.xml +++ b/docs/en-US/plugin-niciranvp-tables.xml @@ -23,29 +23,84 @@
Database tables The following tables are added to the cloud database for the Nicira NVP Plugin - - nicira_nvp_nic_map, contains a mapping from nic to logical switch port - - - id - logicalswitch, uuid of the logical switch this port is connected to - logicalswitchport, uuid of the logical switch port for this nic - nic, the CloudStack uuid for this nic, reference to the nics table - - - - - external_nicira_nvp_devices, contains all configured devices - - - id - uuid - physical_network_id, the physical network this device is configured on - provider_name, set to "NiciraNvp" - device_name, display name for this device - host_id, reference to the host table with the device configuration - - - - + + nicira_nvp_nic_map + + + + id + auto incrementing id + + + logicalswitch + uuid of the logical switch this port is connected to + + + logicalswitchport + uuid of the logical switch port for this nic + + + nic + the &PRODUCT; uuid for this nic, reference to the nics table + + + +
+ + + external_nicira_nvp_devices + + + + id + auto incrementing id + + + uuid + UUID identifying this device + + + physical_network_id + the physical network this device is configured on + + + provider_name + NiciraNVP + + + device_name + display name for this device + + + host_id + reference to the host table with the device configuration + + + +
+ + + nicira_nvp_router_map + + + + id + auto incrementing id + + + logicalrouter_uuid + uuid of the logical router + + + network_id + id of the network this router is linked to + + + +
+ + + nicira_nvp_router_map is only available in &PRODUCT; 4.1 and above + +
\ No newline at end of file diff --git a/docs/en-US/plugin-niciranvp-usage.xml b/docs/en-US/plugin-niciranvp-usage.xml index 76f9a0b5b05..9f04c382bd6 100644 --- a/docs/en-US/plugin-niciranvp-usage.xml +++ b/docs/en-US/plugin-niciranvp-usage.xml @@ -21,10 +21,13 @@ under the License. --> - Using the Nicira NVP Plugin + Configuring the Nicira NVP Plugin - - - + + + + diff --git a/docs/en-US/plugin-niciranvp-guide.xml b/docs/en-US/plugin-niciranvp-vpc.xml similarity index 65% rename from docs/en-US/plugin-niciranvp-guide.xml rename to docs/en-US/plugin-niciranvp-vpc.xml index 89c9871021d..a43c5fa85d3 100644 --- a/docs/en-US/plugin-niciranvp-guide.xml +++ b/docs/en-US/plugin-niciranvp-vpc.xml @@ -1,11 +1,10 @@ - + %BOOK_ENTITIES; %xinclude; ]> - - - Plugin Guide for the Nicira NVP Plugin - - - + + Using the Nicira NVP plugin with VPC + + + + + diff --git a/docs/en-US/plugin-niciranvp-vpcfeatures.xml b/docs/en-US/plugin-niciranvp-vpcfeatures.xml new file mode 100644 index 00000000000..a8d8194e9ba --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcfeatures.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ Supported VPC features + The Nicira NVP plugin supports &PRODUCT; VPC to a certain extent. Starting with &PRODUCT; version 4.1 VPCs can be deployed using NVP isolated networks. + It is not possible to use a Nicira NVP Logical Router for as a VPC Router + It is not possible to connect a private gateway using a Nicira NVP Logical Switch +
diff --git a/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml b/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml new file mode 100644 index 00000000000..141006ee350 --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml @@ -0,0 +1,81 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ VPC Network Offerings + The VPC needs specific network offerings with the VPC flag enabled. Otherwise these network offerings are identical to regular network offerings. To allow VPC networks with a Nicira NVP isolated network the offerings need to support the Virtual Networking service with the NiciraNVP provider. + In a typical configuration two network offerings need to be created. One with the loadbalancing service enabled and one without loadbalancing. + + VPC Network Offering with Loadbalancing + + + + Service + Provider + + + + + VPN + VpcVirtualRouter + + + DHCP + VpcVirtualRouter + + + DNS + VpcVirtualRouter + + + Load Balancer + VpcVirtualRouter + + + User Data + VpcVirtualRouter + + + Source NAT + VpcVirtualRouter + + + Static NAT + VpcVirtualRouter + + + Post Forwarding + VpcVirtualRouter + + + NetworkACL + VpcVirtualRouter + + + Virtual Networking + NiciraNVP + + + +
+ +
diff --git a/docs/en-US/plugin-niciranvp-vpcoffering.xml b/docs/en-US/plugin-niciranvp-vpcoffering.xml new file mode 100644 index 00000000000..292621e516c --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcoffering.xml @@ -0,0 +1,38 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ VPC Offering with Nicira NVP + To allow a VPC to use the Nicira NVP plugin to provision networks, a new VPC offering needs to be created which allows the Virtual Networking service to be implemented by NiciraNVP. + This is not currently possible with the UI. The API does provide the proper calls to create a VPC offering with Virtual Networking enabled. However due to a limitation in the 4.1 API it is not possible to select the provider for this network service. To configure the VPC offering with the NiciraNVP provider edit the database table 'vpc_offering_service_map' and change the provider to NiciraNvp for the service 'Connectivity' + It is also possible to update the default VPC offering by adding a row to the + 'vpc_offering_service_map' with service 'Connectivity' and provider 'NiciraNvp' + + + + + + nvp-physical-network-stt.png: a screenshot of the mysql table. + + + When creating a new VPC offering please note that the UI does not allow you to select a VPC offering yet. The VPC needs to be created using the API with the offering UUID. +
diff --git a/docs/en-US/portable-ip.xml b/docs/en-US/portable-ip.xml new file mode 100644 index 00000000000..ec1035ec204 --- /dev/null +++ b/docs/en-US/portable-ip.xml @@ -0,0 +1,30 @@ + + +%BOOK_ENTITIES; +]> + +
+ About Portable IP + Portable IPs in &PRODUCT; are nothing but elastic IPs that can be transferred across + geographically separated zones. As an administrator, you can provision a pool of portable IPs at + region level and are available for user consumption. The users can acquire portable IPs if admin + has provisioned portable public IPs at the region level they are part of. These IPs can be use + for any service within an advanced zone. You can also use portable IPs for EIP service in basic + zones. Additionally, a portable IP can be transferred from one network to another + network. +
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/AbstractScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/AbstractScope.java index c94db66b202..083b1fe6c39 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/AbstractScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/AbstractScope.java @@ -21,10 +21,6 @@ package org.apache.cloudstack.engine.subsystem.api.storage; public abstract class AbstractScope implements Scope { @Override public boolean isSameScope(Scope scope) { - if (this.getScopeType() == scope.getScopeType() && this.getScopeId() == scope.getScopeId()) { - return true; - } else { - return false; - } + return this.getScopeType() == scope.getScopeType() && this.getScopeId().equals(scope.getScopeId()); } } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index 25e742301cf..38ed7e63605 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -24,6 +24,7 @@ import java.util.UUID; import javax.inject.Inject; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.engine.cloud.entity.api.db.VMEntityVO; import org.apache.cloudstack.engine.cloud.entity.api.db.VMReservationVO; import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMEntityDao; @@ -60,6 +61,7 @@ import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfileImpl; @@ -111,6 +113,9 @@ public class VMEntityManagerImpl implements VMEntityManager { @Inject DeploymentPlanningManager _dpMgr; + @Inject + protected AffinityGroupVMMapDao _affinityGroupVMMapDao; + @Override public VMEntityVO loadVirtualMachine(String vmId) { // TODO Auto-generated method stub @@ -123,6 +128,16 @@ public class VMEntityManagerImpl implements VMEntityManager { } + protected boolean areAffinityGroupsAssociated(VirtualMachineProfile vmProfile) { + VirtualMachine vm = vmProfile.getVirtualMachine(); + long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); + + if (vmGroupCount > 0) { + return true; + } + return false; + } + @Override public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude) throws InsufficientCapacityException, ResourceUnavailableException { @@ -194,7 +209,8 @@ public class VMEntityManagerImpl implements VMEntityManager { // call retry it. return UUID.randomUUID().toString(); }else{ - throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); + throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, + DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile)); } } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/VolumeReservationVO.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/VolumeReservationVO.java index f064623f887..e858f740a07 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/VolumeReservationVO.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/VolumeReservationVO.java @@ -16,22 +16,14 @@ // under the License. package org.apache.cloudstack.engine.cloud.entity.api.db; -import java.util.Date; -import java.util.Map; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import javax.persistence.Transient; - -import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -import com.cloud.utils.db.GenericDao; - @Entity @Table(name = "volume_reservation") public class VolumeReservationVO implements InternalIdentity{ @@ -42,7 +34,7 @@ public class VolumeReservationVO implements InternalIdentity{ private long id; @Column(name = "vm_reservation_id") - private Long vmReservationId; + private long vmReservationId; @Column(name = "vm_id") private long vmId; @@ -53,10 +45,6 @@ public class VolumeReservationVO implements InternalIdentity{ @Column(name="pool_id") private long poolId; - // VolumeId -> poolId - @Transient - Map volumeReservationMap; - /** * There should never be a public constructor for this class. Since it's * only here to define the table for the DAO class. @@ -64,7 +52,7 @@ public class VolumeReservationVO implements InternalIdentity{ protected VolumeReservationVO() { } - public VolumeReservationVO(long vmId, long volumeId, long poolId, Long vmReservationId) { + public VolumeReservationVO(long vmId, long volumeId, long poolId, long vmReservationId) { this.vmId = vmId; this.volumeId = volumeId; this.poolId = poolId; @@ -80,7 +68,7 @@ public class VolumeReservationVO implements InternalIdentity{ return vmId; } - public Long geVmReservationId() { + public long getVmReservationId() { return vmReservationId; } @@ -93,8 +81,4 @@ public class VolumeReservationVO implements InternalIdentity{ } - public Map getVolumeReservation(){ - return volumeReservationMap; - } - } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/dao/VolumeReservationDaoImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/dao/VolumeReservationDaoImpl.java index 26bc65f35c1..4f3761b7f45 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/dao/VolumeReservationDaoImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/db/dao/VolumeReservationDaoImpl.java @@ -49,7 +49,7 @@ public class VolumeReservationDaoImpl extends GenericDaoBase implements Alert AlertSearchByIdsAndType.and("type", AlertSearchByIdsAndType.entity().getType(), Op.EQ); AlertSearchByIdsAndType.and("createdDateL", AlertSearchByIdsAndType.entity().getCreatedDate(), Op.LT); AlertSearchByIdsAndType.and("data_center_id", AlertSearchByIdsAndType.entity().getDataCenterId(), Op.EQ); + AlertSearchByIdsAndType.and("archived", AlertSearchByIdsAndType.entity().getArchived(), Op.EQ); AlertSearchByIdsAndType.done(); } @@ -53,6 +54,7 @@ public class AlertDaoImpl extends GenericDaoBase implements Alert sc.addAnd("type", SearchCriteria.Op.EQ, Short.valueOf(type)); sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, Long.valueOf(dataCenterId)); + sc.addAnd("archived", SearchCriteria.Op.EQ, false); if (podId != null) { sc.addAnd("podId", SearchCriteria.Op.EQ, podId); } @@ -74,6 +76,7 @@ public class AlertDaoImpl extends GenericDaoBase implements Alert sc.addAnd("type", SearchCriteria.Op.EQ, Short.valueOf(type)); sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, Long.valueOf(dataCenterId)); + sc.addAnd("archived", SearchCriteria.Op.EQ, false); if (podId != null) { sc.addAnd("podId", SearchCriteria.Op.EQ, podId); } @@ -101,6 +104,8 @@ public class AlertDaoImpl extends GenericDaoBase implements Alert if(olderThan != null) { sc.setParameters("createdDateL", olderThan); } + sc.setParameters("archived", false); + boolean result = true;; List alerts = listBy(sc); if (Ids != null && alerts.size() < Ids.size()) { @@ -135,6 +140,8 @@ public class AlertDaoImpl extends GenericDaoBase implements Alert if(olderThan != null) { sc.setParameters("createdDateL", olderThan); } + sc.setParameters("archived", false); + boolean result = true; List alerts = listBy(sc); if (ids != null && alerts.size() < ids.size()) { @@ -150,6 +157,7 @@ public class AlertDaoImpl extends GenericDaoBase implements Alert if (oldTime == null) return null; SearchCriteria sc = createSearchCriteria(); sc.addAnd("createDate", SearchCriteria.Op.LT, oldTime); + sc.addAnd("archived", SearchCriteria.Op.EQ, false); return listIncludingRemovedBy(sc, null); } diff --git a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java index 111bcb122d6..dc5a65c8ef7 100644 --- a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java +++ b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java @@ -55,4 +55,6 @@ public interface ResourceCountDao extends GenericDao { Set listAllRowsToUpdate(long ownerId, ResourceOwnerType ownerType, ResourceType type); Set listRowsToUpdateForDomain(long domainId, ResourceType type); + + long removeEntriesByOwner(long ownerId, ResourceOwnerType ownerType); } diff --git a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java index 52bc746fd8e..cfd2137f479 100644 --- a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java +++ b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java @@ -219,4 +219,20 @@ public class ResourceCountDaoImpl extends GenericDaoBase return super.persist(resourceCountVO); } + + + @Override + public long removeEntriesByOwner(long ownerId, ResourceOwnerType ownerType) { + SearchCriteria sc = TypeSearch.create(); + + if (ownerType == ResourceOwnerType.Account) { + sc.setParameters("accountId", ownerId); + return remove(sc); + } else if (ownerType == ResourceOwnerType.Domain) { + sc.setParameters("domainId", ownerId); + return remove(sc); + } + return 0; + } + } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDao.java b/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDao.java index 5fd79b37bc4..e47b38340c2 100644 --- a/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDao.java +++ b/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDao.java @@ -32,4 +32,6 @@ public interface ResourceLimitDao extends GenericDao { ResourceCount.ResourceType getLimitType(String type); ResourceLimitVO findByOwnerIdAndType(long ownerId, ResourceOwnerType ownerType, ResourceCount.ResourceType type); + + long removeEntriesByOwner(Long ownerId, ResourceOwnerType ownerType); } diff --git a/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDaoImpl.java b/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDaoImpl.java index d337070e921..bb67f6bbe21 100644 --- a/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDaoImpl.java +++ b/engine/schema/src/com/cloud/configuration/dao/ResourceLimitDaoImpl.java @@ -97,4 +97,18 @@ public class ResourceLimitDaoImpl extends GenericDaoBase return null; } } + + @Override + public long removeEntriesByOwner(Long ownerId, ResourceOwnerType ownerType) { + SearchCriteria sc = IdTypeSearch.create(); + + if (ownerType == ResourceOwnerType.Account) { + sc.setParameters("accountId", ownerId); + return remove(sc); + } else if (ownerType == ResourceOwnerType.Domain) { + sc.setParameters("domainId", ownerId); + return remove(sc); + } + return 0; + } } diff --git a/engine/schema/src/com/cloud/event/dao/EventDaoImpl.java b/engine/schema/src/com/cloud/event/dao/EventDaoImpl.java index 0d3d38a0204..cefe1078dbd 100644 --- a/engine/schema/src/com/cloud/event/dao/EventDaoImpl.java +++ b/engine/schema/src/com/cloud/event/dao/EventDaoImpl.java @@ -44,6 +44,7 @@ public class EventDaoImpl extends GenericDaoBase implements Event CompletedEventSearch = createSearchBuilder(); CompletedEventSearch.and("state",CompletedEventSearch.entity().getState(),SearchCriteria.Op.EQ); CompletedEventSearch.and("startId", CompletedEventSearch.entity().getStartId(), SearchCriteria.Op.EQ); + CompletedEventSearch.and("archived", CompletedEventSearch.entity().getArchived(), Op.EQ); CompletedEventSearch.done(); ToArchiveOrDeleteEventSearch = createSearchBuilder(); @@ -51,6 +52,7 @@ public class EventDaoImpl extends GenericDaoBase implements Event ToArchiveOrDeleteEventSearch.and("type", ToArchiveOrDeleteEventSearch.entity().getType(), Op.EQ); ToArchiveOrDeleteEventSearch.and("accountIds", ToArchiveOrDeleteEventSearch.entity().getAccountId(), Op.IN); ToArchiveOrDeleteEventSearch.and("createDateL", ToArchiveOrDeleteEventSearch.entity().getCreateDate(), Op.LT); + ToArchiveOrDeleteEventSearch.and("archived", ToArchiveOrDeleteEventSearch.entity().getArchived(), Op.EQ); ToArchiveOrDeleteEventSearch.done(); } @@ -64,6 +66,7 @@ public class EventDaoImpl extends GenericDaoBase implements Event if (oldTime == null) return null; SearchCriteria sc = createSearchCriteria(); sc.addAnd("createDate", SearchCriteria.Op.LT, oldTime); + sc.addAnd("archived", SearchCriteria.Op.EQ, false); return listIncludingRemovedBy(sc, null); } @@ -72,6 +75,7 @@ public class EventDaoImpl extends GenericDaoBase implements Event SearchCriteria sc = CompletedEventSearch.create(); sc.setParameters("state", State.Completed); sc.setParameters("startId", startId); + sc.setParameters("archived", false); return findOneIncludingRemovedBy(sc); } @@ -90,6 +94,7 @@ public class EventDaoImpl extends GenericDaoBase implements Event if (accountIds != null && !accountIds.isEmpty()) { sc.setParameters("accountIds", accountIds.toArray(new Object[accountIds.size()])); } + sc.setParameters("archived", false); return search(sc, null); } diff --git a/engine/schema/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java b/engine/schema/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java index 04714a6a4de..c1c983489a3 100644 --- a/engine/schema/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java +++ b/engine/schema/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java @@ -198,7 +198,7 @@ public class ExternalLoadBalancerDeviceVO implements InternalIdentity, Identity } public void setGslbProvider(boolean gslbProvider) { - gslbProvider = gslbProvider; + this.gslbProvider = gslbProvider; } public void setGslbSitePublicIP(String gslbSitePublicIP) { diff --git a/engine/schema/src/com/cloud/network/dao/IPAddressVO.java b/engine/schema/src/com/cloud/network/dao/IPAddressVO.java index ae27e95ce4b..5eb2500e0a6 100644 --- a/engine/schema/src/com/cloud/network/dao/IPAddressVO.java +++ b/engine/schema/src/com/cloud/network/dao/IPAddressVO.java @@ -111,6 +111,8 @@ public class IPAddressVO implements IpAddress { @Column(name="dnat_vmip") private String vmIp; + @Column(name="is_portable") + private boolean portable = false; protected IPAddressVO() { this.uuid = UUID.randomUUID().toString(); @@ -134,6 +136,19 @@ public class IPAddressVO implements IpAddress { this.uuid = UUID.randomUUID().toString(); } + public IPAddressVO(Ip address, long dataCenterId, Long networkId, Long vpcId, long physicalNetworkId, long sourceNetworkId, + long vlanDbId, boolean portable) { + this.address = address; + this.dataCenterId = dataCenterId; + this.associatedWithNetworkId = networkId; + this.vpcId = vpcId; + this.physicalNetworkId = physicalNetworkId; + this.sourceNetworkId = sourceNetworkId; + this.vlanId = vlanDbId; + this.portable = portable; + this.uuid = UUID.randomUUID().toString(); + } + public long getMacAddress() { return macAddress; } @@ -283,6 +298,15 @@ public class IPAddressVO implements IpAddress { this.system = isSystem; } + @Override + public boolean isPortable() { + return portable; + } + + public void setPortable(boolean portable) { + this.portable = portable; + } + @Override public Long getVpcId() { return vpcId; diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java new file mode 100644 index 00000000000..b005c738e82 --- /dev/null +++ b/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java @@ -0,0 +1,73 @@ +// 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.service; + +import org.apache.cloudstack.api.InternalIdentity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="service_offering_details") +public class ServiceOfferingDetailsVO implements InternalIdentity { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="service_offering_id") + private long serviceOfferingId; + + @Column(name="name") + private String name; + + @Column(name="value") + private String value; + + protected ServiceOfferingDetailsVO() { + } + + public ServiceOfferingDetailsVO(long serviceOfferingId, String name, String value) { + this.serviceOfferingId = serviceOfferingId; + this.name = name; + this.value = value; + } + + public long getServiceOfferingId() { + return serviceOfferingId; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public long getId() { + return id; + } +} \ No newline at end of file diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java index fd31d301bc3..9a262c540b7 100755 --- a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java +++ b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.service; +import java.util.Map; + import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; @@ -71,6 +73,12 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering @Column(name = "deployment_planner") private String deploymentPlanner = null; + // This is a delayed load value. If the value is null, + // then this field has not been loaded yet. + // Call service offering dao to load it. + @Transient + Map details; + protected ServiceOfferingVO() { super(); } @@ -225,4 +233,23 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering return deploymentPlanner; } + public Map getDetails() { + return details; + } + + public String getDetail(String name) { + assert (details != null) : "Did you forget to load the details?"; + + return details != null ? details.get(name) : null; + } + + public void setDetail(String name, String value) { + assert (details != null) : "Did you forget to load the details?"; + + details.put(name, value); + } + + public void setDetails(Map details) { + this.details = details; + } } diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java index 589de7cc055..7da72088431 100644 --- a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java +++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java @@ -31,4 +31,6 @@ public interface ServiceOfferingDao extends GenericDao List findServiceOfferingByDomainId(Long domainId); List findSystemOffering(Long domainId, Boolean isSystem, String vm_type); ServiceOfferingVO persistDeafultServiceOffering(ServiceOfferingVO offering); + void loadDetails(ServiceOfferingVO serviceOffering); + void saveDetails(ServiceOfferingVO serviceOffering); } diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java index 062103e3198..14b2abf8fc4 100644 --- a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java +++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java @@ -18,15 +18,16 @@ package com.cloud.service.dao; import java.util.Date; import java.util.List; +import java.util.Map; import javax.ejb.Local; +import javax.inject.Inject; import javax.persistence.EntityExistsException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.service.ServiceOfferingVO; -import com.cloud.storage.DiskOfferingVO; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -37,6 +38,8 @@ import com.cloud.utils.db.SearchCriteria; public class ServiceOfferingDaoImpl extends GenericDaoBase implements ServiceOfferingDao { protected static final Logger s_logger = Logger.getLogger(ServiceOfferingDaoImpl.class); + @Inject protected ServiceOfferingDetailsDao detailsDao; + protected final SearchBuilder UniqueNameSearch; protected final SearchBuilder ServiceOfferingsByDomainIdSearch; protected final SearchBuilder SystemServiceOffering; @@ -154,4 +157,18 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase details = detailsDao.findDetails(serviceOffering.getId()); + serviceOffering.setDetails(details); + } + + @Override + public void saveDetails(ServiceOfferingVO serviceOffering) { + Map details = serviceOffering.getDetails(); + if (details != null) { + detailsDao.persist(serviceOffering.getId(), details); + } + } } diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDetailsDao.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDetailsDao.java new file mode 100644 index 00000000000..38169105819 --- /dev/null +++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDetailsDao.java @@ -0,0 +1,29 @@ +// 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.service.dao; + +import java.util.Map; + +import com.cloud.service.ServiceOfferingDetailsVO; +import com.cloud.utils.db.GenericDao; + +public interface ServiceOfferingDetailsDao extends GenericDao { + Map findDetails(long serviceOfferingId); + void persist(long serviceOfferingId, Map details); + ServiceOfferingDetailsVO findDetail(long serviceOfferingId, String name); + void deleteDetails(long serviceOfferingId); +} \ No newline at end of file diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java new file mode 100644 index 00000000000..91d736a38c4 --- /dev/null +++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDetailsDaoImpl.java @@ -0,0 +1,98 @@ +// 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.service.dao; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.service.ServiceOfferingDetailsVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; + +@Component +@Local(value=ServiceOfferingDetailsDao.class) +public class ServiceOfferingDetailsDaoImpl extends GenericDaoBase + implements ServiceOfferingDetailsDao { + protected final SearchBuilder ServiceOfferingSearch; + protected final SearchBuilder DetailSearch; + + public ServiceOfferingDetailsDaoImpl() { + ServiceOfferingSearch = createSearchBuilder(); + ServiceOfferingSearch.and("serviceOfferingId", ServiceOfferingSearch.entity().getServiceOfferingId(), SearchCriteria.Op.EQ); + ServiceOfferingSearch.done(); + + DetailSearch = createSearchBuilder(); + DetailSearch.and("serviceOfferingId", DetailSearch.entity().getServiceOfferingId(), SearchCriteria.Op.EQ); + DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); + DetailSearch.done(); + } + + @Override + public ServiceOfferingDetailsVO findDetail(long serviceOfferingId, String name) { + SearchCriteria sc = DetailSearch.create(); + sc.setParameters("serviceOfferingId", serviceOfferingId); + sc.setParameters("name", name); + ServiceOfferingDetailsVO detail = findOneIncludingRemovedBy(sc); + return detail; + } + + @Override + public Map findDetails(long serviceOfferingId) { + SearchCriteria sc = ServiceOfferingSearch.create(); + sc.setParameters("serviceOfferingId", serviceOfferingId); + List results = search(sc, null); + Map details = new HashMap(results.size()); + for (ServiceOfferingDetailsVO result : results) { + details.put(result.getName(), result.getValue()); + } + + return details; + } + + @Override + public void deleteDetails(long serviceOfferingId) { + SearchCriteria sc = ServiceOfferingSearch.create(); + sc.setParameters("serviceOfferingId", serviceOfferingId); + List results = search(sc, null); + for (ServiceOfferingDetailsVO result : results) { + remove(result.getId()); + } + } + + @Override + public void persist(long serviceOfferingId, Map details) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + SearchCriteria sc = ServiceOfferingSearch.create(); + sc.setParameters("serviceOfferingId", serviceOfferingId); + expunge(sc); + + for (Map.Entry detail : details.entrySet()) { + String value = detail.getValue(); + ServiceOfferingDetailsVO vo = new ServiceOfferingDetailsVO(serviceOfferingId, detail.getKey(), value); + persist(vo); + } + txn.commit(); + } +} diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 5e108e0a770..2e9f47fb364 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -75,6 +75,7 @@ public class Upgrade410to420 implements DbUpgrade { updateNetworkACLs(conn); addHostDetailsIndex(conn); updateNetworksForPrivateGateways(conn); + removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -749,4 +750,35 @@ public class Upgrade410to420 implements DbUpgrade { throw new CloudRuntimeException("Failed to update private networks with VPC id.", e); } } + + private void removeFirewallServiceFromSharedNetworkOfferingWithSGService(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = conn.prepareStatement("select id from `cloud`.`network_offerings` where unique_name='DefaultSharedNetworkOfferingWithSGService'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + // remove Firewall service for SG shared network offering + pstmt = conn.prepareStatement("DELETE `cloud`.`ntwk_offering_service_map` where network_offering_id=? and service='Firewall'"); + pstmt.setLong(1, id); + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to remove Firewall service for SG shared network offering.", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } + } diff --git a/framework/jobs/pom.xml b/framework/jobs/pom.xml index 5ae63af77ad..cf1fdd585a6 100644 --- a/framework/jobs/pom.xml +++ b/framework/jobs/pom.xml @@ -19,6 +19,7 @@ 4.0.0 cloud-framework-jobs + Apache CloudStack Framework - Jobs org.apache.cloudstack cloudstack-framework diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index 893a2455bc4..d918670edab 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -757,7 +757,10 @@ EOF fi if [ -n "$MGMTNET" -a -n "$LOCAL_GW" ] then - ip route add $MGMTNET via $LOCAL_GW dev eth1 + if [ "$hyp" == "vmware" ] + then + ip route add $MGMTNET via $LOCAL_GW dev eth0 + fi fi ip route delete default 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 4c2c7f1c131..6c3f57f1691 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 @@ -17,17 +17,24 @@ package org.apache.cloudstack.affinity; import java.util.List; +import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import javax.naming.ConfigurationException; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.framework.messagebus.MessageSubscriber; import org.apache.log4j.Logger; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; +import com.cloud.utils.DateUtil; +import com.cloud.utils.NumbersUtil; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @@ -46,7 +53,10 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements protected AffinityGroupDao _affinityGroupDao; @Inject protected AffinityGroupVMMapDao _affinityGroupVMMapDao; - + private int _vmCapacityReleaseInterval; + @Inject + protected ConfigurationDao _configDao; + @Override public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) @@ -76,12 +86,14 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements } } 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"); + long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - groupVM.getUpdateTime().getTime()) / 1000; + if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) { + 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 but has reserved capacity"); + } } - } } } @@ -89,5 +101,12 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements } } + + @Override + public boolean configure(final String name, final Map params) throws ConfigurationException { + super.configure(name, params); + _vmCapacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()),3600); + return true; + } } diff --git a/plugins/deployment-planners/implicit-dedication/pom.xml b/plugins/deployment-planners/implicit-dedication/pom.xml new file mode 100644 index 00000000000..18555923668 --- /dev/null +++ b/plugins/deployment-planners/implicit-dedication/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + cloud-plugin-planner-implicit-dedication + Apache CloudStack Plugin - Implicit Dedication Planner + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../pom.xml + + diff --git a/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java b/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java new file mode 100644 index 00000000000..d47d8f52c46 --- /dev/null +++ b/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java @@ -0,0 +1,249 @@ +// 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.deploy; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.configuration.Config; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.host.HostVO; +import com.cloud.resource.ResourceManager; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.service.dao.ServiceOfferingDetailsDao; +import com.cloud.user.Account; +import com.cloud.utils.DateUtil; +import com.cloud.utils.NumbersUtil; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=DeploymentPlanner.class) +public class ImplicitDedicationPlanner extends FirstFitPlanner implements DeploymentClusterPlanner { + + private static final Logger s_logger = Logger.getLogger(ImplicitDedicationPlanner.class); + + @Inject + private ServiceOfferingDao serviceOfferingDao; + @Inject + private ServiceOfferingDetailsDao serviceOfferingDetailsDao; + @Inject + private ResourceManager resourceMgr; + + private int capacityReleaseInterval; + + @Override + public boolean configure(final String name, final Map params) throws ConfigurationException { + super.configure(name, params); + capacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600); + return true; + } + + @Override + public List orderClusters(VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { + List clusterList = super.orderClusters(vmProfile, plan, avoid); + Set hostsToAvoid = avoid.getHostsToAvoid(); + Account account = vmProfile.getOwner(); + + if (clusterList == null || clusterList.isEmpty()) { + return clusterList; + } + + // Check if strict or preferred mode should be used. + boolean preferred = isServiceOfferingUsingPlannerInPreferredMode(vmProfile.getServiceOfferingId()); + + // Get the list of all the hosts in the given clusters + List allHosts = new ArrayList(); + for (Long cluster : clusterList) { + List hostsInCluster = resourceMgr.listAllHostsInCluster(cluster); + for (HostVO hostVO : hostsInCluster) { + allHosts.add(hostVO.getId()); + } + } + + // Go over all the hosts in the cluster and get a list of + // 1. All empty hosts, not running any vms. + // 2. Hosts running vms for this account and created by a service offering which uses an + // implicit dedication planner. + // 3. Hosts running vms created by implicit planner and in strict mode of other accounts. + // 4. Hosts running vms from other account or from this account but created by a service offering which uses + // any planner besides implicit. + Set emptyHosts = new HashSet(); + Set hostRunningVmsOfAccount = new HashSet(); + Set hostRunningStrictImplicitVmsOfOtherAccounts = new HashSet(); + Set allOtherHosts = new HashSet(); + for (Long host : allHosts) { + List userVms = getVmsOnHost(host); + if (userVms == null || userVms.isEmpty()) { + emptyHosts.add(host); + } else if (checkHostSuitabilityForImplicitDedication(account.getAccountId(), userVms)) { + hostRunningVmsOfAccount.add(host); + } else if (checkIfAllVmsCreatedInStrictMode(account.getAccountId(), userVms)) { + hostRunningStrictImplicitVmsOfOtherAccounts.add(host); + } else { + allOtherHosts.add(host); + } + } + + // Hosts running vms of other accounts created by ab implicit planner in strict mode should always be avoided. + avoid.addHostList(hostRunningStrictImplicitVmsOfOtherAccounts); + + if (!hostRunningVmsOfAccount.isEmpty() && (hostsToAvoid == null || + !hostsToAvoid.containsAll(hostRunningVmsOfAccount))) { + // Check if any of hosts that are running implicit dedicated vms are available (not in avoid list). + // If so, we'll try and use these hosts. + avoid.addHostList(emptyHosts); + avoid.addHostList(allOtherHosts); + clusterList = getUpdatedClusterList(clusterList, avoid.getHostsToAvoid()); + } else if (!emptyHosts.isEmpty() && (hostsToAvoid == null || !hostsToAvoid.containsAll(emptyHosts))) { + // If there aren't implicit resources try on empty hosts + avoid.addHostList(allOtherHosts); + clusterList = getUpdatedClusterList(clusterList, avoid.getHostsToAvoid()); + } else if (!preferred) { + // If in strict mode, there is nothing else to try. + clusterList = null; + } else { + // If in preferred mode, check if hosts are available to try, otherwise return an empty cluster list. + if (!allOtherHosts.isEmpty() && (hostsToAvoid == null || !hostsToAvoid.containsAll(allOtherHosts))) { + clusterList = getUpdatedClusterList(clusterList, avoid.getHostsToAvoid()); + } else { + clusterList = null; + } + } + + return clusterList; + } + + private List getVmsOnHost(long hostId) { + List vms = _vmDao.listUpByHostId(hostId); + List vmsByLastHostId = _vmDao.listByLastHostId(hostId); + if (vmsByLastHostId.size() > 0) { + // check if any VMs are within skip.counting.hours, if yes we have to consider the host. + for (UserVmVO stoppedVM : vmsByLastHostId) { + long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - stoppedVM.getUpdateTime() + .getTime()) / 1000; + if (secondsSinceLastUpdate < capacityReleaseInterval) { + vms.add(stoppedVM); + } + } + } + + return vms; + } + + private boolean checkHostSuitabilityForImplicitDedication(Long accountId, List allVmsOnHost) { + boolean suitable = true; + for (UserVmVO vm : allVmsOnHost) { + if (vm.getAccountId() != accountId) { + s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for implicit dedication as it is " + + "running instances of another account"); + suitable = false; + break; + } else { + if (!isImplicitPlannerUsedByOffering(vm.getServiceOfferingId())) { + s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for implicit dedication as it " + + "is running instances of this account which haven't been created using implicit dedication."); + suitable = false; + break; + } + } + } + return suitable; + } + + private boolean checkIfAllVmsCreatedInStrictMode(Long accountId, List allVmsOnHost) { + boolean createdByImplicitStrict = true; + for (UserVmVO vm : allVmsOnHost) { + if (!isImplicitPlannerUsedByOffering(vm.getServiceOfferingId())) { + s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by a planner other" + + " than implicit."); + createdByImplicitStrict = false; + break; + } else if (isServiceOfferingUsingPlannerInPreferredMode(vm.getServiceOfferingId())) { + s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by an implicit planner" + + " in preferred mode."); + createdByImplicitStrict = false; + break; + } + } + return createdByImplicitStrict; + } + + private boolean isImplicitPlannerUsedByOffering(long offeringId) { + boolean implicitPlannerUsed = false; + ServiceOfferingVO offering = serviceOfferingDao.findByIdIncludingRemoved(offeringId); + if (offering == null) { + s_logger.error("Couldn't retrieve the offering by the given id : " + offeringId); + } else { + String plannerName = offering.getDeploymentPlanner(); + if (plannerName == null) { + plannerName = _globalDeploymentPlanner; + } + + if (plannerName != null && this.getName().equals(plannerName)) { + implicitPlannerUsed = true; + } + } + + return implicitPlannerUsed; + } + + private boolean isServiceOfferingUsingPlannerInPreferredMode(long serviceOfferingId) { + boolean preferred = false; + Map details = serviceOfferingDetailsDao.findDetails(serviceOfferingId); + if (details != null && !details.isEmpty()) { + String preferredAttribute = details.get("ImplicitDedicationMode"); + if (preferredAttribute != null && preferredAttribute.equals("Preferred")) { + preferred = true; + } + } + return preferred; + } + + private List getUpdatedClusterList(List clusterList, Set hostsSet) { + List updatedClusterList = new ArrayList(); + for (Long cluster : clusterList) { + List hosts = resourceMgr.listAllHostsInCluster(cluster); + Set hostsInClusterSet = new HashSet(); + for (HostVO host : hosts) { + hostsInClusterSet.add(host.getId()); + } + + if (!hostsSet.containsAll(hostsInClusterSet)) { + updatedClusterList.add(cluster); + } + } + + return updatedClusterList; + } + + @Override + public PlannerResourceUsage getResourceUsage() { + return PlannerResourceUsage.Dedicated; + } +} \ No newline at end of file diff --git a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java new file mode 100644 index 00000000000..44507600db9 --- /dev/null +++ b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java @@ -0,0 +1,586 @@ +// 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.implicitplanner; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.cloud.capacity.CapacityManager; +import com.cloud.capacity.CapacityVO; +import com.cloud.capacity.dao.CapacityDao; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.deploy.ImplicitDedicationPlanner; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.service.dao.ServiceOfferingDetailsDao; +import com.cloud.storage.StorageManager; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.GuestOSCategoryDao; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.utils.Pair; +import com.cloud.utils.component.ComponentContext; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class ImplicitPlannerTest { + + @Inject + ImplicitDedicationPlanner planner = new ImplicitDedicationPlanner(); + @Inject + HostDao hostDao; + @Inject + DataCenterDao dcDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + GuestOSDao guestOSDao; + @Inject + GuestOSCategoryDao guestOSCategoryDao; + @Inject + DiskOfferingDao diskOfferingDao; + @Inject + StoragePoolHostDao poolHostDao; + @Inject + UserVmDao vmDao; + @Inject + VMInstanceDao vmInstanceDao; + @Inject + VolumeDao volsDao; + @Inject + CapacityManager capacityMgr; + @Inject + ConfigurationDao configDao; + @Inject + PrimaryDataStoreDao storagePoolDao; + @Inject + CapacityDao capacityDao; + @Inject + AccountManager accountMgr; + @Inject + StorageManager storageMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + ClusterDetailsDao clusterDetailsDao; + @Inject + ServiceOfferingDao serviceOfferingDao; + @Inject + ServiceOfferingDetailsDao serviceOfferingDetailsDao; + @Inject + ResourceManager resourceMgr; + + private static long domainId = 5L; + long dataCenterId = 1L; + long accountId = 200L; + long offeringId = 12L; + int noOfCpusInOffering = 1; + int cpuSpeedInOffering = 500; + int ramInOffering = 512; + AccountVO acct = new AccountVO(accountId); + + @BeforeClass + public static void setUp() throws ConfigurationException { + } + + @Before + public void testSetUp() { + ComponentContext.initComponentsLifeCycle(); + + acct.setType(Account.ACCOUNT_TYPE_NORMAL); + acct.setAccountName("user1"); + acct.setDomainId(domainId); + acct.setId(accountId); + + UserContext.registerContext(1, acct, null, true); + } + + @Test + public void checkWhenDcInAvoidList() throws InsufficientServerCapacityException { + DataCenterVO mockDc = mock(DataCenterVO.class); + ExcludeList avoids = mock(ExcludeList.class); + @SuppressWarnings("unchecked") + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VMInstanceVO vm = mock(VMInstanceVO.class); + DataCenterDeployment plan = mock(DataCenterDeployment.class); + + when(avoids.shouldAvoid(mockDc)).thenReturn(true); + when(vmProfile.getVirtualMachine()).thenReturn(vm); + when(vm.getDataCenterId()).thenReturn(1L); + when(dcDao.findById(1L)).thenReturn(mockDc); + + List clusterList = planner.orderClusters(vmProfile, plan, avoids); + assertTrue("Cluster list should be null/empty if the dc is in avoid list", + (clusterList == null || clusterList.isEmpty())); + } + + @Test + public void checkStrictModeWithCurrentAccountVmsPresent() throws InsufficientServerCapacityException { + @SuppressWarnings("unchecked") + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + DataCenterDeployment plan = mock(DataCenterDeployment.class); + ExcludeList avoids = new ExcludeList(); + + initializeForTest(vmProfile, plan); + + initializeForImplicitPlannerTest(false); + + List clusterList = planner.orderClusters(vmProfile, plan, avoids); + + // Validations. + // Check cluster 2 and 3 are not in the cluster list. + // Host 6 and 7 should also be in avoid list. + assertFalse("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); + boolean foundNeededCluster = false; + for (Long cluster : clusterList) { + if (cluster != 1) { + fail("Found a cluster that shouldn't have been present, cluster id : " + cluster); + }else { + foundNeededCluster = true; + } + } + assertTrue("Didn't find cluster 1 in the list. It should have been present", foundNeededCluster); + + Set hostsInAvoidList = avoids.getHostsToAvoid(); + assertFalse("Host 5 shouldn't have be in the avoid list, but it is present", hostsInAvoidList.contains(5L)); + Set hostsThatShouldBeInAvoidList = new HashSet(); + hostsThatShouldBeInAvoidList.add(6L); + hostsThatShouldBeInAvoidList.add(7L); + assertTrue("Hosts 6 and 7 that should have been present were not found in avoid list" , + hostsInAvoidList.containsAll(hostsThatShouldBeInAvoidList)); + } + + @Test + public void checkStrictModeHostWithCurrentAccountVmsFull() throws InsufficientServerCapacityException { + @SuppressWarnings("unchecked") + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + DataCenterDeployment plan = mock(DataCenterDeployment.class); + ExcludeList avoids = new ExcludeList(); + + initializeForTest(vmProfile, plan); + + initializeForImplicitPlannerTest(false); + + // Mark the host 5 with current account vms to be in avoid list. + avoids.addHost(5L); + List clusterList = planner.orderClusters(vmProfile, plan, avoids); + + // Validations. + // Check cluster 1 and 3 are not in the cluster list. + // Host 5 and 7 should also be in avoid list. + assertFalse("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); + boolean foundNeededCluster = false; + for (Long cluster : clusterList) { + if (cluster != 2) { + fail("Found a cluster that shouldn't have been present, cluster id : " + cluster); + }else { + foundNeededCluster = true; + } + } + assertTrue("Didn't find cluster 2 in the list. It should have been present", foundNeededCluster); + + Set hostsInAvoidList = avoids.getHostsToAvoid(); + assertFalse("Host 6 shouldn't have be in the avoid list, but it is present", hostsInAvoidList.contains(6L)); + Set hostsThatShouldBeInAvoidList = new HashSet(); + hostsThatShouldBeInAvoidList.add(5L); + hostsThatShouldBeInAvoidList.add(7L); + assertTrue("Hosts 5 and 7 that should have been present were not found in avoid list" , + hostsInAvoidList.containsAll(hostsThatShouldBeInAvoidList)); + } + + @Test + public void checkStrictModeNoHostsAvailable() throws InsufficientServerCapacityException { + @SuppressWarnings("unchecked") + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + DataCenterDeployment plan = mock(DataCenterDeployment.class); + ExcludeList avoids = new ExcludeList(); + + initializeForTest(vmProfile, plan); + + initializeForImplicitPlannerTest(false); + + // Mark the host 5 and 6 to be in avoid list. + avoids.addHost(5L); + avoids.addHost(6L); + List clusterList = planner.orderClusters(vmProfile, plan, avoids); + + // Validations. + // Check cluster list is empty. + assertTrue("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); + } + + @Test + public void checkPreferredModePreferredHostAvailable() throws InsufficientServerCapacityException { + @SuppressWarnings("unchecked") + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + DataCenterDeployment plan = mock(DataCenterDeployment.class); + ExcludeList avoids = new ExcludeList(); + + initializeForTest(vmProfile, plan); + + initializeForImplicitPlannerTest(true); + + // Mark the host 5 and 6 to be in avoid list. + avoids.addHost(5L); + avoids.addHost(6L); + List clusterList = planner.orderClusters(vmProfile, plan, avoids); + + // Validations. + // Check cluster 1 and 2 are not in the cluster list. + // Host 5 and 6 should also be in avoid list. + assertFalse("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); + boolean foundNeededCluster = false; + for (Long cluster : clusterList) { + if (cluster != 3) { + fail("Found a cluster that shouldn't have been present, cluster id : " + cluster); + } else { + foundNeededCluster = true; + } + } + assertTrue("Didn't find cluster 3 in the list. It should have been present", foundNeededCluster); + + Set hostsInAvoidList = avoids.getHostsToAvoid(); + assertFalse("Host 7 shouldn't have be in the avoid list, but it is present", hostsInAvoidList.contains(7L)); + Set hostsThatShouldBeInAvoidList = new HashSet(); + hostsThatShouldBeInAvoidList.add(5L); + hostsThatShouldBeInAvoidList.add(6L); + assertTrue("Hosts 5 and 6 that should have been present were not found in avoid list" , + hostsInAvoidList.containsAll(hostsThatShouldBeInAvoidList)); + } + + @Test + public void checkPreferredModeNoHostsAvailable() throws InsufficientServerCapacityException { + @SuppressWarnings("unchecked") + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + DataCenterDeployment plan = mock(DataCenterDeployment.class); + ExcludeList avoids = new ExcludeList(); + + initializeForTest(vmProfile, plan); + + initializeForImplicitPlannerTest(false); + + // Mark the host 5, 6 and 7 to be in avoid list. + avoids.addHost(5L); + avoids.addHost(6L); + avoids.addHost(7L); + List clusterList = planner.orderClusters(vmProfile, plan, avoids); + + // Validations. + // Check cluster list is empty. + assertTrue("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); + } + + private void initializeForTest(VirtualMachineProfileImpl vmProfile, DataCenterDeployment plan) { + DataCenterVO mockDc = mock(DataCenterVO.class); + VMInstanceVO vm = mock(VMInstanceVO.class); + UserVmVO userVm = mock(UserVmVO.class); + ServiceOfferingVO offering = mock(ServiceOfferingVO.class); + + AccountVO account = mock(AccountVO.class); + when(account.getId()).thenReturn(accountId); + when(account.getAccountId()).thenReturn(accountId); + when(vmProfile.getOwner()).thenReturn(account); + when(vmProfile.getVirtualMachine()).thenReturn(vm); + when(vmProfile.getId()).thenReturn(12L); + when(vmDao.findById(12L)).thenReturn(userVm); + when(userVm.getAccountId()).thenReturn(accountId); + + when(vm.getDataCenterId()).thenReturn(dataCenterId); + when(dcDao.findById(1L)).thenReturn(mockDc); + when(plan.getDataCenterId()).thenReturn(dataCenterId); + when(plan.getClusterId()).thenReturn(null); + when(plan.getPodId()).thenReturn(null); + when(configDao.getValue(anyString())).thenReturn("false").thenReturn("CPU"); + + // Mock offering details. + when(vmProfile.getServiceOffering()).thenReturn(offering); + when(offering.getId()).thenReturn(offeringId); + when(vmProfile.getServiceOfferingId()).thenReturn(offeringId); + when(offering.getCpu()).thenReturn(noOfCpusInOffering); + when(offering.getSpeed()).thenReturn(cpuSpeedInOffering); + when(offering.getRamSize()).thenReturn(ramInOffering); + + List clustersWithEnoughCapacity = new ArrayList(); + clustersWithEnoughCapacity.add(1L); + clustersWithEnoughCapacity.add(2L); + clustersWithEnoughCapacity.add(3L); + when(capacityDao.listClustersInZoneOrPodByHostCapacities(dataCenterId, noOfCpusInOffering * cpuSpeedInOffering, + ramInOffering * 1024L * 1024L, CapacityVO.CAPACITY_TYPE_CPU, true)).thenReturn(clustersWithEnoughCapacity); + + Map clusterCapacityMap = new HashMap(); + clusterCapacityMap.put(1L, 2048D); + clusterCapacityMap.put(2L, 2048D); + clusterCapacityMap.put(3L, 2048D); + Pair, Map> clustersOrderedByCapacity = + new Pair, Map>(clustersWithEnoughCapacity, clusterCapacityMap); + when(capacityDao.orderClustersByAggregateCapacity(dataCenterId, CapacityVO.CAPACITY_TYPE_CPU, + true)).thenReturn(clustersOrderedByCapacity); + + List disabledClusters = new ArrayList(); + List clustersWithDisabledPods = new ArrayList(); + when(clusterDao.listDisabledClusters(dataCenterId, null)).thenReturn(disabledClusters); + when(clusterDao.listClustersWithDisabledPods(dataCenterId)).thenReturn(clustersWithDisabledPods); + } + + private void initializeForImplicitPlannerTest(boolean preferred) { + String plannerMode = new String("Strict"); + if (preferred) { + plannerMode = new String("Preferred"); + } + + Map details = new HashMap(); + details.put("ImplicitDedicationMode", plannerMode); + when(serviceOfferingDetailsDao.findDetails(offeringId)).thenReturn(details); + + // Initialize hosts in clusters + HostVO host1 = mock(HostVO.class); + when(host1.getId()).thenReturn(5L); + HostVO host2 = mock(HostVO.class); + when(host2.getId()).thenReturn(6L); + HostVO host3 = mock(HostVO.class); + when(host3.getId()).thenReturn(7L); + List hostsInCluster1 = new ArrayList(); + List hostsInCluster2 = new ArrayList(); + List hostsInCluster3 = new ArrayList(); + hostsInCluster1.add(host1); + hostsInCluster2.add(host2); + hostsInCluster3.add(host3); + when(resourceMgr.listAllHostsInCluster(1)).thenReturn(hostsInCluster1); + when(resourceMgr.listAllHostsInCluster(2)).thenReturn(hostsInCluster2); + when(resourceMgr.listAllHostsInCluster(3)).thenReturn(hostsInCluster3); + + // Mock vms on each host. + long offeringIdForVmsOfThisAccount = 15L; + long offeringIdForVmsOfOtherAccount = 16L; + UserVmVO vm1 = mock(UserVmVO.class); + when(vm1.getAccountId()).thenReturn(accountId); + when(vm1.getServiceOfferingId()).thenReturn(offeringIdForVmsOfThisAccount); + UserVmVO vm2 = mock(UserVmVO.class); + when(vm2.getAccountId()).thenReturn(accountId); + when(vm2.getServiceOfferingId()).thenReturn(offeringIdForVmsOfThisAccount); + // Vm from different account + UserVmVO vm3 = mock(UserVmVO.class); + when(vm3.getAccountId()).thenReturn(201L); + when(vm3.getServiceOfferingId()).thenReturn(offeringIdForVmsOfOtherAccount); + List userVmsForHost1 = new ArrayList(); + List userVmsForHost2 = new ArrayList(); + List userVmsForHost3 = new ArrayList(); + List stoppedVmsForHost = new ArrayList(); + // Host 2 is empty. + userVmsForHost1.add(vm1); + userVmsForHost1.add(vm2); + userVmsForHost3.add(vm3); + when(vmDao.listUpByHostId(5L)).thenReturn(userVmsForHost1); + when(vmDao.listUpByHostId(6L)).thenReturn(userVmsForHost2); + when(vmDao.listUpByHostId(7L)).thenReturn(userVmsForHost3); + when(vmDao.listByLastHostId(5L)).thenReturn(stoppedVmsForHost); + when(vmDao.listByLastHostId(6L)).thenReturn(stoppedVmsForHost); + when(vmDao.listByLastHostId(7L)).thenReturn(stoppedVmsForHost); + + // Mock the offering with which the vm was created. + ServiceOfferingVO offeringForVmOfThisAccount = mock(ServiceOfferingVO.class); + when(serviceOfferingDao.findByIdIncludingRemoved(offeringIdForVmsOfThisAccount)).thenReturn(offeringForVmOfThisAccount); + when(offeringForVmOfThisAccount.getDeploymentPlanner()).thenReturn(planner.getName()); + + ServiceOfferingVO offeringForVMOfOtherAccount = mock(ServiceOfferingVO.class); + when(serviceOfferingDao.findByIdIncludingRemoved(offeringIdForVmsOfOtherAccount)).thenReturn(offeringForVMOfOtherAccount); + when(offeringForVMOfOtherAccount.getDeploymentPlanner()).thenReturn("FirstFitPlanner"); + } + + @Configuration + @ComponentScan(basePackageClasses = { ImplicitDedicationPlanner.class }, + includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, + useDefaultFilters = false) + public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration { + + @Bean + public HostDao hostDao() { + return Mockito.mock(HostDao.class); + } + + @Bean + public DataCenterDao dcDao() { + return Mockito.mock(DataCenterDao.class); + } + + @Bean + public HostPodDao hostPodDao() { + return Mockito.mock(HostPodDao.class); + } + + @Bean + public ClusterDao clusterDao() { + return Mockito.mock(ClusterDao.class); + } + + @Bean + public GuestOSDao guestOsDao() { + return Mockito.mock(GuestOSDao.class); + } + + @Bean + public GuestOSCategoryDao guestOsCategoryDao() { + return Mockito.mock(GuestOSCategoryDao.class); + } + + @Bean + public DiskOfferingDao diskOfferingDao() { + return Mockito.mock(DiskOfferingDao.class); + } + + @Bean + public StoragePoolHostDao storagePoolHostDao() { + return Mockito.mock(StoragePoolHostDao.class); + } + + @Bean + public UserVmDao userVmDao() { + return Mockito.mock(UserVmDao.class); + } + + @Bean + public VMInstanceDao vmInstanceDao() { + return Mockito.mock(VMInstanceDao.class); + } + + @Bean + public VolumeDao volumeDao() { + return Mockito.mock(VolumeDao.class); + } + + @Bean + public CapacityManager capacityManager() { + return Mockito.mock(CapacityManager.class); + } + + @Bean + public ConfigurationDao configurationDao() { + return Mockito.mock(ConfigurationDao.class); + } + + @Bean + public PrimaryDataStoreDao primaryDataStoreDao() { + return Mockito.mock(PrimaryDataStoreDao.class); + } + + @Bean + public CapacityDao capacityDao() { + return Mockito.mock(CapacityDao.class); + } + + @Bean + public AccountManager accountManager() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public StorageManager storageManager() { + return Mockito.mock(StorageManager.class); + } + + @Bean + public DataStoreManager dataStoreManager() { + return Mockito.mock(DataStoreManager.class); + } + + @Bean + public ClusterDetailsDao clusterDetailsDao() { + return Mockito.mock(ClusterDetailsDao.class); + } + + @Bean + public ServiceOfferingDao serviceOfferingDao() { + return Mockito.mock(ServiceOfferingDao.class); + } + + @Bean + public ServiceOfferingDetailsDao serviceOfferingDetailsDao() { + return Mockito.mock(ServiceOfferingDetailsDao.class); + } + + @Bean + public ResourceManager resourceManager() { + return Mockito.mock(ResourceManager.class); + } + + public static class Library implements TypeFilter { + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 39375f8ebd3..ee8531b5ca9 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -243,7 +243,7 @@ import com.cloud.vm.VirtualMachineName; /** * LibvirtComputingResource execute requests on the computing/routing host using * the libvirt API - * + * * @config {@table || Param Name | Description | Values | Default || || * hypervisor.type | type of local hypervisor | string | kvm || || * hypervisor.uri | local hypervisor to connect to | URI | @@ -394,7 +394,7 @@ ServerResource { } protected BridgeType _bridgeType; - + protected StorageSubsystemCommandHandler storageHandler; private String getEndIpFromStartIp(String startIp, int numIps) { @@ -605,13 +605,13 @@ ServerResource { throw new ConfigurationException( "Unable to find the ovs-pvlan-dhcp-host.sh"); } - + _ovsPvlanVmPath = Script.findScript(networkScriptsDir, "ovs-pvlan-vm.sh"); if ( _ovsPvlanVmPath == null) { throw new ConfigurationException( "Unable to find the ovs-pvlan-vm.sh"); } - + String value = (String) params.get("developer"); boolean isDeveloper = Boolean.parseBoolean(value); @@ -691,7 +691,7 @@ ServerResource { if (_localStoragePath == null) { _localStoragePath = "/var/lib/libvirt/images/"; } - + File storagePath = new File(_localStoragePath); _localStoragePath = storagePath.getAbsolutePath(); @@ -835,7 +835,7 @@ ServerResource { params.put("libvirt.computing.resource", this); configureVifDrivers(params); - + KVMStorageProcessor storageProcessor = new KVMStorageProcessor(this._storagePoolMgr, this); storageProcessor.configure(name, params); storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor); @@ -987,13 +987,13 @@ ServerResource { return pif; } - + private String matchPifFileInDirectory(String bridgeName){ File f = new File("/sys/devices/virtual/net/" + bridgeName + "/brif"); if (! f.isDirectory()){ s_logger.debug("failing to get physical interface from bridge" - + bridgeName + ", does " + f.getAbsolutePath() + + bridgeName + ", does " + f.getAbsolutePath() + "exist?"); return ""; } @@ -1063,7 +1063,7 @@ ServerResource { return vnetId; } - private void passCmdLine(String vmName, String cmdLine) + private void passCmdLine(String vmName, String cmdLine) throws InternalErrorException { final Script command = new Script(_patchViaSocketPath, _timeout, s_logger); String result; @@ -1373,7 +1373,7 @@ ServerResource { disksize = dskch.getSize(); if (cmd.getTemplateUrl() != null) { - if(primaryPool.getType() == StoragePoolType.CLVM) { + if(primaryPool.getType() == StoragePoolType.CLVM) { vol = templateToPrimaryDownload(cmd.getTemplateUrl(),primaryPool); } else { BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl()); @@ -1450,7 +1450,7 @@ ServerResource { private String getResizeScriptType (KVMStoragePool pool, KVMPhysicalDisk vol) { StoragePoolType poolType = pool.getType(); PhysicalDiskFormat volFormat = vol.getFormat(); - + if(pool.getType() == StoragePoolType.CLVM && volFormat == PhysicalDiskFormat.RAW) { return "CLVM"; } else if ((poolType == StoragePoolType.NetworkFilesystem @@ -1462,7 +1462,7 @@ ServerResource { return null; } - /* uses a local script now, eventually support for virStorageVolResize() will maybe work on + /* uses a local script now, eventually support for virStorageVolResize() will maybe work on qcow2 and lvm and we can do this in libvirt calls */ public Answer execute(ResizeVolumeCommand cmd) { String volid = cmd.getPath(); @@ -1479,16 +1479,16 @@ ServerResource { String type = getResizeScriptType(pool, vol); if (type == null) { - return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + pool.getType() + "' and volume format '" + vol.getFormat() + "'"); } else if (type.equals("QCOW2") && shrinkOk) { return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); } - s_logger.debug("got to the stage where we execute the volume resize, params:" + s_logger.debug("got to the stage where we execute the volume resize, params:" + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); final Script resizecmd = new Script(_resizeVolumePath, - _cmdsTimeout, s_logger); + _cmdsTimeout, s_logger); resizecmd.add("-s",String.valueOf(newSize)); resizecmd.add("-c",String.valueOf(currentSize)); resizecmd.add("-p",path); @@ -1512,8 +1512,8 @@ ServerResource { s_logger.debug(error); return new ResizeVolumeAnswer(cmd, false, error); } - - } + + } public Answer execute(DestroyCommand cmd) { VolumeTO vol = cmd.getVolume(); @@ -1537,7 +1537,7 @@ ServerResource { if(pifparts.length == 2) { return pifparts[1]; } else { - s_logger.debug("failed to get vlan id from bridge " + brName + s_logger.debug("failed to get vlan id from bridge " + brName + "attached to physical interface" + pif); return ""; } @@ -1552,13 +1552,13 @@ ServerResource { String dhcpIp = cmd.getDhcpIp(); String vmMac = cmd.getVmMac(); boolean add = true; - + String opr = "-A"; if (op.equals("delete")) { opr = "-D"; add = false; } - + String result = null; Connect conn; try { @@ -1722,7 +1722,7 @@ ServerResource { private SetNetworkACLAnswer execute(SetNetworkACLCommand cmd) { String[] results = new String[cmd.getRules().length]; - + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); String privateGw = cmd.getAccessDetail(NetworkElementCommand.VPC_PRIVATE_GATEWAY); @@ -1772,7 +1772,7 @@ ServerResource { for (InterfaceDef pluggedNic : pluggedNics) { String pluggedVlanBr = pluggedNic.getBrName(); String pluggedVlanId = getVlanIdFromBridge(pluggedVlanBr); - if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) + if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) && pluggedVlanBr.equalsIgnoreCase(_publicBridgeName)) { break; } else if (pluggedVlanBr.equalsIgnoreCase(_linkLocalBridgeName)){ @@ -1818,7 +1818,7 @@ ServerResource { for (InterfaceDef pluggedNic : pluggedNics) { String pluggedVlan = pluggedNic.getBrName(); if (pluggedVlan.equalsIgnoreCase(_linkLocalBridgeName)) { - vlanToNicNum.put("LinkLocal",devNum); + vlanToNicNum.put("LinkLocal",devNum); } else if (pluggedVlan.equalsIgnoreCase(_publicBridgeName) || pluggedVlan.equalsIgnoreCase(_privBridgeName) || pluggedVlan.equalsIgnoreCase(_guestBridgeName)) { @@ -1864,8 +1864,8 @@ ServerResource { if (nic.getBrName().equalsIgnoreCase(_linkLocalBridgeName)) { vlanAllocatedToVM.put("LinkLocal", nicPos); } else { - if (nic.getBrName().equalsIgnoreCase(_publicBridgeName) - || nic.getBrName().equalsIgnoreCase(_privBridgeName) + if (nic.getBrName().equalsIgnoreCase(_publicBridgeName) + || nic.getBrName().equalsIgnoreCase(_privBridgeName) || nic.getBrName().equalsIgnoreCase(_guestBridgeName)) { vlanAllocatedToVM.put(Vlan.UNTAGGED, nicPos); } else { @@ -2613,8 +2613,7 @@ ServerResource { Domain vms = null; while (retry-- > 0) { try { - vms = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + vms = conn.domainLookupByName(vmName); State s = convertToState(vms.getInfo().state); return s; } catch (final LibvirtException e) { @@ -2706,8 +2705,7 @@ ServerResource { try { conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName()); ifaces = getInterfaces(conn, vmName); - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); dconn = new Connect("qemu+tcp://" + cmd.getDestinationIp() + "/system"); /* @@ -2722,6 +2720,9 @@ ServerResource { } finally { try { if (dm != null) { + if (dm.isPersistent() == 1) { + dm.undefine(); + } dm.free(); } if (dconn != null) { @@ -3153,8 +3154,7 @@ ServerResource { protected LibvirtVMDef createVMFromSpec(VirtualMachineTO vmTO) { LibvirtVMDef vm = new LibvirtVMDef(); vm.setDomainName(vmTO.getName()); - vm.setDomUUID(UUID.nameUUIDFromBytes(vmTO.getName().getBytes()) - .toString()); + vm.setDomUUID(vmTO.getUuid()); vm.setDomDescription(vmTO.getOs()); GuestDef guest = new GuestDef(); @@ -3355,7 +3355,7 @@ ServerResource { throws LibvirtException, URISyntaxException { DataTO data = volume.getData(); DataStoreTO store = data.getDataStore(); - + if (volume.getType() == Volume.Type.ISO && data.getPath() != null) { NfsTO nfsStore = (NfsTO)store; String isoPath = nfsStore.getUrl() + File.separator + data.getPath(); @@ -3574,10 +3574,10 @@ ServerResource { List disks = null; Domain dm = null; DiskDef diskdef = null; + KVMStoragePool attachingPool = attachingDisk.getPool(); try { if (!attach) { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); String xml = dm.getXMLDesc(0); parser.parseDomainXML(xml); @@ -3598,7 +3598,12 @@ ServerResource { } } else { diskdef = new DiskDef(); - if (attachingDisk.getFormat() == PhysicalDiskFormat.QCOW2) { + if (attachingPool.getType() == StoragePoolType.RBD) { + diskdef.defNetworkBasedDisk(attachingDisk.getPath(), + attachingPool.getSourceHost(), attachingPool.getSourcePort(), + attachingPool.getAuthUserName(), attachingPool.getUuid(), devId, + DiskDef.diskBus.VIRTIO, diskProtocol.RBD); + } else if (attachingDisk.getFormat() == PhysicalDiskFormat.QCOW2) { diskdef.defFileBasedDisk(attachingDisk.getPath(), devId, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); } else if (attachingDisk.getFormat() == PhysicalDiskFormat.RAW) { @@ -3621,9 +3626,7 @@ ServerResource { InternalErrorException { Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes((vmName - .getBytes()))); - + dm = conn.domainLookupByName(vmName); if (attach) { s_logger.debug("Attaching device: " + xml); dm.attachDevice(xml); @@ -3854,8 +3857,7 @@ ServerResource { for (; i < 5; i++) { try { Connect conn = LibvirtConnection.getConnectionByVmName(vm); - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vm - .getBytes())); + dm = conn.domainLookupByName(vm); DomainInfo.DomainState vps = dm.getInfo().state; if (vps != null && vps != DomainInfo.DomainState.VIR_DOMAIN_SHUTOFF @@ -3992,8 +3994,7 @@ ServerResource { for (int i = 0; i < vms.length; i++) { try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vms[i] - .getBytes())); + dm = conn.domainLookupByName(vms[i]); DomainInfo.DomainState ps = dm.getInfo().state; final State state = convertToState(ps); @@ -4098,8 +4099,7 @@ ServerResource { Domain dm = null; String msg = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String vmDef = dm.getXMLDesc(0); s_logger.debug(vmDef); msg = stopVM(conn, vmName); @@ -4141,8 +4141,7 @@ ServerResource { /* Retry 3 times, to make sure we can get the vm's status */ for (int i = 0; i < 3; i++) { try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); state = dm.getInfo().state; break; } catch (LibvirtException e) { @@ -4178,8 +4177,7 @@ ServerResource { protected String stopVM(Connect conn, String vmName, boolean force) { Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); int persist = dm.isPersistent(); if (force) { if (dm.isActive() == 1) { @@ -4266,8 +4264,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String xmlDesc = dm.getXMLDesc(0); parser.parseDomainXML(xmlDesc); return parser.getVncPort(); @@ -4309,6 +4306,28 @@ ServerResource { } + private String getGuestType(Connect conn, String vmName) { + LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); + Domain dm = null; + try { + dm = conn.domainLookupByName(vmName); + String xmlDesc = dm.getXMLDesc(0); + parser.parseDomainXML(xmlDesc); + return parser.getDescription(); + } catch (LibvirtException e) { + s_logger.trace("Ignoring libvirt error.", e); + return null; + } finally { + try { + if (dm != null) { + dm.free(); + } + } catch (LibvirtException l) { + s_logger.trace("Ignoring libvirt error.", l); + } + } + } + boolean isGuestPVEnabled(String guestOS) { if (guestOS == null) { return false; @@ -4381,15 +4400,14 @@ ServerResource { public Domain getDomain(Connect conn, String vmName) throws LibvirtException { return conn - .domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes())); + .domainLookupByName(vmName); } protected List getInterfaces(Connect conn, String vmName) { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); parser.parseDomainXML(dm.getXMLDesc(0)); return parser.getInterfaces(); @@ -4411,8 +4429,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); parser.parseDomainXML(dm.getXMLDesc(0)); return parser.getDisks(); @@ -4786,13 +4803,13 @@ ServerResource { @Override public void setName(String name) { // TODO Auto-generated method stub - + } @Override public void setConfigParams(Map params) { // TODO Auto-generated method stub - + } @Override @@ -4810,7 +4827,7 @@ ServerResource { @Override public void setRunLevel(int level) { // TODO Auto-generated method stub - + } } diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java index ac4baf122a9..b8645e1664a 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java @@ -35,6 +35,7 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef.diskProtocol; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.nicModel; @@ -64,31 +65,45 @@ public class LibvirtDomainXMLParser { NodeList disks = devices.getElementsByTagName("disk"); for (int i = 0; i < disks.getLength(); i++) { Element disk = (Element) disks.item(i); - String diskFmtType = getAttrValue("driver", "type", disk); - String diskFile = getAttrValue("source", "file", disk); - String diskDev = getAttrValue("source", "dev", disk); - - String diskLabel = getAttrValue("target", "dev", disk); - String bus = getAttrValue("target", "bus", disk); String type = disk.getAttribute("type"); - String device = disk.getAttribute("device"); - DiskDef def = new DiskDef(); - if (type.equalsIgnoreCase("file")) { - if (device.equalsIgnoreCase("disk")) { - DiskDef.diskFmtType fmt = null; - if (diskFmtType != null) { - fmt = DiskDef.diskFmtType.valueOf(diskFmtType - .toUpperCase()); + if (type.equalsIgnoreCase("network")) { + String diskFmtType = getAttrValue("driver", "type", disk); + String diskPath = getAttrValue("source", "name", disk); + String protocol = getAttrValue("source", "protocol", disk); + String authUserName = getAttrValue("auth", "username", disk); + String poolUuid = getAttrValue("secret", "uuid", disk); + String host = getAttrValue("host", "name", disk); + int port = Integer.parseInt(getAttrValue("host", "port", disk)); + String diskLabel = getAttrValue("target", "dev", disk); + String bus = getAttrValue("target", "bus", disk); + def.defNetworkBasedDisk(diskPath, host, port, authUserName, poolUuid, diskLabel, + DiskDef.diskBus.valueOf(bus.toUpperCase()), DiskDef.diskProtocol.valueOf(protocol.toUpperCase())); + } else { + String diskFmtType = getAttrValue("driver", "type", disk); + String diskFile = getAttrValue("source", "file", disk); + String diskDev = getAttrValue("source", "dev", disk); + + String diskLabel = getAttrValue("target", "dev", disk); + String bus = getAttrValue("target", "bus", disk); + String device = disk.getAttribute("device"); + + if (type.equalsIgnoreCase("file")) { + if (device.equalsIgnoreCase("disk")) { + DiskDef.diskFmtType fmt = null; + if (diskFmtType != null) { + fmt = DiskDef.diskFmtType.valueOf(diskFmtType + .toUpperCase()); + } + def.defFileBasedDisk(diskFile, diskLabel, + DiskDef.diskBus.valueOf(bus.toUpperCase()), fmt); + } else if (device.equalsIgnoreCase("cdrom")) { + def.defISODisk(diskFile); } - def.defFileBasedDisk(diskFile, diskLabel, - DiskDef.diskBus.valueOf(bus.toUpperCase()), fmt); - } else if (device.equalsIgnoreCase("cdrom")) { - def.defISODisk(diskFile); + } else if (type.equalsIgnoreCase("block")) { + def.defBlockBasedDisk(diskDev, diskLabel, + DiskDef.diskBus.valueOf(bus.toUpperCase())); } - } else if (type.equalsIgnoreCase("block")) { - def.defBlockBasedDisk(diskDev, diskLabel, - DiskDef.diskBus.valueOf(bus.toUpperCase())); } diskDefs.add(def); } diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 39e36d65c65..0bafd073f68 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -60,6 +60,7 @@ public class LibvirtComputingResourceTest { LibvirtComputingResource lcr = new LibvirtComputingResource(); VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, speed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); LibvirtVMDef vm = lcr.createVMFromSpec(to); vm.setHvsType(_hyperVisorType); @@ -135,6 +136,7 @@ public class LibvirtComputingResourceTest { LibvirtComputingResource lcr = new LibvirtComputingResource(); VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); LibvirtVMDef vm = lcr.createVMFromSpec(to); vm.setHvsType(_hyperVisorType); @@ -181,4 +183,4 @@ public class LibvirtComputingResourceTest { assertEquals(vmStr, vm.toString()); } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index 5698218e4f8..6d9265db2dd 100755 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -16,24 +16,6 @@ // under the License. package com.cloud.hypervisor.xen.discoverer; -import java.net.InetAddress; -import java.net.URI; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import javax.persistence.EntityExistsException; - -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; - import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -65,6 +47,7 @@ import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.xen.resource.CitrixResourceBase; import com.cloud.hypervisor.xen.resource.XcpOssResource; +import com.cloud.hypervisor.xen.resource.XcpServer16Resource; import com.cloud.hypervisor.xen.resource.XcpServerResource; import com.cloud.hypervisor.xen.resource.XenServer56FP1Resource; import com.cloud.hypervisor.xen.resource.XenServer56Resource; @@ -79,9 +62,9 @@ import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; -import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.user.Account; import com.cloud.utils.NumbersUtil; @@ -96,6 +79,22 @@ import com.xensource.xenapi.Pool; import com.xensource.xenapi.Session; import com.xensource.xenapi.Types.SessionAuthenticationFailed; import com.xensource.xenapi.Types.XenAPIException; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import javax.persistence.EntityExistsException; +import java.net.InetAddress; +import java.net.URI; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; @Local(value=Discoverer.class) public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { @@ -314,6 +313,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L details.put("wait", Integer.toString(_wait)); params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString())); params.put(Config.XenMaxNics.toString().toLowerCase(), _configDao.getValue(Config.XenMaxNics.toString())); + params.put(Config.XenHeartBeatInterval.toString().toLowerCase(), _configDao.getValue(Config.XenHeartBeatInterval.toString())); params.put(Config.InstanceName.toString().toLowerCase(), _instance); details.put(Config.InstanceName.toString().toLowerCase(), _instance); try { @@ -418,6 +418,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } else { prodBrand = prodBrand.trim(); } + String prodVersion = record.softwareVersion.get("product_version"); if (prodVersion == null) { prodVersion = record.softwareVersion.get("platform_version").trim(); @@ -425,34 +426,33 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L prodVersion = prodVersion.trim(); } - if(prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) { - return new XcpServerResource("1.1"); + // Xen Cloud Platform group of hypervisors + if (prodBrand.equals("XCP") && ( + prodVersion.equals("1.0.0") + || prodVersion.equals("1.1.0") + || prodVersion.equals("5.6.100") + || prodVersion.startsWith("1.4") + )) { + return new XcpServerResource(); } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) { - return new XcpServerResource("1.6"); - } - - if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) + return new XcpServer16Resource(); + } // Citrix Xenserver group of hypervisors + else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) return new XenServer56Resource(); - - if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) return new XenServer600Resource(); - - if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2")) + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2")) return new XenServer602Resource(); - - if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) return new XenServer610Resource(); - - if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { + else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { String prodVersionTextShort = record.softwareVersion.get("product_version_text_short").trim(); - if("5.6 SP2".equals(prodVersionTextShort)) { + if ("5.6 SP2".equals(prodVersionTextShort)) { return new XenServer56SP2Resource(); - } else if("5.6 FP1".equals(prodVersionTextShort)) { + } else if ("5.6 FP1".equals(prodVersionTextShort)) { return new XenServer56FP1Resource(); } - } - - if (prodBrand.equals("XCP_Kronos")) { + } else if (prodBrand.equals("XCP_Kronos")) { return new XcpOssResource(); } @@ -584,9 +584,11 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L String prodBrand = details.get("product_brand").trim(); String prodVersion = details.get("product_version").trim(); - if(prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4") || prodVersion.startsWith("1.6"))) { + if (prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) { resource = XcpServerResource.class.getName(); - } else if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) { + } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) { + resource = XcpServer16Resource.class.getName(); + } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) { resource = XenServer56Resource.class.getName(); } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) { resource = XenServer600Resource.class.getName(); @@ -594,11 +596,11 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L resource = XenServer602Resource.class.getName(); } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) { resource = XenServer610Resource.class.getName(); - } else if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { + } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { String prodVersionTextShort = details.get("product_version_text_short").trim(); - if("5.6 SP2".equals(prodVersionTextShort)) { + if ("5.6 SP2".equals(prodVersionTextShort)) { resource = XenServer56SP2Resource.class.getName(); - } else if("5.6 FP1".equals(prodVersionTextShort)) { + } else if ("5.6 FP1".equals(prodVersionTextShort)) { resource = XenServer56FP1Resource.class.getName(); } } else if (prodBrand.equals("XCP_Kronos")) { diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixHelper.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixHelper.java index 34b8f2981e2..0f71c7ba9ad 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixHelper.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixHelper.java @@ -16,11 +16,11 @@ // under the License. package com.cloud.hypervisor.xen.resource; +import org.apache.log4j.Logger; + import java.util.ArrayList; import java.util.HashMap; -import org.apache.log4j.Logger; - /** * Reduce bloat inside CitrixResourceBase * diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index ac5056e3411..3a4453c3dd9 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -387,6 +387,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe long _xs_memory_used = 128 * 1024 * 1024L; // xen hypervisor used 128 M double _xs_virtualization_factor = 63.0/64.0; // 1 - virtualization overhead + //static min values for guests on xen + private static final long mem_128m = 134217728L; + protected boolean _canBridgeFirewall = false; protected boolean _isOvs = false; protected List _tmpDom0Vif = new ArrayList(); @@ -709,6 +712,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Connection conn = getConnection(); Set vms = VM.getByNameLabel(conn, vmName); Host host = Host.getByUuid(conn, _host.uuid); + + // If DMC is not enable then don't execute this command. + if (!isDmcEnabled(conn, host)) { + String msg = "Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.uuid + " ,check your license and hypervisor version."; + s_logger.info(msg); + return new ScaleVmAnswer(cmd, false, msg); + } // stop vm which is running on this host or is in halted state Iterator iter = vms.iterator(); while ( iter.hasNext() ) { @@ -1272,8 +1282,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } Set templates = VM.getByNameLabel(conn, guestOsTypeName); assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); + if (!templates.iterator().hasNext()) { + throw new CloudRuntimeException("No matching OS type found for starting a [" + vmSpec.getOs() + + "] VM on host " + host.getHostname(conn)); + } VM template = templates.iterator().next(); - VM vm = template.createClone(conn, vmSpec.getName()); VM.Record vmr = vm.getRecord(conn); if (s_logger.isDebugEnabled()) { @@ -3572,8 +3585,29 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } + /** + * WARN: static-min <= dynamic-min <= dynamic-max <= static-max + * @see XcpServerResource#setMemory(com.xensource.xenapi.Connection, com.xensource.xenapi.VM, long, long) + * @param conn + * @param vm + * @param minMemsize + * @param maxMemsize + * @throws XmlRpcException + * @throws XenAPIException + */ protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { - vm.setMemoryLimits(conn, maxMemsize, maxMemsize, minMemsize, maxMemsize); + vm.setMemoryLimits(conn, mem_128m, maxMemsize, minMemsize, maxMemsize); + } + + /** + * When Dynamic Memory Control (DMC) is enabled - + * xen allows scaling the guest memory while the guest is running + * + * By default this is disallowed, override the specific xen resource + * if this is enabled + */ + protected boolean isDmcEnabled(Connection conn, Host host) throws XenAPIException, XmlRpcException { + return false; } protected void waitForTask(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException { @@ -4368,7 +4402,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe * @throws XenAPIException * @throws XmlRpcException * - * @see enableVlanNetwork + * @see CitrixResourceBase#enableVlanNetwork */ protected XsLocalNetwork getNetworkByName(Connection conn, String name) throws XenAPIException, XmlRpcException { Set networks = Network.getByNameLabel(conn, name); diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServer16Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServer16Resource.java new file mode 100644 index 00000000000..8cb7997305f --- /dev/null +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServer16Resource.java @@ -0,0 +1,32 @@ +/* + * 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.hypervisor.xen.resource; + +public class XcpServer16Resource extends XcpServerResource { + + public XcpServer16Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXcp160GuestOsType(stdType); + } +} diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServerResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServerResource.java index 6baf6a09e3f..67e37d52a4a 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServerResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpServerResource.java @@ -16,15 +16,6 @@ // under the License. package com.cloud.hypervisor.xen.resource; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import javax.ejb.Local; - -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkUsageAnswer; @@ -33,18 +24,27 @@ import com.cloud.resource.ServerResource; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.xensource.xenapi.Connection; -import com.xensource.xenapi.VM; +import com.xensource.xenapi.Host; import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import javax.ejb.Local; +import java.io.File; +import java.util.ArrayList; +import java.util.List; @Local(value=ServerResource.class) public class XcpServerResource extends CitrixResourceBase { - private final static Logger s_logger = Logger.getLogger(XcpServerResource.class); - private String version; - public XcpServerResource(String version) { + private final static Logger s_logger = Logger.getLogger(XcpServerResource.class); + private static final long mem_32m = 33554432L; + private String version; + + public XcpServerResource() { super(); - this.version = version; } - + @Override public Answer executeRequest(Command cmd) { if (cmd instanceof NetworkUsageCommand) { @@ -53,15 +53,6 @@ public class XcpServerResource extends CitrixResourceBase { return super.executeRequest(cmd); } } - - @Override - protected String getGuestOsType(String stdType, boolean bootFromCD) { - if (version.equalsIgnoreCase("1.6")) { - return CitrixHelper.getXcp160GuestOsType(stdType); - } else { - return CitrixHelper.getXcpGuestOsType(stdType); - } - } @Override protected List getPatchFiles() { @@ -77,19 +68,9 @@ public class XcpServerResource extends CitrixResourceBase { } @Override - protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { - - vm.setMemoryStaticMin(conn, 33554432L); - //vm.setMemoryDynamicMin(conn, 33554432L); - //vm.setMemoryDynamicMax(conn, 33554432L); - vm.setMemoryStaticMax(conn, 33554432L); - - //vm.setMemoryStaticMax(conn, maxMemsize ); - vm.setMemoryDynamicMax(conn, maxMemsize ); - vm.setMemoryDynamicMin(conn, minMemsize ); - //vm.setMemoryStaticMin(conn, maxMemsize ); + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXcpGuestOsType(stdType); } - protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { try { @@ -108,5 +89,70 @@ public class XcpServerResource extends CitrixResourceBase { } } - + /** + XCP provides four memory configuration fields through which + administrators can control this behaviour: + + * static-min + * dynamic-min + * dynamic-max + * static-max + + The fields static-{min,max} act as *hard* lower and upper + bounds for a guest's memory. For a running guest: + * it's not possible to assign the guest more memory than + static-max without first shutting down the guest. + * it's not possible to assign the guest less memory than + static-min without first shutting down the guest. + + The fields dynamic-{min,max} act as *soft* lower and upper + bounds for a guest's memory. It's possible to change these + fields even when a guest is running. + + The dynamic range must lie wholly within the static range. To + put it another way, XCP at all times ensures that: + + static-min <= dynamic-min <= dynamic-max <= static-max + + At all times, XCP will attempt to keep a guest's memory usage + between dynamic-min and dynamic-max. + + If dynamic-min = dynamic-max, then XCP will attempt to keep + a guest's memory allocation at a constant size. + + If dynamic-min < dynamic-max, then XCP will attempt to give + the guest as much memory as possible, while keeping the guest + within dynamic-min and dynamic-max. + + If there is enough memory on a given host to give all resident + guests dynamic-max, then XCP will attempt do so. + + If there is not enough memory to give all guests dynamic-max, + then XCP will ask each of the guests (on that host) to use + an amount of memory that is the same *proportional* distance + between dynamic-min and dynamic-max. + + XCP will refuse to start guests if starting those guests would + cause the sum of all the dynamic-min values to exceed the total + host memory (taking into account various memory overheads). + + cf: http://wiki.xen.org/wiki/XCP_FAQ_Dynamic_Memory_Control + */ + @Override + protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + //setMemoryLimits(staticMin, staticMax, dynamicMin, dynamicMax) + if (s_logger.isDebugEnabled()) { + s_logger.debug("Memory Limits for VM [" + vm.getNameLabel(conn) + + "[staticMin:" + mem_32m + ", staticMax:" + maxMemsize + + ", dynamicMin: " + minMemsize + ", dynamicMax:" + maxMemsize+"]]"); + } + vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); + } + + @Override + protected boolean isDmcEnabled(Connection conn, Host host) { + //Dynamic Memory Control (DMC) is a technology provided by Xen Cloud Platform (XCP), starting from the 0.5 release + //For the supported XCPs dmc is default enabled, XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; + return true; + } } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java index d2b96e42f2c..724c21bc4a2 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java @@ -11,12 +11,13 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.hypervisor.xen.resource; + import java.io.File; import java.util.ArrayList; import java.util.HashMap; @@ -35,38 +36,37 @@ import com.cloud.agent.api.FenceAnswer; import com.cloud.agent.api.FenceCommand; import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.resource.ServerResource; import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Console; import com.xensource.xenapi.Host; import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; -import com.xensource.xenapi.Types.XenAPIException; @Local(value=ServerResource.class) public class XenServer56FP1Resource extends XenServer56Resource { + private static final long mem_128m = 134217728L; private static final Logger s_logger = Logger.getLogger(XenServer56FP1Resource.class); - + public XenServer56FP1Resource() { super(); } - + @Override protected String getGuestOsType(String stdType, boolean bootFromCD) { return CitrixHelper.getXenServer56FP1GuestOsType(stdType, bootFromCD); } - + @Override - protected List getPatchFiles() { + protected List getPatchFiles() { List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; + String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; String patchfilePath = Script.findScript("" , patch); if ( patchfilePath == null ) { throw new CloudRuntimeException("Unable to find patch file " + patch); @@ -131,41 +131,46 @@ public class XenServer56FP1Resource extends XenServer56Resource { assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); VM template = templates.iterator().next(); - VM.Record record = template.getRecord(conn); - record.affinity = host; - record.otherConfig.remove("disks"); - record.otherConfig.remove("default_template"); - record.otherConfig.remove("mac_seed"); - record.isATemplate = false; - record.nameLabel = vmSpec.getName(); - record.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; - record.actionsAfterShutdown = Types.OnNormalExit.DESTROY; - record.memoryDynamicMax = vmSpec.getMaxRam(); - record.memoryDynamicMin = vmSpec.getMinRam(); - Map hostParams = new HashMap(); - hostParams = host.getLicenseParams(conn); - if (hostParams.get("restrict_dmc").equalsIgnoreCase("false")) { - record.memoryStaticMax = 8589934592L; //8GB - record.memoryStaticMin = 134217728L; //128MB + VM.Record vmr = template.getRecord(conn); + vmr.affinity = host; + vmr.otherConfig.remove("disks"); + vmr.otherConfig.remove("default_template"); + vmr.otherConfig.remove("mac_seed"); + vmr.isATemplate = false; + vmr.nameLabel = vmSpec.getName(); + vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; + vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY; + + if (isDmcEnabled(conn, host)) { + //scaling is allowed + vmr.memoryStaticMin = mem_128m; //128MB + //TODO: Remove hardcoded 8GB and assign proportionate to ServiceOffering and mem overcommit ratio + vmr.memoryStaticMax = 8589934592L; //8GB + vmr.memoryDynamicMin = vmSpec.getMinRam(); + vmr.memoryDynamicMax = vmSpec.getMaxRam(); } else { - s_logger.warn("Host "+ _host.uuid + " does not support Dynamic Memory Control, so we cannot scale up the vm"); - record.memoryStaticMax = vmSpec.getMaxRam(); - record.memoryStaticMin = vmSpec.getMinRam(); + //scaling disallowed, set static memory target + if (s_logger.isDebugEnabled()) { + s_logger.warn("Host "+ host.getHostname(conn) +" does not support dynamic scaling"); + } + vmr.memoryStaticMin = vmSpec.getMinRam(); + vmr.memoryStaticMax = vmSpec.getMaxRam(); + vmr.memoryDynamicMin = vmSpec.getMinRam(); + vmr.memoryDynamicMax = vmSpec.getMaxRam(); } if (guestOsTypeName.toLowerCase().contains("windows")) { - record.VCPUsMax = (long) vmSpec.getCpus(); + vmr.VCPUsMax = (long) vmSpec.getCpus(); } else { - record.VCPUsMax = 32L; + vmr.VCPUsMax = 32L; } - record.VCPUsAtStartup = (long) vmSpec.getCpus(); - record.consoles.clear(); + vmr.VCPUsAtStartup = (long) vmSpec.getCpus(); + vmr.consoles.clear(); - VM vm = VM.create(conn, record); - VM.Record vmr = vm.getRecord(conn); + VM vm = VM.create(conn, vmr); if (s_logger.isDebugEnabled()) { - s_logger.debug("Created VM " + vmr.uuid + " for " + vmSpec.getName()); + s_logger.debug("Created VM " + vm.getUuid(conn) + " for " + vmSpec.getName()); } Map vcpuParams = new HashMap(); @@ -236,4 +241,20 @@ public class XenServer56FP1Resource extends XenServer56Resource { return vm; } + /** + * When Dynamic Memory Control (DMC) is enabled - + * xen allows scaling the guest memory while the guest is running + * + * This is determined by the 'restrict_dmc' option on the host. + * When false, scaling is allowed hence DMC is enabled + */ + @Override + protected boolean isDmcEnabled(Connection conn, Host host) throws XenAPIException, XmlRpcException { + Map hostParams = new HashMap(); + hostParams = host.getLicenseParams(conn); + + Boolean isDmcEnabled = hostParams.get("restrict_dmc").equalsIgnoreCase("false"); + + return isDmcEnabled; + } } diff --git a/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java index 49c61fa3b83..c796b691d8d 100644 --- a/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java +++ b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java @@ -53,6 +53,7 @@ import com.cloud.agent.api.to.VolumeTO; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.StoragePool; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; @@ -76,7 +77,12 @@ public class XenServerStorageMotionStrategy implements DataMotionStrategy { @Override public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { - return true; + boolean canHandle = false; + if (srcHost.getHypervisorType() == HypervisorType.XenServer && + destHost.getHypervisorType() == HypervisorType.XenServer) { + canHandle = true; + } + return canHandle; } @Override diff --git a/plugins/hypervisors/xen/test/com/cloud/hypervisor/xen/resource/CitrixResourceBaseTest.java b/plugins/hypervisors/xen/test/com/cloud/hypervisor/xen/resource/CitrixResourceBaseTest.java index 877e3bc5120..3328d4be50c 100644 --- a/plugins/hypervisors/xen/test/com/cloud/hypervisor/xen/resource/CitrixResourceBaseTest.java +++ b/plugins/hypervisors/xen/test/com/cloud/hypervisor/xen/resource/CitrixResourceBaseTest.java @@ -58,7 +58,10 @@ public class CitrixResourceBaseTest { super.scaleVM(conn, vm, vmSpec, host); } - + @Override + protected boolean isDmcEnabled(Connection conn, Host host) throws Types.XenAPIException, XmlRpcException { + return true; + } }; @Mock XsHost _host; @Mock Host host; diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java index 28e2535ca91..be4814ae6be 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java @@ -74,16 +74,16 @@ public interface CiscoVnmcConnection { String ipAddress) throws ExecutionException; public boolean createTenantVDCDNatRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String publicIp) throws ExecutionException; public boolean deleteTenantVDCDNatRule(String tenantName, - String identifier, String policyIdentifier) + long ruleId, String policyIdentifier) throws ExecutionException; public boolean createTenantVDCAclRuleForDNat(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String ipAddress) throws ExecutionException; @@ -104,17 +104,17 @@ public interface CiscoVnmcConnection { String ipAddress) throws ExecutionException; public boolean createTenantVDCPFRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String publicIp, String startPort, String endPort) throws ExecutionException; public boolean deleteTenantVDCPFRule(String tenantName, - String identifier, String policyIdentifier) + long ruleId, String policyIdentifier) throws ExecutionException; public boolean createTenantVDCAclRuleForPF(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String ipAddress, String startPort, String endPort) throws ExecutionException; @@ -138,29 +138,29 @@ public interface CiscoVnmcConnection { throws ExecutionException; public boolean createTenantVDCIngressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp, String destStartPort, String destEndPort) throws ExecutionException; public boolean createTenantVDCIngressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp) throws ExecutionException; public boolean createTenantVDCEgressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp, String destStartPort, String destEndPort) throws ExecutionException; public boolean createTenantVDCEgressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp) throws ExecutionException; public boolean deleteTenantVDCAclRule(String tenantName, - String identifier, String policyIdentifier) throws ExecutionException; + long ruleId, String policyIdentifier) throws ExecutionException; public boolean createTenantVDCAclPolicy(String tenantName, String identifier) throws ExecutionException; diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java index a9e8cf633f9..72ecc67cad6 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java @@ -490,12 +490,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "srcendip", endSourceIp); xml = replaceXmlValue(xml, "ippoolname", getNameForSourceNatIpPool(tenantName)); - List rules = listChildren(getDnForSourceNatPolicy(tenantName)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); @@ -671,12 +667,13 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCIngressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp, String destStartPort, String destEndPort) throws ExecutionException { String xml = VnmcXml.CREATE_INGRESS_ACL_RULE.getXml(); String service = VnmcXml.CREATE_INGRESS_ACL_RULE.getService(); + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); @@ -688,12 +685,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "deststartport", destStartPort); xml = replaceXmlValue(xml, "destendport", destEndPort); - List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); @@ -701,11 +694,12 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCIngressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp) throws ExecutionException { String xml = VnmcXml.CREATE_GENERIC_INGRESS_ACL_RULE.getXml(); String service = VnmcXml.CREATE_GENERIC_INGRESS_ACL_RULE.getService(); + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); @@ -715,12 +709,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "sourcestartip", sourceStartIp); xml = replaceXmlValue(xml, "sourceendip", sourceEndIp); - List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); @@ -728,12 +718,13 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCEgressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp, String destStartPort, String destEndPort) throws ExecutionException { String xml = VnmcXml.CREATE_EGRESS_ACL_RULE.getXml(); String service = VnmcXml.CREATE_EGRESS_ACL_RULE.getService(); + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); @@ -745,12 +736,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "deststartport", destStartPort); xml = replaceXmlValue(xml, "destendport", destEndPort); - List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); @@ -758,7 +745,7 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCEgressAclRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String sourceStartIp, String sourceEndIp) throws ExecutionException { String xml = VnmcXml.CREATE_GENERIC_EGRESS_ACL_RULE.getXml(); String service = VnmcXml.CREATE_GENERIC_EGRESS_ACL_RULE.getService(); @@ -768,6 +755,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { } else { // specific protocol xml = replaceXmlValue(xml, "protocolvalue", protocol); } + + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); @@ -776,19 +765,16 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "sourcestartip", sourceStartIp); xml = replaceXmlValue(xml, "sourceendip", sourceEndIp); - List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); } @Override - public boolean deleteTenantVDCAclRule(String tenantName, String identifier, String policyIdentifier) throws ExecutionException { + public boolean deleteTenantVDCAclRule(String tenantName, long ruleId, String policyIdentifier) throws ExecutionException { + String identifier = Long.toString(ruleId); return deleteTenantVDCRule( getDnForAclRule(tenantName, identifier, policyIdentifier), getNameForAclRule(tenantName, identifier)); @@ -1001,11 +987,13 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCPFRule(String tenantName, - String identifier, String policyIdentifier, + long ruleId, String policyIdentifier, String protocol, String publicIp, String startPort, String endPort) throws ExecutionException { String xml = VnmcXml.CREATE_PF_RULE.getXml(); String service = VnmcXml.CREATE_PF_RULE.getService(); + + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "natruledn", getDnForPFRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "natrulename", getNameForPFRule(tenantName, identifier)); @@ -1017,20 +1005,16 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "endport", endPort); xml = replaceXmlValue(xml, "protocolvalue", protocol); - List rules = listChildren(getDnForPFPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); } @Override - public boolean deleteTenantVDCPFRule(String tenantName, String identifier, - String policyIdentifier) throws ExecutionException { + public boolean deleteTenantVDCPFRule(String tenantName, long ruleId, String policyIdentifier) throws ExecutionException { + String identifier = Long.toString(ruleId); return deleteTenantVDCRule( getDnForPFRule(tenantName, identifier, policyIdentifier), getNameForPFRule(tenantName, identifier)); @@ -1038,11 +1022,13 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCAclRuleForPF(String tenantName, - String identifier, String policyIdentifier, String protocol, + long ruleId, String policyIdentifier, String protocol, String ipAddress, String startPort, String endPort) throws ExecutionException { String xml = VnmcXml.CREATE_ACL_RULE_FOR_PF.getXml(); String service = VnmcXml.CREATE_ACL_RULE_FOR_PF.getService(); + + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); @@ -1053,12 +1039,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "startport", startPort); xml = replaceXmlValue(xml, "endport", endPort); - List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); @@ -1127,10 +1109,12 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCDNatRule(String tenantName, - String identifier, String policyIdentifier, String publicIp) + long ruleId, String policyIdentifier, String publicIp) throws ExecutionException { String xml = VnmcXml.CREATE_DNAT_RULE.getXml(); String service = VnmcXml.CREATE_DNAT_RULE.getService(); + + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "natruledn", getDnForDNatRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "natrulename", getNameForDNatRule(tenantName, identifier)); @@ -1138,21 +1122,17 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "ippoolname", getNameForDNatIpPool(tenantName, identifier)); xml = replaceXmlValue(xml, "ip", publicIp); - List rules = listChildren(getDnForDNatPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); } @Override - public boolean deleteTenantVDCDNatRule(String tenantName, - String identifier, String policyIdentifier) + public boolean deleteTenantVDCDNatRule(String tenantName, long ruleId, String policyIdentifier) throws ExecutionException { + String identifier = Long.toString(ruleId); return deleteTenantVDCRule( getDnForDNatRule(tenantName, identifier, policyIdentifier), getNameForDNatRule(tenantName, identifier)); @@ -1160,10 +1140,12 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCAclRuleForDNat(String tenantName, - String identifier, String policyIdentifier, String ipAddress) + long ruleId, String policyIdentifier, String ipAddress) throws ExecutionException { String xml = VnmcXml.CREATE_ACL_RULE_FOR_DNAT.getXml(); String service = VnmcXml.CREATE_ACL_RULE_FOR_DNAT.getService(); + + String identifier = Long.toString(ruleId); xml = replaceXmlValue(xml, "cookie", _cookie); xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); @@ -1171,12 +1153,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "actiontype", "permit"); xml = replaceXmlValue(xml, "ip", ipAddress); - List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); - int order = 100; - if (rules != null) { - order += rules.size(); - } - xml = replaceXmlValue(xml, "order", Integer.toString(order)); + long order = 100 + ruleId; + xml = replaceXmlValue(xml, "order", Long.toString(order)); String response = sendRequest(service, xml); return verifySuccess(response); diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java index 29bbbe67a31..fc0c33483ac 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java @@ -174,7 +174,7 @@ public class CiscoVnmcResource implements ServerResource { cmd.setPod(""); cmd.setPrivateIpAddress(_ip); cmd.setStorageIpAddress(""); - cmd.setVersion(""); + cmd.setVersion(CiscoVnmcResource.class.getPackage().getImplementationVersion()); cmd.setGuid(_guid); return new StartupCommand[] { cmd }; } @@ -359,7 +359,7 @@ public class CiscoVnmcResource implements ServerResource { for (FirewallRuleTO rule : publicIpRulesMap.get(publicIp)) { if (rule.revoked()) { - if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + if (!_connection.deleteTenantVDCAclRule(tenant, rule.getId(), policyIdentifier)) { throw new ExecutionException("Failed to delete ACL rule in VNMC for guest network with vlan " + vlanId); } } else { @@ -368,14 +368,14 @@ public class CiscoVnmcResource implements ServerResource { if (!rule.getProtocol().equalsIgnoreCase("icmp") && rule.getSrcPortRange() != null) { if (!_connection.createTenantVDCIngressAclRule(tenant, - Long.toString(rule.getId()), policyIdentifier, + rule.getId(), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { throw new ExecutionException("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); } } else { if (!_connection.createTenantVDCIngressAclRule(tenant, - Long.toString(rule.getId()), policyIdentifier, + rule.getId(), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1])) { throw new ExecutionException("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); } @@ -384,7 +384,7 @@ public class CiscoVnmcResource implements ServerResource { if ((rule.getProtocol().equalsIgnoreCase("tcp") || rule.getProtocol().equalsIgnoreCase("udp")) && rule.getSrcPortRange() != null) { if (!_connection.createTenantVDCEgressAclRule(tenant, - Long.toString(rule.getId()), policyIdentifier, + rule.getId(), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { @@ -392,7 +392,7 @@ public class CiscoVnmcResource implements ServerResource { } } else { if (!_connection.createTenantVDCEgressAclRule(tenant, - Long.toString(rule.getId()), policyIdentifier, + rule.getId(), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1])) { throw new ExecutionException("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); } @@ -472,7 +472,7 @@ public class CiscoVnmcResource implements ServerResource { for (StaticNatRuleTO rule : publicIpRulesMap.get(publicIp)) { if (rule.revoked()) { - if (!_connection.deleteTenantVDCDNatRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + if (!_connection.deleteTenantVDCDNatRule(tenant, rule.getId(), policyIdentifier)) { throw new ExecutionException("Failed to delete DNAT rule in VNMC for guest network with vlan " + vlanId); } } else { @@ -481,7 +481,7 @@ public class CiscoVnmcResource implements ServerResource { } if (!_connection.createTenantVDCDNatRule(tenant, - Long.toString(rule.getId()), policyIdentifier, rule.getSrcIp())) { + rule.getId(), policyIdentifier, rule.getSrcIp())) { throw new ExecutionException("Failed to create DNAT rule in VNMC for guest network with vlan " + vlanId); } } @@ -558,7 +558,7 @@ public class CiscoVnmcResource implements ServerResource { for (PortForwardingRuleTO rule : publicIpRulesMap.get(publicIp)) { if (rule.revoked()) { - if (!_connection.deleteTenantVDCPFRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + if (!_connection.deleteTenantVDCPFRule(tenant, rule.getId(), policyIdentifier)) { throw new ExecutionException("Failed to delete PF rule in VNMC for guest network with vlan " + vlanId); } } else { @@ -571,7 +571,7 @@ public class CiscoVnmcResource implements ServerResource { } if (!_connection.createTenantVDCPFRule(tenant, - Long.toString(rule.getId()), policyIdentifier, + rule.getId(), policyIdentifier, rule.getProtocol().toUpperCase(), rule.getSrcIp(), Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { throw new ExecutionException("Failed to create PF rule in VNMC for guest network with vlan " + vlanId); diff --git a/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java index f1942ea5fe5..b3821d78bd5 100755 --- a/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java +++ b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java @@ -163,13 +163,13 @@ public class CiscoVnmcResourceTest { when(_connection.createTenantVDCAclPolicySet(anyString(), anyBoolean())).thenReturn(true); when(_connection.createTenantVDCAclPolicy(anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclPolicyRef(anyString(), anyString(), anyBoolean())).thenReturn(true); - when(_connection.deleteTenantVDCAclRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCAclRule(anyString(), anyLong(), anyString())).thenReturn(true); when(_connection.createTenantVDCIngressAclRule( - anyString(), anyString(), anyString(), + anyString(), anyLong(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCEgressAclRule( - anyString(), anyString(), anyString(), + anyString(), anyLong(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(true); when(_connection.associateAclPolicySet(anyString())).thenReturn(true); @@ -201,13 +201,13 @@ public class CiscoVnmcResourceTest { when(_connection.createTenantVDCDNatPolicyRef(anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclPolicy(anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclPolicyRef(anyString(), anyString(), anyBoolean())).thenReturn(true); - when(_connection.deleteTenantVDCDNatRule(anyString(), anyString(), anyString())).thenReturn(true); - when(_connection.deleteTenantVDCAclRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCDNatRule(anyString(), anyLong(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCAclRule(anyString(), anyLong(), anyString())).thenReturn(true); when(_connection.createTenantVDCDNatIpPool(anyString(), anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCDNatRule(anyString(), - anyString(), anyString(), anyString())).thenReturn(true); + anyLong(), anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclRuleForDNat(anyString(), - anyString(), anyString(), anyString())).thenReturn(true); + anyLong(), anyString(), anyString())).thenReturn(true); when(_connection.associateAclPolicySet(anyString())).thenReturn(true); Answer answer = _resource.executeRequest(cmd); @@ -237,15 +237,15 @@ public class CiscoVnmcResourceTest { when(_connection.createTenantVDCPFPolicyRef(anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclPolicy(anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclPolicyRef(anyString(), anyString(), anyBoolean())).thenReturn(true); - when(_connection.deleteTenantVDCPFRule(anyString(), anyString(), anyString())).thenReturn(true); - when(_connection.deleteTenantVDCAclRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCPFRule(anyString(), anyLong(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCAclRule(anyString(), anyLong(), anyString())).thenReturn(true); when(_connection.createTenantVDCPFIpPool(anyString(), anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCPFPortPool(anyString(), anyString(), anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCPFRule(anyString(), - anyString(), anyString(), anyString(), + anyLong(), anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(true); when(_connection.createTenantVDCAclRuleForPF(anyString(), - anyString(), anyString(), anyString(), + anyLong(), anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(true); when(_connection.associateAclPolicySet(anyString())).thenReturn(true); diff --git a/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java b/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java index baf99b908d4..a7d96b0c310 100644 --- a/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java +++ b/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java @@ -17,7 +17,8 @@ * under the License. */ -import com.cloud.network.element.MidoNetElement; +package com.cloud.network.element; + import com.cloud.user.AccountVO; import com.cloud.user.dao.AccountDao; import junit.framework.TestCase; diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java b/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java index bd2588054d2..1348788da25 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java +++ b/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java @@ -60,6 +60,15 @@ public class NetscalerLoadBalancerResponse extends BaseResponse { @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the management IP address of the external load balancer") private String ipAddress; + @SerializedName(ApiConstants.GSLB_PROVIDER) @Param(description="true if NetScaler device is provisioned to be a GSLB service provider") + private Boolean isGslbProvider; + + @SerializedName(ApiConstants.GSLB_PROVIDER_PUBLIC_IP) @Param(description="public IP of the NetScaler representing GSLB site") + private String gslbSitePublicIp; + + @SerializedName(ApiConstants.GSLB_PROVIDER_PRIVATE_IP) @Param(description="private IP of the NetScaler representing GSLB site") + private String gslbSitePrivateIp; + @SerializedName(ApiConstants.POD_IDS) @Param(description="Used when NetScaler device is provider of EIP service." + " This parameter represents the list of pod's, for which there exists a policy based route on datacenter L3 router to " + "route pod's subnet IP to a NetScaler device.") @@ -108,4 +117,16 @@ public class NetscalerLoadBalancerResponse extends BaseResponse { public void setAssociatedPods(List pods) { this.podIds = pods; } + + public void setGslbProvider(boolean isGslbProvider) { + this.isGslbProvider = isGslbProvider; + } + + public void setGslbSitePublicIp(String publicIP) { + this.gslbSitePublicIp = publicIP; + } + + public void setGslbSitePrivateIp(String privateIp) { + this.gslbSitePrivateIp = privateIp; + } } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index 850962d05ee..13a6900f2a6 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -589,6 +589,10 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl response.setDeviceState(lbDeviceVO.getState().name()); response.setObjectName("netscalerloadbalancer"); + response.setGslbProvider(lbDeviceVO.getGslbProvider()); + response.setGslbSitePublicIp(lbDeviceVO.getGslbSitePublicIP()); + response.setGslbSitePrivateIp(lbDeviceVO.getGslbSitePrivateIP()); + List associatedPods = new ArrayList(); List currentPodVOs = _netscalerPodDao.listByNetScalerDeviceId(lbDeviceVO.getId()); if (currentPodVOs != null && currentPodVOs.size() > 0) { diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java new file mode 100644 index 00000000000..20afea9710b --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java @@ -0,0 +1,105 @@ +// 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.network.nicira; + +public class DestinationNatRule extends NatRule { + private String toDestinationIpAddress; + private Integer toDestinationPort; + + public DestinationNatRule() { + setType("DestinationNatRule"); + } + + public String getToDestinationIpAddress() { + return toDestinationIpAddress; + } + + + public void setToDestinationIpAddress(String toDestinationIpAddress) { + this.toDestinationIpAddress = toDestinationIpAddress; + } + + + public Integer getToDestinationPort() { + return toDestinationPort; + } + + + public void setToDestinationPort(Integer toDestinationPort) { + this.toDestinationPort = toDestinationPort; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime + * result + + ((toDestinationIpAddress == null) ? 0 + : toDestinationIpAddress.hashCode()); + result = prime + * result + + ((toDestinationPort == null) ? 0 : toDestinationPort + .hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DestinationNatRule other = (DestinationNatRule) obj; + if (toDestinationIpAddress == null) { + if (other.toDestinationIpAddress != null) + return false; + } else if (!toDestinationIpAddress.equals(other.toDestinationIpAddress)) + return false; + if (toDestinationPort == null) { + if (other.toDestinationPort != null) + return false; + } else if (!toDestinationPort.equals(other.toDestinationPort)) + return false; + return true; + } + + @Override + public boolean equalsIgnoreUuid(Object obj) { + if (this == obj) + return true; + if (!super.equalsIgnoreUuid(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DestinationNatRule other = (DestinationNatRule) obj; + if (toDestinationIpAddress == null) { + if (other.toDestinationIpAddress != null) + return false; + } else if (!toDestinationIpAddress.equals(other.toDestinationIpAddress)) + return false; + if (toDestinationPort == null) { + if (other.toDestinationPort != null) + return false; + } else if (!toDestinationPort.equals(other.toDestinationPort)) + return false; + return true; + } + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java index 0c4e677536c..f7777822a06 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java @@ -22,15 +22,9 @@ package com.cloud.network.nicira; public class Match { private Integer protocol; private String source_ip_addresses; - private Boolean source_ip_addresses_not; private String destination_ip_addresses; - private Boolean destination_ip_addresses_not; - private Integer source_port_min; - private Integer source_port_max; - private Boolean source_port_not; - private Integer destination_port_min; - private Integer destination_port_max; - private Boolean destination_port_not; + private Integer source_port; + private Integer destination_port; private String ethertype = "IPv4"; public Integer getProtocol() { @@ -41,54 +35,22 @@ public class Match { this.protocol = protocol; } - public Integer getSourcePortMin() { - return source_port_min; + public Integer getSourcePort() { + return source_port; } - public void setSourcePortMin(Integer source_port_min) { - this.source_port_min = source_port_min; + public void setSourcePort(Integer source_port) { + this.source_port = source_port; + } + + public Integer getDestinationPort() { + return destination_port; } - public Integer getSourcePortMax() { - return source_port_max; + public void setDestinationPort(Integer destination_port) { + this.destination_port = destination_port; } - - public void setSourcePortMax(Integer source_port_max) { - this.source_port_max = source_port_max; - } - - public Boolean isSourcePortNot() { - return source_port_not; - } - - public void setSourcePortNot(Boolean source_port_not) { - this.source_port_not = source_port_not; - } - - public Integer getDestinationPortMin() { - return destination_port_min; - } - - public void setDestinationPortMin(Integer destination_port_min) { - this.destination_port_min = destination_port_min; - } - - public Integer getDestinationPortMax() { - return destination_port_max; - } - - public void setDestinationPortMax(Integer destination_port_max) { - this.destination_port_max = destination_port_max; - } - - public Boolean isDestinationPortNot() { - return destination_port_not; - } - - public void setDestinationPortNot(Boolean destination_port_not) { - this.destination_port_not = destination_port_not; - } - + public String getEthertype() { return ethertype; } @@ -105,14 +67,6 @@ public class Match { this.source_ip_addresses = source_ip_addresses; } - public boolean isSourceIpAddressesNot() { - return source_ip_addresses_not; - } - - public void setSourceIpAddresses_not(boolean source_ip_addresses_not) { - this.source_ip_addresses_not = source_ip_addresses_not; - } - public String getDestinationIpAddresses() { return destination_ip_addresses; } @@ -121,14 +75,6 @@ public class Match { this.destination_ip_addresses = destination_ip_addresses; } - public Boolean isDestinationIpAddressesNot() { - return destination_ip_addresses_not; - } - - public void setDestinationIpAddressesNot(Boolean destination_ip_addresses_not) { - this.destination_ip_addresses_not = destination_ip_addresses_not; - } - @Override public int hashCode() { final int prime = 31; @@ -139,19 +85,7 @@ public class Match { : destination_ip_addresses.hashCode()); result = prime * result - + ((destination_ip_addresses_not == null) ? 0 - : destination_ip_addresses_not.hashCode()); - result = prime - * result - + ((destination_port_max == null) ? 0 : destination_port_max - .hashCode()); - result = prime - * result - + ((destination_port_min == null) ? 0 : destination_port_min - .hashCode()); - result = prime - * result - + ((destination_port_not == null) ? 0 : destination_port_not + + ((destination_port == null) ? 0 : destination_port .hashCode()); result = prime * result + ((ethertype == null) ? 0 : ethertype.hashCode()); @@ -161,16 +95,8 @@ public class Match { * result + ((source_ip_addresses == null) ? 0 : source_ip_addresses .hashCode()); - result = prime - * result - + ((source_ip_addresses_not == null) ? 0 - : source_ip_addresses_not.hashCode()); result = prime * result - + ((source_port_max == null) ? 0 : source_port_max.hashCode()); - result = prime * result - + ((source_port_min == null) ? 0 : source_port_min.hashCode()); - result = prime * result - + ((source_port_not == null) ? 0 : source_port_not.hashCode()); + + ((source_port == null) ? 0 : source_port.hashCode()); return result; } @@ -189,26 +115,10 @@ public class Match { } else if (!destination_ip_addresses .equals(other.destination_ip_addresses)) return false; - if (destination_ip_addresses_not == null) { - if (other.destination_ip_addresses_not != null) + if (destination_port == null) { + if (other.destination_port != null) return false; - } else if (!destination_ip_addresses_not - .equals(other.destination_ip_addresses_not)) - return false; - if (destination_port_max == null) { - if (other.destination_port_max != null) - return false; - } else if (!destination_port_max.equals(other.destination_port_max)) - return false; - if (destination_port_min == null) { - if (other.destination_port_min != null) - return false; - } else if (!destination_port_min.equals(other.destination_port_min)) - return false; - if (destination_port_not == null) { - if (other.destination_port_not != null) - return false; - } else if (!destination_port_not.equals(other.destination_port_not)) + } else if (!destination_port.equals(other.destination_port)) return false; if (ethertype == null) { if (other.ethertype != null) @@ -225,26 +135,10 @@ public class Match { return false; } else if (!source_ip_addresses.equals(other.source_ip_addresses)) return false; - if (source_ip_addresses_not == null) { - if (other.source_ip_addresses_not != null) + if (source_port == null) { + if (other.source_port != null) return false; - } else if (!source_ip_addresses_not - .equals(other.source_ip_addresses_not)) - return false; - if (source_port_max == null) { - if (other.source_port_max != null) - return false; - } else if (!source_port_max.equals(other.source_port_max)) - return false; - if (source_port_min == null) { - if (other.source_port_min != null) - return false; - } else if (!source_port_min.equals(other.source_port_min)) - return false; - if (source_port_not == null) { - if (other.source_port_not != null) - return false; - } else if (!source_port_not.equals(other.source_port_not)) + } else if (!source_port.equals(other.source_port)) return false; return true; } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java index b66ffa89b77..93de51e45ac 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java @@ -16,267 +16,114 @@ // under the License. package com.cloud.network.nicira; +import java.util.UUID; + /** * */ -public class NatRule { - protected Match match; - protected String to_source_ip_address_min; - protected String to_source_ip_address_max; - protected Integer to_source_port_min; - protected Integer to_source_port_max; - protected String uuid; - protected String type; - protected String to_destination_ip_address_min; - protected String to_destination_ip_address_max; - protected Integer to_destination_port; - - public NatRule() {} - - public Match getMatch() { - return match; - } - - public void setMatch(Match match) { - this.match = match; - } - - public String getToSourceIpAddressMin() { - return to_source_ip_address_min; - } - - public void setToSourceIpAddressMin(String to_source_ip_address_min) { - this.to_source_ip_address_min = to_source_ip_address_min; - } - - public String getToSourceIpAddressMax() { - return to_source_ip_address_max; - } - - public void setToSourceIpAddressMax(String to_source_ip_address_max) { - this.to_source_ip_address_max = to_source_ip_address_max; - } - - public Integer getToSourcePortMin() { - return to_source_port_min; - } - - public void setToSourcePortMin(Integer to_source_port_min) { - this.to_source_port_min = to_source_port_min; - } - - public Integer getToSourcePortMax() { - return to_source_port_max; - } - - public void setToSourcePortMax(Integer to_source_port_max) { - this.to_source_port_max = to_source_port_max; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getToDestinationIpAddressMin() { - return to_destination_ip_address_min; - } - - public void setToDestinationIpAddressMin( - String to_destination_ip_address_min) { - this.to_destination_ip_address_min = to_destination_ip_address_min; - } - - public String getToDestinationIpAddressMax() { - return to_destination_ip_address_max; - } - - public void setToDestinationIpAddressMax( - String to_destination_ip_address_max) { - this.to_destination_ip_address_max = to_destination_ip_address_max; - } - - public Integer getToDestinationPort() { - return to_destination_port; - } - - public void setToDestinationPort(Integer to_destination_port) { - this.to_destination_port = to_destination_port; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } +public abstract class NatRule { + protected Match match; + protected UUID uuid; + protected String type; + protected int order; - @Override - public int hashCode() { - final int prime = 42; - int result = 1; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime - * result - + ((to_destination_ip_address_max == null) ? 0 - : to_destination_ip_address_max.hashCode()); - result = prime - * result - + ((to_destination_ip_address_min == null) ? 0 - : to_destination_ip_address_min.hashCode()); - result = prime - * result - + ((to_destination_port == null) ? 0 : to_destination_port - .hashCode()); - result = prime - * result - + ((to_source_ip_address_max == null) ? 0 - : to_source_ip_address_max.hashCode()); - result = prime - * result - + ((to_source_ip_address_min == null) ? 0 - : to_source_ip_address_min.hashCode()); - result = prime - * result - + ((to_source_port_max == null) ? 0 : to_source_port_max - .hashCode()); - result = prime - * result - + ((to_source_port_min == null) ? 0 : to_source_port_min - .hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); - return result; - } + public NatRule() { + } + + public Match getMatch() { + return match; + } + + public void setMatch(Match match) { + this.match = match; + } + + public UUID getUuid() { + return uuid; + } + + public void setUuid(UUID uuid) { + this.uuid = uuid; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((match == null) ? 0 : match.hashCode()); + result = prime * result + order; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NatRule other = (NatRule) obj; + if (match == null) { + if (other.match != null) + return false; + } else if (!match.equals(other.match)) + return false; + if (order != other.order) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (uuid == null) { + if (other.uuid != null) + return false; + } else if (!uuid.equals(other.uuid)) + return false; + return true; + } + + public boolean equalsIgnoreUuid(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NatRule other = (NatRule) obj; + if (match == null) { + if (other.match != null) + return false; + } else if (!match.equals(other.match)) + return false; + if (order != other.order) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NatRule other = (NatRule) obj; - if (match == null) { - if (other.match != null) - return false; - } else if (!match.equals(other.match)) - return false; - if (to_destination_ip_address_max == null) { - if (other.to_destination_ip_address_max != null) - return false; - } else if (!to_destination_ip_address_max - .equals(other.to_destination_ip_address_max)) - return false; - if (to_destination_ip_address_min == null) { - if (other.to_destination_ip_address_min != null) - return false; - } else if (!to_destination_ip_address_min - .equals(other.to_destination_ip_address_min)) - return false; - if (to_destination_port == null) { - if (other.to_destination_port != null) - return false; - } else if (!to_destination_port.equals(other.to_destination_port)) - return false; - if (to_source_ip_address_max == null) { - if (other.to_source_ip_address_max != null) - return false; - } else if (!to_source_ip_address_max - .equals(other.to_source_ip_address_max)) - return false; - if (to_source_ip_address_min == null) { - if (other.to_source_ip_address_min != null) - return false; - } else if (!to_source_ip_address_min - .equals(other.to_source_ip_address_min)) - return false; - if (to_source_port_max == null) { - if (other.to_source_port_max != null) - return false; - } else if (!to_source_port_max.equals(other.to_source_port_max)) - return false; - if (to_source_port_min == null) { - if (other.to_source_port_min != null) - return false; - } else if (!to_source_port_min.equals(other.to_source_port_min)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (uuid == null) { - if (other.uuid != null) - return false; - } else if (!uuid.equals(other.uuid)) - return false; - return true; - } - - public boolean equalsIgnoreUuid(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NatRule other = (NatRule) obj; - if (match == null) { - if (other.match != null) - return false; - } else if (!match.equals(other.match)) - return false; - if (to_destination_ip_address_max == null) { - if (other.to_destination_ip_address_max != null) - return false; - } else if (!to_destination_ip_address_max - .equals(other.to_destination_ip_address_max)) - return false; - if (to_destination_ip_address_min == null) { - if (other.to_destination_ip_address_min != null) - return false; - } else if (!to_destination_ip_address_min - .equals(other.to_destination_ip_address_min)) - return false; - if (to_destination_port == null) { - if (other.to_destination_port != null) - return false; - } else if (!to_destination_port.equals(other.to_destination_port)) - return false; - if (to_source_ip_address_max == null) { - if (other.to_source_ip_address_max != null) - return false; - } else if (!to_source_ip_address_max - .equals(other.to_source_ip_address_max)) - return false; - if (to_source_ip_address_min == null) { - if (other.to_source_ip_address_min != null) - return false; - } else if (!to_source_ip_address_min - .equals(other.to_source_ip_address_min)) - return false; - if (to_source_port_max == null) { - if (other.to_source_port_max != null) - return false; - } else if (!to_source_port_max.equals(other.to_source_port_max)) - return false; - if (to_source_port_min == null) { - if (other.to_source_port_min != null) - return false; - } else if (!to_source_port_min.equals(other.to_source_port_min)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - return true; - } - } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java index 039c174be2d..12fa6c0b67c 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java @@ -34,6 +34,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.UUID; + import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; @@ -41,7 +43,6 @@ import javax.net.ssl.X509TrustManager; import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpMethodBase; @@ -59,7 +60,15 @@ import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; import org.apache.log4j.Logger; + +import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; public class NiciraNvpApi { @@ -73,6 +82,9 @@ public class NiciraNvpApi { private String _adminpass; private HttpClient _client; + private String _nvpversion; + + private Gson _gson; /* This factory method is protected so we can extend this * in the unittests. @@ -118,6 +130,11 @@ public class NiciraNvpApi { s_logger.warn("Failed to register the TrustingProtocolSocketFactory, falling back to default SSLSocketFactory", e); } + _gson = new GsonBuilder() + .registerTypeAdapter(NatRule.class, new NatRuleAdapter()) + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + } public void setControllerAddress(String address) { @@ -170,6 +187,12 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Nicira NVP API login failed " + pm.getStatusText()); } + // Extract the version for later use + if (pm.getResponseHeader("Server") != null) { + _nvpversion = pm.getResponseHeader("Server").getValue(); + s_logger.debug("NVP Controller reports version " + _nvpversion); + } + // Success; the cookie required for login is kept in _client } @@ -290,8 +313,8 @@ public class NiciraNvpApi { executeUpdateObject(natRule, uri, Collections.emptyMap()); } - public void deleteLogicalRouterNatRule(String logicalRouterUuid, String natRuleUuid) throws NiciraNvpApiException { - String uri = "/ws.v1/lrouter/" + logicalRouterUuid + "/nat/" + natRuleUuid; + public void deleteLogicalRouterNatRule(String logicalRouterUuid, UUID natRuleUuid) throws NiciraNvpApiException { + String uri = "/ws.v1/lrouter/" + logicalRouterUuid + "/nat/" + natRuleUuid.toString(); executeDeleteObject(uri); } @@ -342,13 +365,11 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } - Gson gson = new Gson(); - PutMethod pm = (PutMethod) createMethod("put", uri); pm.setRequestHeader("Content-Type", "application/json"); try { pm.setRequestEntity(new StringRequestEntity( - gson.toJson(newObject),"application/json", null)); + _gson.toJson(newObject),"application/json", null)); } catch (UnsupportedEncodingException e) { throw new NiciraNvpApiException("Failed to encode json request body", e); } @@ -371,13 +392,11 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } - Gson gson = new Gson(); - PostMethod pm = (PostMethod) createMethod("post", uri); pm.setRequestHeader("Content-Type", "application/json"); try { pm.setRequestEntity(new StringRequestEntity( - gson.toJson(newObject),"application/json", null)); + _gson.toJson(newObject),"application/json", null)); } catch (UnsupportedEncodingException e) { throw new NiciraNvpApiException("Failed to encode json request body", e); } @@ -393,7 +412,7 @@ public class NiciraNvpApi { T result; try { - result = (T)gson.fromJson(pm.getResponseBodyAsString(), TypeToken.get(newObject.getClass()).getType()); + result = (T)_gson.fromJson(pm.getResponseBodyAsString(), TypeToken.get(newObject.getClass()).getType()); } catch (IOException e) { throw new NiciraNvpApiException("Failed to decode json response body", e); } finally { @@ -450,10 +469,9 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Failed to retrieve object : " + errorMessage); } - Gson gson = new Gson(); T returnValue; try { - returnValue = (T)gson.fromJson(gm.getResponseBodyAsString(), returnObjectType); + returnValue = (T)_gson.fromJson(gm.getResponseBodyAsString(), returnObjectType); } catch (IOException e) { s_logger.error("IOException while retrieving response body",e); throw new NiciraNvpApiException(e); @@ -577,5 +595,28 @@ public class NiciraNvpApi { } - + public static class NatRuleAdapter implements JsonDeserializer { + + @Override + public NatRule deserialize(JsonElement jsonElement, Type type, + JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + NatRule natRule = null; + + if (!jsonObject.has("type")) { + throw new JsonParseException("Deserializing as a NatRule, but no type present in the json object"); + } + + String natRuleType = jsonObject.get("type").getAsString(); + if ("SourceNatRule".equals(natRuleType)) { + return context.deserialize(jsonElement, SourceNatRule.class); + } + else if ("DestinationNatRule".equals(natRuleType)) { + return context.deserialize(jsonElement, DestinationNatRule.class); + } + + throw new JsonParseException("Failed to deserialize type \"" + natRuleType + "\""); + } + + } } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java new file mode 100644 index 00000000000..4132da48094 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java @@ -0,0 +1,123 @@ +// 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.network.nicira; + +public class SourceNatRule extends NatRule { + private String toSourceIpAddressMax; + private String toSourceIpAddressMin; + private Integer toSourcePort; + + public SourceNatRule() { + setType("SourceNatRule"); + } + + public String getToSourceIpAddressMax() { + return toSourceIpAddressMax; + } + + public void setToSourceIpAddressMax(String toSourceIpAddressMax) { + this.toSourceIpAddressMax = toSourceIpAddressMax; + } + + public String getToSourceIpAddressMin() { + return toSourceIpAddressMin; + } + + public void setToSourceIpAddressMin(String toSourceIpAddressMin) { + this.toSourceIpAddressMin = toSourceIpAddressMin; + } + + public Integer getToSourcePort() { + return toSourcePort; + } + + public void setToSourcePort(Integer toSourcePort) { + this.toSourcePort = toSourcePort; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime + * result + + ((toSourceIpAddressMax == null) ? 0 : toSourceIpAddressMax + .hashCode()); + result = prime + * result + + ((toSourceIpAddressMin == null) ? 0 : toSourceIpAddressMin + .hashCode()); + result = prime * result + + ((toSourcePort == null) ? 0 : toSourcePort.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + SourceNatRule other = (SourceNatRule) obj; + if (toSourceIpAddressMax == null) { + if (other.toSourceIpAddressMax != null) + return false; + } else if (!toSourceIpAddressMax.equals(other.toSourceIpAddressMax)) + return false; + if (toSourceIpAddressMin == null) { + if (other.toSourceIpAddressMin != null) + return false; + } else if (!toSourceIpAddressMin.equals(other.toSourceIpAddressMin)) + return false; + if (toSourcePort == null) { + if (other.toSourcePort != null) + return false; + } else if (!toSourcePort.equals(other.toSourcePort)) + return false; + return true; + } + + @Override + public boolean equalsIgnoreUuid(Object obj) { + if (this == obj) + return true; + if (!super.equalsIgnoreUuid(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + SourceNatRule other = (SourceNatRule) obj; + if (toSourceIpAddressMax == null) { + if (other.toSourceIpAddressMax != null) + return false; + } else if (!toSourceIpAddressMax.equals(other.toSourceIpAddressMax)) + return false; + if (toSourceIpAddressMin == null) { + if (other.toSourceIpAddressMin != null) + return false; + } else if (!toSourceIpAddressMin.equals(other.toSourceIpAddressMin)) + return false; + if (toSourcePort == null) { + if (other.toSourcePort != null) + return false; + } else if (!toSourcePort.equals(other.toSourcePort)) + return false; + return true; + } + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java index 6a9a0060387..114c9395d15 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java @@ -61,6 +61,7 @@ import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.network.nicira.ControlClusterStatus; +import com.cloud.network.nicira.DestinationNatRule; import com.cloud.network.nicira.L3GatewayAttachment; import com.cloud.network.nicira.LogicalRouterConfig; import com.cloud.network.nicira.LogicalRouterPort; @@ -75,6 +76,7 @@ import com.cloud.network.nicira.NiciraNvpTag; import com.cloud.network.nicira.PatchAttachment; import com.cloud.network.nicira.RouterNextHop; import com.cloud.network.nicira.SingleDefaultRouteImplictRoutingConfig; +import com.cloud.network.nicira.SourceNatRule; import com.cloud.network.nicira.TransportZoneBinding; import com.cloud.network.nicira.VifAttachment; import com.cloud.resource.ServerResource; @@ -449,13 +451,13 @@ public class NiciraNvpResource implements ServerResource { new PatchAttachment(lrpi.getUuid())); // Setup the source nat rule - NatRule snr = new NatRule(); - snr.setType("SourceNatRule"); + SourceNatRule snr = new SourceNatRule(); snr.setToSourceIpAddressMin(publicNetworkIpAddress.split("/")[0]); snr.setToSourceIpAddressMax(publicNetworkIpAddress.split("/")[0]); Match match = new Match(); match.setSourceIpAddresses(internalNetworkAddress); snr.setMatch(match); + snr.setOrder(200); _niciraNvpApi.createLogicalRouterNatRule(lrc.getUuid(), snr); } catch (NiciraNvpApiException e) { // We need to destroy the router if we already created it @@ -604,7 +606,8 @@ public class NiciraNvpResource implements ServerResource { continue; } - if (rule.getDstPortRange()[0] != rule.getDstPortRange()[1]) { + if (rule.getDstPortRange()[0] != rule.getDstPortRange()[1] || + rule.getSrcPortRange()[0] != rule.getSrcPortRange()[1] ) { return new ConfigurePortForwardingRulesOnLogicalRouterAnswer(cmd, false, "Nicira NVP doesn't support port ranges for port forwarding"); } @@ -700,32 +703,24 @@ public class NiciraNvpResource implements ServerResource { natRuleStr.append(" "); natRuleStr.append(m.getSourceIpAddresses()); natRuleStr.append(" ["); - natRuleStr.append(m.getSourcePortMin()); - natRuleStr.append("-"); - natRuleStr.append(m.getSourcePortMax()); + natRuleStr.append(m.getSourcePort()); natRuleStr.append(" ] -> "); natRuleStr.append(m.getDestinationIpAddresses()); natRuleStr.append(" ["); - natRuleStr.append(m.getDestinationPortMin()); - natRuleStr.append("-"); - natRuleStr.append(m.getDestinationPortMax()); + natRuleStr.append(m.getDestinationPort()); natRuleStr.append(" ]) -->"); if ("SourceNatRule".equals(rule.getType())) { - natRuleStr.append(rule.getToSourceIpAddressMin()); + natRuleStr.append(((SourceNatRule)rule).getToSourceIpAddressMin()); natRuleStr.append("-"); - natRuleStr.append(rule.getToSourceIpAddressMax()); + natRuleStr.append(((SourceNatRule)rule).getToSourceIpAddressMax()); natRuleStr.append(" ["); - natRuleStr.append(rule.getToSourcePortMin()); - natRuleStr.append("-"); - natRuleStr.append(rule.getToSourcePortMax()); + natRuleStr.append(((SourceNatRule)rule).getToSourcePort()); natRuleStr.append(" ])"); } else { - natRuleStr.append(rule.getToDestinationIpAddressMin()); - natRuleStr.append("-"); - natRuleStr.append(rule.getToDestinationIpAddressMax()); + natRuleStr.append(((DestinationNatRule)rule).getToDestinationIpAddress()); natRuleStr.append(" ["); - natRuleStr.append(rule.getToDestinationPort()); + natRuleStr.append(((DestinationNatRule)rule).getToDestinationPort()); natRuleStr.append(" ])"); } return natRuleStr.toString(); @@ -742,23 +737,24 @@ public class NiciraNvpResource implements ServerResource { protected NatRule[] generateStaticNatRulePair(String insideIp, String outsideIp) { NatRule[] rulepair = new NatRule[2]; - rulepair[0] = new NatRule(); + rulepair[0] = new DestinationNatRule(); rulepair[0].setType("DestinationNatRule"); - rulepair[1] = new NatRule(); + rulepair[0].setOrder(100); + rulepair[1] = new SourceNatRule(); rulepair[1].setType("SourceNatRule"); + rulepair[1].setOrder(100); Match m = new Match(); m.setDestinationIpAddresses(outsideIp); rulepair[0].setMatch(m); - rulepair[0].setToDestinationIpAddressMin(insideIp); - rulepair[0].setToDestinationIpAddressMax(insideIp); + ((DestinationNatRule)rulepair[0]).setToDestinationIpAddress(insideIp); // create matching snat rule m = new Match(); m.setSourceIpAddresses(insideIp); rulepair[1].setMatch(m); - rulepair[1].setToSourceIpAddressMin(outsideIp); - rulepair[1].setToSourceIpAddressMax(outsideIp); + ((SourceNatRule)rulepair[1]).setToSourceIpAddressMin(outsideIp); + ((SourceNatRule)rulepair[1]).setToSourceIpAddressMax(outsideIp); return rulepair; @@ -768,9 +764,9 @@ public class NiciraNvpResource implements ServerResource { // Start with a basic static nat rule, then add port and protocol details NatRule[] rulepair = generateStaticNatRulePair(insideIp, outsideIp); - rulepair[0].setToDestinationPort(insidePorts[0]); - rulepair[0].getMatch().setDestinationPortMin(outsidePorts[0]); - rulepair[0].getMatch().setDestinationPortMax(outsidePorts[1]); + ((DestinationNatRule)rulepair[0]).setToDestinationPort(insidePorts[0]); + rulepair[0].getMatch().setDestinationPort(outsidePorts[0]); + rulepair[0].setOrder(50); rulepair[0].getMatch().setEthertype("IPv4"); if ("tcp".equals(protocol)) { rulepair[0].getMatch().setProtocol(6); @@ -779,10 +775,9 @@ public class NiciraNvpResource implements ServerResource { rulepair[0].getMatch().setProtocol(17); } - rulepair[1].setToSourcePortMin(outsidePorts[0]); - rulepair[1].setToSourcePortMax(outsidePorts[1]); - rulepair[1].getMatch().setSourcePortMin(insidePorts[0]); - rulepair[1].getMatch().setSourcePortMax(insidePorts[1]); + ((SourceNatRule)rulepair[1]).setToSourcePort(outsidePorts[0]); + rulepair[1].getMatch().setSourcePort(insidePorts[0]); + rulepair[1].setOrder(50); rulepair[1].getMatch().setEthertype("IPv4"); if ("tcp".equals(protocol)) { rulepair[1].getMatch().setProtocol(6); diff --git a/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java index 88c5402822d..8e7245ebbdf 100644 --- a/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java +++ b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java @@ -20,28 +20,33 @@ import static org.junit.Assert.*; import org.junit.Test; +import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; public class NatRuleTest { - Gson gson = new Gson(); + @Test + public void testNatRuleEncoding() { + Gson gson = new GsonBuilder() + .registerTypeAdapter(NatRule.class, new com.cloud.network.nicira.NiciraNvpApi.NatRuleAdapter()) + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + + DestinationNatRule rn1 = new DestinationNatRule(); + rn1.setToDestinationIpAddress("10.10.10.10"); + rn1.setToDestinationPort(80); + Match mr1 = new Match(); + mr1.setSourceIpAddresses("11.11.11.11/24"); + mr1.setEthertype("IPv4"); + mr1.setProtocol(6); + rn1.setMatch(mr1); + + String jsonString = gson.toJson(rn1); + NatRule dnr = gson.fromJson(jsonString, NatRule.class); + + assertTrue(dnr instanceof DestinationNatRule); + assertTrue(rn1.equals(dnr)); + } - @Test - public void testNatRuleEncoding() { - NatRule rn1 = new NatRule(); - rn1.setToDestinationIpAddressMax("10.10.10.10"); - rn1.setToDestinationIpAddressMin("10.10.10.10"); - rn1.setToDestinationPort(80); - Match mr1 = new Match(); - mr1.setSourceIpAddresses("11.11.11.11/24"); - mr1.setEthertype("IPv4"); - mr1.setProtocol(6); - rn1.setMatch(mr1); - - - String jsonString = gson.toJson(rn1); - NatRule dnr = gson.fromJson(jsonString, NatRule.class); - - assertTrue(rn1.equals(dnr)); - } } diff --git a/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java b/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java index e3789108f34..8b5af3cc12d 100644 --- a/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java +++ b/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.naming.ConfigurationException; @@ -61,6 +62,7 @@ import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.host.Host; import com.cloud.network.nicira.Attachment; import com.cloud.network.nicira.ControlClusterStatus; +import com.cloud.network.nicira.DestinationNatRule; import com.cloud.network.nicira.LogicalRouterConfig; import com.cloud.network.nicira.LogicalRouterPort; import com.cloud.network.nicira.LogicalSwitch; @@ -69,6 +71,7 @@ import com.cloud.network.nicira.NatRule; import com.cloud.network.nicira.NiciraNvpApi; import com.cloud.network.nicira.NiciraNvpApiException; import com.cloud.network.nicira.NiciraNvpList; +import com.cloud.network.nicira.SourceNatRule; public class NiciraNvpResourceTest { NiciraNvpApi _nvpApi = mock(NiciraNvpApi.class); @@ -440,8 +443,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); ConfigureStaticNatRulesOnLogicalRouterAnswer a = (ConfigureStaticNatRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); @@ -452,11 +455,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -481,8 +484,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -500,11 +503,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -529,8 +532,10 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + final UUID rule0Uuid = UUID.randomUUID(); + final UUID rule1Uuid = UUID.randomUUID(); + rulepair[0].setUuid(rule0Uuid); + rulepair[1].setUuid(rule1Uuid); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -543,11 +548,11 @@ public class NiciraNvpResourceTest { ConfigureStaticNatRulesOnLogicalRouterAnswer a = (ConfigureStaticNatRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertTrue(a.getResult()); - verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { + verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override public boolean matches(Object argument) { - String uuid = (String) argument; - if ("bbbbb".equals(uuid) || "ccccc".equals(uuid)) { + UUID uuid = (UUID) argument; + if (rule0Uuid.equals(uuid) || rule1Uuid.equals(uuid)) { return true; } return false; @@ -572,8 +577,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenThrow(new NiciraNvpApiException()); // Mock the api find call @@ -585,7 +590,7 @@ public class NiciraNvpResourceTest { ConfigureStaticNatRulesOnLogicalRouterAnswer a = (ConfigureStaticNatRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertFalse(a.getResult()); - verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq("bbbbb")); + verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq(rulepair[0].getUuid())); } @Test @@ -611,8 +616,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); @@ -623,11 +628,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -652,8 +657,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -671,11 +676,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -700,8 +705,10 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + final UUID rule0Uuid = UUID.randomUUID(); + final UUID rule1Uuid = UUID.randomUUID(); + rulepair[0].setUuid(rule0Uuid); + rulepair[1].setUuid(rule1Uuid); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -714,11 +721,11 @@ public class NiciraNvpResourceTest { ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertTrue(a.getResult()); - verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { + verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override public boolean matches(Object argument) { - String uuid = (String) argument; - if ("bbbbb".equals(uuid) || "ccccc".equals(uuid)) { + UUID uuid = (UUID) argument; + if (rule0Uuid.equals(uuid) || rule1Uuid.equals(uuid)) { return true; } return false; @@ -743,8 +750,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenThrow(new NiciraNvpApiException()); // Mock the api find call @@ -756,7 +763,7 @@ public class NiciraNvpResourceTest { ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertFalse(a.getResult()); - verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq("bbbbb")); + verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq(rulepair[0].getUuid())); } @Test @@ -782,8 +789,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 80, 85 }, "11.11.11.11", new int[] { 80, 85}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); @@ -799,13 +806,15 @@ public class NiciraNvpResourceTest { assertTrue("DestinationNatRule".equals(rules[0].getType())); assertTrue("SourceNatRule".equals(rules[1].getType())); - assertTrue(rules[0].getToDestinationIpAddressMin().equals("10.10.10.10") && rules[0].getToDestinationIpAddressMax().equals("10.10.10.10")); - assertTrue(rules[0].getToDestinationPort() == null); - assertTrue(rules[0].getMatch().getDestinationIpAddresses().equals("11.11.11.11")); + DestinationNatRule dnr = (DestinationNatRule) rules[0]; + assertTrue(dnr.getToDestinationIpAddress().equals("10.10.10.10")); + assertTrue(dnr.getToDestinationPort() == null); + assertTrue(dnr.getMatch().getDestinationIpAddresses().equals("11.11.11.11")); - assertTrue(rules[1].getToSourceIpAddressMin().equals("11.11.11.11") && rules[1].getToSourceIpAddressMax().equals("11.11.11.11")); - assertTrue(rules[1].getToSourcePortMin() == null && rules[1].getToSourcePortMax() == null); - assertTrue(rules[1].getMatch().getSourceIpAddresses().equals("10.10.10.10")); + SourceNatRule snr = (SourceNatRule) rules[1]; + assertTrue(snr.getToSourceIpAddressMin().equals("11.11.11.11") && snr.getToSourceIpAddressMax().equals("11.11.11.11")); + assertTrue(snr.getToSourcePort() == null); + assertTrue(snr.getMatch().getSourceIpAddresses().equals("10.10.10.10")); } @Test @@ -814,17 +823,19 @@ public class NiciraNvpResourceTest { assertTrue("DestinationNatRule".equals(rules[0].getType())); assertTrue("SourceNatRule".equals(rules[1].getType())); - assertTrue(rules[0].getToDestinationIpAddressMin().equals("10.10.10.10") && rules[0].getToDestinationIpAddressMax().equals("10.10.10.10")); - assertTrue(rules[0].getToDestinationPort() == 8080); - assertTrue(rules[0].getMatch().getDestinationIpAddresses().equals("11.11.11.11")); - assertTrue(rules[0].getMatch().getDestinationPortMin() == 80 && rules[0].getMatch().getDestinationPortMax() == 80); - assertTrue(rules[0].getMatch().getEthertype().equals("IPv4") && rules[0].getMatch().getProtocol() == 6); + DestinationNatRule dnr = (DestinationNatRule) rules[0]; + assertTrue(dnr.getToDestinationIpAddress().equals("10.10.10.10")); + assertTrue(dnr.getToDestinationPort() == 8080); + assertTrue(dnr.getMatch().getDestinationIpAddresses().equals("11.11.11.11")); + assertTrue(dnr.getMatch().getDestinationPort() == 80 ); + assertTrue(dnr.getMatch().getEthertype().equals("IPv4") && dnr.getMatch().getProtocol() == 6); - assertTrue(rules[1].getToSourceIpAddressMin().equals("11.11.11.11") && rules[1].getToSourceIpAddressMax().equals("11.11.11.11")); - assertTrue(rules[1].getToSourcePortMin() == 80 && rules[1].getToSourcePortMax() == 80); - assertTrue(rules[1].getMatch().getSourceIpAddresses().equals("10.10.10.10")); - assertTrue(rules[1].getMatch().getSourcePortMin() == 8080 && rules[1].getMatch().getSourcePortMax() == 8080); - assertTrue(rules[1].getMatch().getEthertype().equals("IPv4") && rules[1].getMatch().getProtocol() == 6); + SourceNatRule snr = (SourceNatRule) rules[1]; + assertTrue(snr.getToSourceIpAddressMin().equals("11.11.11.11") && snr.getToSourceIpAddressMax().equals("11.11.11.11")); + assertTrue(snr.getToSourcePort() == 80); + assertTrue(snr.getMatch().getSourceIpAddresses().equals("10.10.10.10")); + assertTrue(snr.getMatch().getSourcePort() == 8080); + assertTrue(snr.getMatch().getEthertype().equals("IPv4") && rules[1].getMatch().getProtocol() == 6); } } diff --git a/plugins/pom.xml b/plugins/pom.xml index c7f41e165ca..8a5b598c811 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -38,6 +38,7 @@ affinity-group-processors/host-anti-affinity deployment-planners/user-concentrated-pod deployment-planners/user-dispersing + deployment-planners/implicit-dedication host-allocators/random hypervisors/ovm hypervisors/xen diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index 6dc3baae555..4d07c76a68f 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -65,3 +65,5 @@ getRouterStatus.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin bumpUpPriority.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin getDomRVersion.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin router_proxy.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin +createipAlias.sh=..,0755,/usr/lib/xcp/bin +deleteipAlias.sh=..,0755,/usr/lib/xcp/bin diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index a275df4a48b..7e92d5aa4ec 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -40,8 +40,8 @@ make_migratable.sh=..,0755,/opt/xensource/bin setup_iscsi.sh=..,0755,/opt/xensource/bin pingtest.sh=../../..,0755,/opt/xensource/bin dhcp_entry.sh=../../../../network/domr/,0755,/opt/xensource/bin -createipAlias.sh=../../..,0755,/opt/xensource/bin -deleteipAlias.sh=../../..,0755,/opt/xensource/bin +createipAlias.sh=..,0755,/opt/xensource/bin +deleteipAlias.sh=..,0755,/opt/xensource/bin router_proxy.sh=../../../../network/domr/,0755,/opt/xensource/bin vm_data.sh=../../../../network/domr/,0755,/opt/xensource/bin save_password_to_domr.sh=../../../../network/domr/,0755,/opt/xensource/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index 5c4673df247..8abd6b2c850 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -38,8 +38,8 @@ make_migratable.sh=..,0755,/opt/xensource/bin setup_iscsi.sh=..,0755,/opt/xensource/bin cloud-setup-bonding.sh=..,0755,/opt/xensource/bin pingtest.sh=../../..,0755,/opt/xensource/bin -createipAlias.sh=../../..,0755,/opt/xensource/bin -deleteipAlias.sh=../../..,0755,/opt/xensource/bin +createipAlias.sh=..,0755,/opt/xensource/bin +deleteipAlias.sh=..,0755,/opt/xensource/bin dhcp_entry.sh=../../../../network/domr/,0755,/opt/xensource/bin vm_data.sh=../../../../network/domr/,0755,/opt/xensource/bin save_password_to_domr.sh=../../../../network/domr/,0755,/opt/xensource/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index c7c58b98374..901f6de3643 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -37,8 +37,8 @@ setupxenserver.sh=..,0755,/opt/xensource/bin make_migratable.sh=..,0755,/opt/xensource/bin setup_iscsi.sh=..,0755,/opt/xensource/bin pingtest.sh=../../..,0755,/opt/xensource/bin -createipAlias.sh=../../..,0755,/opt/xensource/bin -deleteipAlias.sh=../../..,0755,/opt/xensource/bin +createipAlias.sh=..,0755,/opt/xensource/bin +deleteipAlias.sh=..,0755,/opt/xensource/bin dhcp_entry.sh=../../../../network/domr/,0755,/opt/xensource/bin vm_data.sh=../../../../network/domr/,0755,/opt/xensource/bin save_password_to_domr.sh=../../../../network/domr/,0755,/opt/xensource/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index 26205f2e7e6..d7da3747183 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -40,8 +40,8 @@ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/xensource/bin setupxenserver.sh=..,0755,/opt/xensource/bin make_migratable.sh=..,0755,/opt/xensource/bin -createipAlias.sh=../../..,0755,/opt/xensource/bin -deleteipAlias.sh=../../..,0755,/opt/xensource/bin +createipAlias.sh=..,0755,/opt/xensource/bin +deleteipAlias.sh=..,0755,/opt/xensource/bin setup_iscsi.sh=..,0755,/opt/xensource/bin pingtest.sh=../../..,0755,/opt/xensource/bin dhcp_entry.sh=../../../../network/domr/,0755,/opt/xensource/bin diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index ae666fe9add..1cb425a1e68 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -34,18 +34,6 @@ import java.util.TimeZone; import javax.inject.Inject; -import com.cloud.network.vpc.NetworkACL; -import com.cloud.network.vpc.NetworkACLItem; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOffering; -import com.cloud.vm.*; -import com.cloud.network.vpc.NetworkACL; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOffering; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -105,6 +93,8 @@ import org.apache.cloudstack.api.response.NicSecondaryIpResponse; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.PodResponse; +import org.apache.cloudstack.api.response.PortableIpRangeResponse; +import org.apache.cloudstack.api.response.PortableIpResponse; import org.apache.cloudstack.api.response.PrivateGatewayResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; @@ -149,6 +139,8 @@ import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.api.response.VpnUsersResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.usage.Usage; @@ -246,6 +238,12 @@ import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; import com.cloud.network.security.SecurityRule.SecurityRuleType; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcOffering; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Detail; @@ -444,11 +442,11 @@ public class ApiResponseHelper implements ResponseGenerator { snapshotResponse.setVolumeId(volume.getUuid()); snapshotResponse.setVolumeName(volume.getName()); snapshotResponse.setVolumeType(volume.getVolumeType().name()); - + DataCenter zone = ApiDBUtils.findZoneById(volume.getDataCenterId()); if (zone != null) { snapshotResponse.setZoneName(zone.getName()); - snapshotResponse.setZoneType(zone.getNetworkType().toString()); + snapshotResponse.setZoneType(zone.getNetworkType().toString()); } } snapshotResponse.setCreated(snapshot.getCreated()); @@ -733,7 +731,10 @@ public class ApiResponseHelper implements ResponseGenerator { } } - // set tag information + + ipResponse.setPortable(ipAddr.isPortable()); + + //set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PublicIpAddress, ipAddr.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -782,6 +783,9 @@ public class ApiResponseHelper implements ResponseGenerator { } lbResponse.setTags(tagResponses); + Network ntwk = ApiDBUtils.findNetworkById(loadBalancer.getNetworkId()); + lbResponse.setNetworkId(ntwk.getUuid()); + lbResponse.setObjectName("loadbalancer"); return lbResponse; } @@ -961,7 +965,7 @@ public class ApiResponseHelper implements ResponseGenerator { assert listStores != null && listStores.size() == 1 : "There should be one image data store returned"; return listStores.get(0); } - + @Override public StoragePoolForMigrationResponse createStoragePoolForMigrationResponse(StoragePool pool) { List viewPools = ApiDBUtils.newStoragePoolView(pool); @@ -991,10 +995,10 @@ public class ApiResponseHelper implements ResponseGenerator { clusterResponse.setClusterType(cluster.getClusterType().toString()); clusterResponse.setAllocationState(cluster.getAllocationState().toString()); clusterResponse.setManagedState(cluster.getManagedState().toString()); - String cpuOvercommitRatio = ApiDBUtils.findClusterDetails(cluster.getId(), "cpuOvercommitRatio").getValue(); - String memoryOvercommitRatio = ApiDBUtils.findClusterDetails(cluster.getId(), "memoryOvercommitRatio").getValue(); - clusterResponse.setCpuovercommitratio(cpuOvercommitRatio); - clusterResponse.setRamovercommitratio(memoryOvercommitRatio); + String cpuOvercommitRatio=ApiDBUtils.findClusterDetails(cluster.getId(),"cpuOvercommitRatio").getValue(); + String memoryOvercommitRatio=ApiDBUtils.findClusterDetails(cluster.getId(),"memoryOvercommitRatio").getValue(); + clusterResponse.setCpuOvercommitRatio(cpuOvercommitRatio); + clusterResponse.setMemoryOvercommitRatio(memoryOvercommitRatio); if (showCapacities != null && showCapacities) { List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, null, cluster.getId()); @@ -1316,7 +1320,7 @@ public class ApiResponseHelper implements ResponseGenerator { } else { tvo = ApiDBUtils.newTemplateView(result, zoneId, readyOnly); } - + return ViewResponseHelper.createIsoResponse(tvo.toArray(new TemplateJoinVO[tvo.size()])); } @@ -2084,13 +2088,13 @@ public class ApiResponseHelper implements ResponseGenerator { response.setForVpc(ApiDBUtils.isOfferingForVpc(offering)); response.setServices(serviceResponses); - + //set network offering details Map details = _ntwkModel.getNtwkOffDetails(offering.getId()); if (details != null && !details.isEmpty()) { response.setDetails(details); } - + response.setObjectName("networkoffering"); return response; } @@ -3522,7 +3526,7 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - + @Override public ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb, Map lbInstances) { @@ -3534,7 +3538,7 @@ public class ApiResponseHelper implements ResponseGenerator { Network nw = ApiDBUtils.findNetworkById(lb.getNetworkId()); lbResponse.setNetworkId(nw.getUuid()); populateOwner(lbResponse, lb); - + if (lb.getScheme() == Scheme.Internal) { lbResponse.setSourceIp(lb.getSourceIp().addr()); //TODO - create the view for the load balancer rule to reflect the network uuid @@ -3547,7 +3551,7 @@ public class ApiResponseHelper implements ResponseGenerator { Network ntwk = ApiDBUtils.findNetworkById(publicIp.getNetworkId()); lbResponse.setSourceIpNetworkId(ntwk.getUuid()); } - + //set load balancer rules information (only one rule per load balancer in this release) List ruleResponses = new ArrayList(); ApplicationLoadBalancerRuleResponse ruleResponse = new ApplicationLoadBalancerRuleResponse(); @@ -3561,7 +3565,7 @@ public class ApiResponseHelper implements ResponseGenerator { ruleResponse.setObjectName("loadbalancerrule"); ruleResponses.add(ruleResponse); lbResponse.setLbRules(ruleResponses); - + //set Lb instances information List instanceResponses = new ArrayList(); for (Ip ip : lbInstances.keySet()) { @@ -3573,7 +3577,7 @@ public class ApiResponseHelper implements ResponseGenerator { instanceResponse.setObjectName("loadbalancerinstance"); instanceResponses.add(instanceResponse); } - + lbResponse.setLbInstances(instanceResponses); //set tag information @@ -3619,6 +3623,69 @@ public class ApiResponseHelper implements ResponseGenerator { } } + @Override + public PortableIpRangeResponse createPortableIPRangeResponse(PortableIpRange ipRange) { + PortableIpRangeResponse response = new PortableIpRangeResponse(); + response.setId(ipRange.getUuid()); + String ipRangeStr = ipRange.getIpRange(); + if (ipRangeStr != null) { + String[] range = ipRangeStr.split("-"); + response.setStartIp(range[0]); + response.setEndIp(range[1]); + } + response.setVlan(ipRange.getVlanTag()); + response.setGateway(ipRange.getGateway()); + response.setNetmask(ipRange.getNetmask()); + response.setRegionId(ipRange.getRegionId()); + return response; + } + + @Override + public PortableIpResponse createPortableIPResponse(PortableIp portableIp) { + PortableIpResponse response = new PortableIpResponse(); + response.setAddress(portableIp.getAddress()); + Long accountId = portableIp.getAllocatedInDomainId(); + if (accountId != null) { + Account account = ApiDBUtils.findAccountById(accountId); + response.setAllocatedToAccountId(account.getAccountName()); + Domain domain = ApiDBUtils.findDomainById(account.getDomainId()); + response.setAllocatedInDomainId(domain.getUuid()); + } + + response.setAllocatedTime(portableIp.getAllocatedTime()); + + if (portableIp.getAssociatedDataCenterId() != null) { + DataCenter zone = ApiDBUtils.findZoneById(portableIp.getAssociatedDataCenterId()); + if (zone != null) { + response.setAssociatedDataCenterId(zone.getUuid()); + } + } + + if (portableIp.getPhysicalNetworkId() != null) { + PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(portableIp.getPhysicalNetworkId()); + if (pnw != null) { + response.setPhysicalNetworkId(pnw.getUuid()); + } + } + + if (portableIp.getAssociatedWithNetworkId() != null) { + Network ntwk = ApiDBUtils.findNetworkById(portableIp.getAssociatedWithNetworkId()); + if (ntwk != null) { + response.setAssociatedWithNetworkId(ntwk.getUuid()); + } + } + + if (portableIp.getAssociatedWithVpcId() != null) { + Vpc vpc = ApiDBUtils.findVpcById(portableIp.getAssociatedWithVpcId()); + if (vpc != null) { + response.setAssociatedWithVpcId(vpc.getUuid()); + } + } + + response.setState(portableIp.getState().name()); + + return response; + } @Override public InternalLoadBalancerElementResponse createInternalLbElementResponse(VirtualRouterProvider result) { @@ -3637,7 +3704,6 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - @Override public IsolationMethodResponse createIsolationMethodResponse(IsolationType method) { IsolationMethodResponse response = new IsolationMethodResponse(); diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index adcce409ebb..331404c382d 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -1134,7 +1134,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (networkId != null) { - sc.setJoinParameters("nicSearch", "networkId", networkId); + sc.setParameters("networkId", networkId); } if (vpcId != null) { diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index a62771965aa..7a94c780706 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -177,10 +177,10 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); - Long clusterId=null; + Long clusterId = null; if (hostId != null) { HostVO host = _hostDao.findById(hostId); - clusterId= host.getClusterId(); + clusterId = host.getClusterId(); } if (capacityCpu == null || capacityMemory == null || svo == null) { return false; @@ -263,8 +263,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, long hostId = vm.getHostId(); HostVO host = _hostDao.findById(hostId); long clusterId = host.getClusterId(); - float cpuOvercommitRatio =Float.parseFloat(_clusterDetailsDao.findDetail(clusterId,"cpuOvercommitRatio").getValue()); - float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId,"memoryOvercommitRatio").getValue()); + float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue()); + float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue()); ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); @@ -348,7 +348,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } @Override - public boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOvercommitRatio,float memoryOvercommitRatio, boolean considerReservedCapacity) { + public boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOvercommitRatio, float memoryOvercommitRatio, boolean considerReservedCapacity) { boolean hasCapacity = false; if (s_logger.isDebugEnabled()) { @@ -381,7 +381,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, long actualTotalCpu = capacityCpu.getTotalCapacity(); long actualTotalMem = capacityMem.getTotalCapacity(); long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio ); - long totalMem = (long) (actualTotalMem *memoryOvercommitRatio ); + long totalMem = (long) (actualTotalMem * memoryOvercommitRatio); if (s_logger.isDebugEnabled()) { s_logger.debug("Hosts's actual total CPU: " + actualTotalCpu + " and CPU after applying overprovisioning: " + totalCpu); } @@ -744,8 +744,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, capacityCPU.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId()); capacityCPU.addAnd("capacityType", SearchCriteria.Op.EQ, CapacityVO.CAPACITY_TYPE_CPU); List capacityVOCpus = _capacityDao.search(capacitySC, null); - Float cpuovercommitratio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(),"cpuOvercommitRatio").getValue()); - Float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(),"memoryOvercommitRatio").getValue()); + Float cpuovercommitratio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(), "cpuOvercommitRatio").getValue()); + Float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(), "memoryOvercommitRatio").getValue()); if (capacityVOCpus != null && !capacityVOCpus.isEmpty()) { CapacityVO CapacityVOCpu = capacityVOCpus.get(0); @@ -778,7 +778,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, if (capacityVOMems != null && !capacityVOMems.isEmpty()) { CapacityVO CapacityVOMem = capacityVOMems.get(0); - long newTotalMem = (long)((server.getTotalMemory())* memoryOvercommitRatio); + long newTotalMem = (long) ((server.getTotalMemory()) * memoryOvercommitRatio); if (CapacityVOMem.getTotalCapacity() <= newTotalMem || (CapacityVOMem.getUsedCapacity() + CapacityVOMem.getReservedCapacity() <= newTotalMem)) { CapacityVOMem.setTotalCapacity(newTotalMem); diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index d0ae914c20f..8db037b24ff 100755 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -80,10 +80,11 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * @param id * @param useVirtualNetwork * @param deploymentPlanner + * @param details * @return ID */ ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, - boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner); + boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner, Map details); /** * Creates a new disk offering diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 174a7ad7c2c..f0b6899c155 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -39,11 +39,8 @@ import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; - -import com.cloud.dc.*; -import com.cloud.dc.dao.*; -import com.cloud.user.*; import com.cloud.event.UsageEventUtils; +import com.cloud.utils.db.*; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.ApiConstants.LDAPParams; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; @@ -60,6 +57,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd; 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.region.CreatePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.DeletePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.ListPortableIpRangesCmd; 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; @@ -70,6 +70,8 @@ import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.region.*; +import org.apache.cloudstack.region.dao.RegionDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; @@ -113,7 +115,6 @@ import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; -import com.cloud.event.UsageEventUtils; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; @@ -165,6 +166,7 @@ import com.cloud.server.ConfigurationServer; import com.cloud.server.ManagementService; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.service.dao.ServiceOfferingDetailsDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.SwiftVO; import com.cloud.storage.dao.DiskOfferingDao; @@ -186,10 +188,6 @@ import com.cloud.utils.NumbersUtil; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.crypt.DBEncryptionUtil; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicIpAlias; @@ -199,58 +197,6 @@ import com.cloud.vm.dao.NicIpAliasDao; import com.cloud.vm.dao.NicIpAliasVO; import com.cloud.vm.dao.NicSecondaryIpDao; import edu.emory.mathcs.backport.java.util.Arrays; -import org.apache.cloudstack.acl.SecurityChecker; -import org.apache.cloudstack.api.ApiConstants.LDAPParams; -import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; -import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; -import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd; -import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd; -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; -import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; -import java.net.URI; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; @Component @Local(value = { ConfigurationManager.class, ConfigurationService.class }) @@ -276,6 +222,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Inject ServiceOfferingDao _serviceOfferingDao; @Inject + ServiceOfferingDetailsDao _serviceOfferingDetailsDao; + @Inject DiskOfferingDao _diskOfferingDao; @Inject NetworkOfferingDao _networkOfferingDao; @@ -330,6 +278,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Inject VpcManager _vpcMgr; @Inject + PortableIpRangeDao _portableIpRangeDao; + @Inject + RegionDao _regionDao; + @Inject + PortableIpDao _portableIpDao; + @Inject ConfigurationServer _configServer; @Inject DcDetailsDao _dcDetailsDao; @@ -1901,7 +1855,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati userNetwork.setBroadcastDomainType(broadcastDomainType); userNetwork.setNetworkDomain(networkDomain); - _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, false, + _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, false, Domain.ROOT_DOMAIN, null, null, null, true); } } @@ -2049,19 +2003,26 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(), - localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner()); + return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), + cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(), + localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), + cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner(), cmd.getDetails()); } @Override @ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CREATE, eventDescription = "creating service offering") - public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_type, String name, int cpu, int ramSize, int speed, String displayText, - boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) { + public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_type, + String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, + boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, + Integer networkRate, String deploymentPlanner, Map details) { tags = cleanupTags(tags); ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type, domainId, hostTag, deploymentPlanner); if ((offering = _serviceOfferingDao.persist(offering)) != null) { + if (details != null) { + _serviceOfferingDetailsDao.persist(offering.getId(), details); + } UserContext.current().setEventDetails("Service offering id=" + offering.getId()); return offering; } else { @@ -2543,7 +2504,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Transaction txn = Transaction.currentTxn(); txn.start(); - Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, podId, startIP, + Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr); //create an entry in the nic_secondary table. This will be the new gateway that will be configured on the corresponding routervm. if (sameSubnet == false) { @@ -2918,7 +2879,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + " as ip " + ip + " belonging to the range is used for static nat purposes. Cleanup the rules first"); } - + if (ip.isSourceNat()) { throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + " as ip " + ip + " belonging to the range is a source nat ip for the network id=" + ip.getSourceNetworkId() + @@ -2937,7 +2898,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } finally { _vlanDao.releaseFromLockTable(vlanDbId); - } + } } } @@ -3765,7 +3726,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati firewallProviderSet.add(firewallProvider); serviceProviderMap.put(Service.Firewall, firewallProviderSet); } - + Map details = new HashMap(); if (detailsStr != null) { for (String detailStr : detailsStr.keySet()) { @@ -3820,7 +3781,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Unknown specified value for " + Capability.LbSchemes.getName()); } } else { - throw new InvalidParameterValueException("Only " + Capability.SupportedLBIsolation.getName() + + throw new InvalidParameterValueException("Only " + Capability.SupportedLBIsolation.getName() + ", " + Capability.ElasticLb.getName() + ", " + Capability.InlineMode.getName() + ", " + Capability.LbSchemes.getName() + " capabilities can be sepcified for LB service"); } @@ -3974,7 +3935,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } else { inline = false; } - + String publicLbStr = lbServiceCapabilityMap.get(Capability.LbSchemes); if (serviceProviderMap.containsKey(Service.Lb)) { if (publicLbStr != null) { @@ -3987,7 +3948,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } } - + //in the current version of the code, publicLb and specificLb can't both be set to true for the same network offering if (publicLb && internalLb) { throw new InvalidParameterValueException("Public lb and internal lb can't be enabled at the same time on the offering"); @@ -4030,7 +3991,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (serviceOfferingId != null) { offering.setServiceOfferingId(serviceOfferingId); } - + //validate the details if (details != null) { validateNtwkOffDetails(details, serviceProviderMap); @@ -4077,7 +4038,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati protected void validateNtwkOffDetails(Map details, Map> serviceProviderMap) { for (Detail detail : details.keySet()) { - + Provider lbProvider = null; if (detail == NetworkOffering.Detail.InternalLbProvider || detail == NetworkOffering.Detail.PublicLbProvider) { //1) Vaidate the detail values - have to match the lb provider name @@ -4092,13 +4053,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati break; } } - } - + } + if (lbProvider == null) { throw new InvalidParameterValueException("Invalid value " + details.get(detail) + " for the detail " + detail + ". The provider is not supported by the network offering"); } - + //2) validate if the provider supports the scheme Set lbProviders = new HashSet(); lbProviders.add(lbProvider); @@ -4708,4 +4669,153 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return null; } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RANGE_CREATE, eventDescription = "creating portable ip range", async = false) + public PortableIpRange createPortableIpRange(CreatePortableIpRangeCmd cmd) throws ConcurrentOperationException { + Integer regionId = cmd.getRegionId(); + String startIP = cmd.getStartIp(); + String endIP = cmd.getEndIp(); + String gateway = cmd.getGateway(); + String netmask = cmd.getNetmask(); + Long userId = UserContext.current().getCallerUserId(); + String vlanId = cmd.getVlan(); + + Region region = _regionDao.findById(regionId); + if (region == null) { + throw new InvalidParameterValueException("Invalid region ID: " + regionId); + } + + if (!NetUtils.isValidIp(startIP) || !NetUtils.isValidIp(endIP) || !NetUtils.validIpRange(startIP, endIP)) { + throw new InvalidParameterValueException("Invalid portable ip range: " + startIP + "-" + endIP); + } + + if (!NetUtils.sameSubnet(startIP, gateway, netmask)) { + throw new InvalidParameterValueException("Please ensure that your start IP is in the same subnet as " + + "your portable IP range's gateway and as per the IP range's netmask."); + } + + if (!NetUtils.sameSubnet(endIP, gateway, netmask)) { + throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as " + + "your portable IP range's gateway and as per the IP range's netmask."); + } + + if (checkOverlapPortableIpRange(regionId, startIP, endIP)) { + throw new InvalidParameterValueException("Ip range: " + startIP + "-" + endIP + " overlaps with a portable" + + " IP range already configured in the region " + regionId); + } + + if (vlanId == null) { + vlanId = Vlan.UNTAGGED; + } else { + if (!NetUtils.isValidVlan(vlanId)) { + throw new InvalidParameterValueException("Invalid vlan id " + vlanId); + } + } + GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange"); + portableIpLock.lock(5); + Transaction txn = Transaction.currentTxn(); + txn.start(); + + PortableIpRangeVO portableIpRange = new PortableIpRangeVO(regionId, vlanId, gateway, netmask, startIP, endIP); + portableIpRange = _portableIpRangeDao.persist(portableIpRange); + + long startIpLong = NetUtils.ip2Long(startIP); + long endIpLong = NetUtils.ip2Long(endIP); + while(startIpLong <= endIpLong) { + PortableIpVO portableIP = new PortableIpVO(regionId, portableIpRange.getId(), vlanId, + gateway, netmask,NetUtils.long2Ip(startIpLong)); + _portableIpDao.persist(portableIP); + startIpLong++; + } + + txn.commit(); + portableIpLock.unlock(); + return portableIpRange; + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RANGE_DELETE, eventDescription = "deleting portable ip range", async = false) + public boolean deletePortableIpRange(DeletePortableIpRangeCmd cmd) { + long rangeId = cmd.getId(); + PortableIpRangeVO portableIpRange = _portableIpRangeDao.findById(rangeId); + if (portableIpRange == null) { + throw new InvalidParameterValueException("Please specify a valid portable IP range id."); + } + + List fullIpRange = _portableIpDao.listByRangeId(portableIpRange.getId()); + List freeIpRange = _portableIpDao.listByRangeIdAndState(portableIpRange.getId(), PortableIp.State.Free); + + if (fullIpRange != null && freeIpRange != null) { + if (fullIpRange.size() == freeIpRange.size()) { + _portableIpRangeDao.expunge(portableIpRange.getId()); + return true; + } else { + throw new InvalidParameterValueException("Can't delete portable IP range as there are IP's assigned."); + } + } + + return false; + } + + @Override + public List listPortableIpRanges(ListPortableIpRangesCmd cmd) { + Integer regionId = cmd.getRegionIdId(); + Long rangeId = cmd.getPortableIpRangeId(); + + List ranges = new ArrayList(); + if (regionId != null) { + Region region = _regionDao.findById(regionId); + if (region == null) { + throw new InvalidParameterValueException("Invalid region ID: " + regionId); + } + return _portableIpRangeDao.listByRegionId(regionId); + } + + if (rangeId != null) { + PortableIpRangeVO range = _portableIpRangeDao.findById(rangeId); + if (range == null) { + throw new InvalidParameterValueException("Invalid portable IP range ID: " + regionId); + } + ranges.add(range); + return ranges; + } + + return _portableIpRangeDao.listAll(); + } + + @Override + public List listPortableIps(long id) { + + PortableIpRangeVO portableIpRange = _portableIpRangeDao.findById(id); + if (portableIpRange == null) { + throw new InvalidParameterValueException("Please specify a valid portable IP range id."); + } + + return _portableIpDao.listByRangeId(portableIpRange.getId()); + } + + private boolean checkOverlapPortableIpRange(int regionId, String newStartIpStr, String newEndIpStr) { + long newStartIp = NetUtils.ip2Long(newStartIpStr); + long newEndIp = NetUtils.ip2Long(newEndIpStr); + + List existingPortableIPRanges = _portableIpRangeDao.listByRegionId(regionId); + for (PortableIpRangeVO portableIpRange : existingPortableIPRanges) { + String ipRangeStr = portableIpRange.getIpRange(); + String[] range = ipRangeStr.split("-"); + long startip = NetUtils.ip2Long(range[0]); + long endIp = NetUtils.ip2Long(range[1]); + + if ((newStartIp >= startip && newStartIp <= endIp) || (newEndIp >= startip && newEndIp <= endIp)) { + return true; + } + + if ((startip >= newStartIp && startip <= newEndIp) || (endIp >= newStartIp && endIp <= newEndIp)) { + return true; + } + } + return false; + } } diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index c45c8d0b807..0f611681110 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -380,7 +380,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (planner instanceof DeploymentClusterPlanner) { - ExcludeList PlannerAvoidInput = new ExcludeList(avoids.getDataCentersToAvoid(), + ExcludeList plannerAvoidInput = new ExcludeList(avoids.getDataCentersToAvoid(), avoids.getPodsToAvoid(), avoids.getClustersToAvoid(), avoids.getHostsToAvoid(), avoids.getPoolsToAvoid()); @@ -388,19 +388,19 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (clusterList != null && !clusterList.isEmpty()) { // planner refactoring. call allocators to list hosts - ExcludeList PlannerAvoidOutput = new ExcludeList(avoids.getDataCentersToAvoid(), + ExcludeList plannerAvoidOutput = new ExcludeList(avoids.getDataCentersToAvoid(), avoids.getPodsToAvoid(), avoids.getClustersToAvoid(), avoids.getHostsToAvoid(), avoids.getPoolsToAvoid()); - resetAvoidSet(PlannerAvoidOutput, PlannerAvoidInput); + resetAvoidSet(plannerAvoidOutput, plannerAvoidInput); dest = checkClustersforDestination(clusterList, vmProfile, plan, avoids, dc, - getPlannerUsage(planner), PlannerAvoidOutput); + getPlannerUsage(planner), plannerAvoidOutput); if (dest != null) { return dest; } // reset the avoid input to the planners - resetAvoidSet(avoids, PlannerAvoidOutput); + resetAvoidSet(avoids, plannerAvoidOutput); } else { return null; @@ -815,12 +815,8 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy // remove any hosts/pools that the planners might have added // to get the list of hosts/pools that Allocators flagged as 'avoid' - if (allocatorAvoidOutput.getHostsToAvoid() != null && plannerAvoidOutput.getHostsToAvoid() != null) { - allocatorAvoidOutput.getHostsToAvoid().removeAll(plannerAvoidOutput.getHostsToAvoid()); - } - if (allocatorAvoidOutput.getPoolsToAvoid() != null && plannerAvoidOutput.getPoolsToAvoid() != null) { - allocatorAvoidOutput.getPoolsToAvoid().removeAll(plannerAvoidOutput.getPoolsToAvoid()); - } + + resetAvoidSet(allocatorAvoidOutput, plannerAvoidOutput); // if all hosts or all pools in the cluster are in avoid set after this // pass, then put the cluster in avoid set. @@ -829,8 +825,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy List allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(Host.Type.Routing, clusterVO.getId(), clusterVO.getPodId(), clusterVO.getDataCenterId(), null); for (HostVO host : allhostsInCluster) { - if (allocatorAvoidOutput.getHostsToAvoid() == null - || !allocatorAvoidOutput.getHostsToAvoid().contains(host.getId())) { + if (!allocatorAvoidOutput.shouldAvoid(host)) { // there's some host in the cluster that is not yet in avoid set avoidAllHosts = false; } @@ -839,8 +834,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy List allPoolsInCluster = _storagePoolDao.findPoolsByTags(clusterVO.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null); for (StoragePoolVO pool : allPoolsInCluster) { - if (allocatorAvoidOutput.getPoolsToAvoid() == null - || !allocatorAvoidOutput.getPoolsToAvoid().contains(pool.getId())) { + if (!allocatorAvoidOutput.shouldAvoid(pool)) { // there's some pool in the cluster that is not yet in avoid set avoidAllPools = false; } diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index 33e9d5da305..befd8c10113 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -88,8 +88,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis ServiceOffering offering = vmProfile.getServiceOffering(); VirtualMachine vm = vmProfile.getVirtualMachine(); - Long minMemory = (long) (offering.getRamSize()/vmProfile.getCpuOvercommitRatio()); - int minspeed= (int)(offering.getSpeed()/vmProfile.getMemoryOvercommitRatio()); + Long minMemory = (long) (offering.getRamSize() / vmProfile.getMemoryOvercommitRatio()); + int minspeed = (int) (offering.getSpeed() / vmProfile.getCpuOvercommitRatio()); int maxspeed = (offering.getSpeed()); VirtualMachineTO to = new VirtualMachineTO(vm.getId(), vm.getInstanceName(), vm.getType(), offering.getCpu(), minspeed, maxspeed, minMemory * 1024l * 1024l, offering.getRamSize() * 1024l * 1024l, null, null, vm.isHaEnabled(), vm.limitCpuUse(), vm.getVncPassword()); diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 08198ee40e6..05bc26ee5c2 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -59,6 +59,7 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; +import org.apache.cloudstack.region.PortableIp; /** * NetworkManager manages the network for the different end users. @@ -122,7 +123,34 @@ public interface NetworkManager { Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; - void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest); + /** + * prepares vm nic change for migration + * + * This method will be called in migration transaction before the vm migration. + * @param vm + * @param dest + */ + void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest); + + /** + * commit vm nic change for migration + * + * This method will be called in migration transaction after the successful + * vm migration. + * @param src + * @param dst + */ + void commitNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst); + + /** + * rollback vm nic change for migration + * + * This method will be called in migaration transaction after vm migration + * failure. + * @param src + * @param dst + */ + void rollbackNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst); boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements); @@ -240,6 +268,16 @@ public interface NetworkManager { IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; + IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException; + + IPAddressVO disassociatePortableIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException; + + boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId); + + void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException;; /** * @param network @@ -325,6 +363,9 @@ public interface NetworkManager { DataCenter zone) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; + IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) + throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; + Map finalizeServicesAndProvidersForNetwork(NetworkOffering offering, Long physicalNetworkId); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index bf79596b67f..e8801801d72 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -104,6 +104,10 @@ import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.dao.*; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpDao; +import org.apache.cloudstack.region.PortableIpVO; +import org.apache.cloudstack.region.Region; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -250,6 +254,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L UserIpv6AddressDao _ipv6Dao; @Inject Ipv6AddressManager _ipv6Mgr; + @Inject + PortableIpDao _portableIpDao; protected StateMachine2 _stateMachine; private final HashMap _systemNetworks = new HashMap(5); @@ -701,6 +707,62 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return ip; } + @Override + @DB + public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) + throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { + + Transaction txn = Transaction.currentTxn(); + GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange"); + PortableIpVO allocatedPortableIp; + IPAddressVO ipaddr; + + try { + portableIpLock.lock(5); + + txn.start(); + //TODO: get the region ID corresponding to running management server + List portableIpVOs = _portableIpDao.listByRegionIdAndState(1, PortableIp.State.Free); + if (portableIpVOs == null || portableIpVOs.isEmpty()) { + InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException + ("Unable to find available portable IP addresses", Region.class, new Long(1)); + throw ex; + } + + // allocate first portable IP to the user + allocatedPortableIp = portableIpVOs.get(0); + allocatedPortableIp.setAllocatedTime(new Date()); + allocatedPortableIp.setAllocatedToAccountId(ipOwner.getAccountId()); + allocatedPortableIp.setAllocatedInDomainId(ipOwner.getDomainId()); + allocatedPortableIp.setState(PortableIp.State.Allocated); + _portableIpDao.update(allocatedPortableIp.getId(), allocatedPortableIp); + + // provision portable IP range VLAN + long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public).getId(); + Network network = _networkModel.getNetwork(physicalNetworkId); + String range = allocatedPortableIp.getAddress() + "-" + allocatedPortableIp.getAddress(); + VlanVO vlan = new VlanVO(VlanType.VirtualNetwork, allocatedPortableIp.getVlan(), allocatedPortableIp.getGateway(), + allocatedPortableIp.getNetmask(), dcId, range, network.getId(), network.getId(), null, null, null); + vlan = _vlanDao.persist(vlan); + + // provision the portable IP in to user_ip_address table + ipaddr = new IPAddressVO(new Ip(allocatedPortableIp.getAddress()), dcId, networkId, vpcID, network.getId(), + network.getId(), vlan.getId(), true); + ipaddr.setState(State.Allocated); + ipaddr.setAllocatedTime(new Date()); + ipaddr.setAllocatedInDomainId(ipOwner.getDomainId()); + ipaddr.setAllocatedToAccountId(ipOwner.getId()); + ipaddr= _ipAddressDao.persist(ipaddr); + + txn.commit(); + + } finally { + portableIpLock.unlock(); + } + + return ipaddr; + } + protected IPAddressVO getExistingSourceNatInNetwork(long ownerId, Long networkId) { List addrs = _networkModel.listPublicIpsAssignedToGuestNtwk(ownerId, networkId, true); @@ -740,13 +802,15 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } DataCenter zone = _configMgr.getZone(network.getDataCenterId()); - if (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced) { + if (zone.getNetworkType() == NetworkType.Advanced) { + if (network.getGuestType() == Network.GuestType.Shared) { if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); } else { throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if " + "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network"); } + } } else { _accountMgr.checkAccess(caller, null, true, ipToAssoc); } @@ -843,6 +907,162 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } } + @Override + public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException { + return associateIPToGuestNetwork(ipAddrId, networkId, releaseOnFailure); + } + + @DB + @Override + public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkId) + throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException { + + Account caller = UserContext.current().getCaller(); + Account owner = null; + + Network network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + + IPAddressVO ipToAssoc = _ipAddressDao.findById(ipId); + if (ipToAssoc != null) { + + if (ipToAssoc.getAssociatedWithNetworkId() == null) { + throw new InvalidParameterValueException("IP " + ipToAssoc + " is not associated with any network"); + } + + if (ipToAssoc.getAssociatedWithNetworkId() != network.getId()) { + throw new InvalidParameterValueException("IP " + ipToAssoc + " is not associated with network id" + networkId); + } + + DataCenter zone = _configMgr.getZone(network.getDataCenterId()); + if (zone.getNetworkType() == NetworkType.Advanced) { + if (network.getGuestType() == Network.GuestType.Shared) { + assert (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())); + _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); + } + } else { + _accountMgr.checkAccess(caller, null, true, ipToAssoc); + } + owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); + } else { + s_logger.debug("Unable to find ip address by id: " + ipId); + return null; + } + + DataCenter zone = _configMgr.getZone(network.getDataCenterId()); + + // Check that network belongs to IP owner - skip this check + // - if zone is basic zone as there is just one guest network, + // - if shared network in Advanced zone + // - and it belongs to the system + if (network.getAccountId() != owner.getId()) { + if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) { + throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP"); + } + } + + // Check if IP has any services (rules) associated in the network + List ipList = new ArrayList(); + PublicIp publicIp = PublicIp.createFromAddrAndVlan(ipToAssoc, _vlanDao.findById(ipToAssoc.getVlanId())); + ipList.add(publicIp); + Map> ipToServices = _networkModel.getIpToServices(ipList, false, true); + if (ipToServices != null & !ipToServices.isEmpty()) { + Set services = ipToServices.get(publicIp); + if (services != null && !services.isEmpty()) { + throw new InvalidParameterValueException("IP " + ipToAssoc + " has services and rules associated in the network " + networkId); + } + } + + IPAddressVO ip = _ipAddressDao.findById(ipId); + ip.setAssociatedWithNetworkId(null); + _ipAddressDao.update(ipId, ip); + + try { + boolean success = applyIpAssociations(network, false); + if (success) { + s_logger.debug("Successfully associated ip address " + ip.getAddress().addr() + " to network " + network); + } else { + s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " to network " + network); + } + return ip; + } finally { + + } + } + + @Override + public boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId) { + Network network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + + IPAddressVO ip = _ipAddressDao.findById(ipAddrId); + if (ip == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + + // Check if IP has any services (rules) associated in the network + List ipList = new ArrayList(); + PublicIp publicIp = PublicIp.createFromAddrAndVlan(ip, _vlanDao.findById(ip.getVlanId())); + ipList.add(publicIp); + Map> ipToServices = _networkModel.getIpToServices(ipList, false, true); + if (ipToServices != null & !ipToServices.isEmpty()) { + Set ipServices = ipToServices.get(publicIp); + if (ipServices != null && !ipServices.isEmpty()) { + return false; + } + } + + return true; + } + + @DB + @Override + public void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException { + + Network srcNetwork = _networksDao.findById(currentNetworkId); + if (srcNetwork == null) { + throw new InvalidParameterValueException("Invalid source network id " + currentNetworkId +" is given"); + } + + Network dstNetwork = _networksDao.findById(newNetworkId); + if (dstNetwork == null) { + throw new InvalidParameterValueException("Invalid source network id " + newNetworkId +" is given"); + } + + IPAddressVO ip = _ipAddressDao.findById(ipAddrId); + if (ip == null) { + throw new InvalidParameterValueException("Invalid portable ip address id is given"); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + assert(isPortableIpTransferableFromNetwork(ipAddrId, currentNetworkId)); + + if (srcNetwork.getVpcId() != null) { + _vpcMgr.unassignIPFromVpcNetwork(ipAddrId, currentNetworkId); + } else { + disassociatePortableIPToGuestNetwork(ipAddrId, currentNetworkId); + } + + associatePortableIPToGuestNetwork(ipAddrId, newNetworkId, false); + + if (dstNetwork.getVpcId() != null) { + ip.setVpcId(dstNetwork.getVpcId()); + } else { + ip.setVpcId(null); + } + + _ipAddressDao.update(ipAddrId, ip); + txn.commit(); + } @Override @DB @@ -883,12 +1103,42 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } if (success) { + if (ip.isPortable()) { + releasePortableIpAddress(addrId); + } s_logger.debug("Released a public ip id=" + addrId); } return success; } + @DB + private void releasePortableIpAddress(long addrId) { + Transaction txn = Transaction.currentTxn(); + GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange"); + + txn.start(); + try { + portableIpLock.lock(5); + IPAddressVO ip = _ipAddressDao.findById(addrId); + + // unassign portable IP + PortableIpVO portableIp = _portableIpDao.findByIpAddress(ip.getAddress().addr()); + _portableIpDao.unassignIpAddress(portableIp.getId()); + + // removed the provisioned vlan + VlanVO vlan = _vlanDao.findById(ip.getVlanId()); + _vlanDao.expunge(vlan.getId()); + + // remove the provisioned public ip address + _ipAddressDao.expunge(ip.getId()); + + txn.commit(); + } finally { + portableIpLock.releaseRef(); + } + } + @Override @DB public boolean configure(final String name, final Map params) throws ConfigurationException { @@ -1749,8 +1999,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { + public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { List nics = _nicDao.listByVmId(vm.getId()); + ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), null, null); for (NicVO nic : nics) { NetworkVO network = _networksDao.findById(nic.getNetworkId()); Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); @@ -1758,11 +2009,80 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName()); NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network)); + if(guru instanceof NetworkMigrationResponder){ + if(!((NetworkMigrationResponder) guru).prepareMigration(profile, network, vm, dest, context)){ + s_logger.error("NetworkGuru "+guru+" prepareForMigration failed."); // XXX: Transaction error + } + } + for (NetworkElement element : _networkElements) { + if(element instanceof NetworkMigrationResponder){ + if(!((NetworkMigrationResponder) element).prepareMigration(profile, network, vm, dest, context)){ + s_logger.error("NetworkElement "+element+" prepareForMigration failed."); // XXX: Transaction error + } + } + } guru.updateNicProfile(profile, network); vm.addNic(profile); } } + private NicProfile findNicProfileById(VirtualMachineProfile vm, long id){ + for(NicProfile nic: vm.getNics()){ + if(nic.getId() == id){ + return nic; + } + } + return null; + } + + @Override + public void commitNicForMigration( + VirtualMachineProfile src, + VirtualMachineProfile dst) { + for(NicProfile nicSrc: src.getNics()){ + NetworkVO network = _networksDao.findById(nicSrc.getNetworkId()); + NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName()); + NicProfile nicDst = findNicProfileById(dst, nicSrc.getId()); + ReservationContext src_context = new ReservationContextImpl(nicSrc.getReservationId(), null, null); + ReservationContext dst_context = new ReservationContextImpl(nicDst.getReservationId(), null, null); + + if(guru instanceof NetworkMigrationResponder){ + ((NetworkMigrationResponder) guru).commitMigration(nicSrc, network, src, src_context, dst_context); + } + for (NetworkElement element : _networkElements) { + if(element instanceof NetworkMigrationResponder){ + ((NetworkMigrationResponder) element).commitMigration(nicSrc, network, src, src_context, dst_context); + } + } + // update the reservation id + NicVO nicVo = _nicDao.findById(nicDst.getId()); + nicVo.setReservationId(nicDst.getReservationId()); + _nicDao.persist(nicVo); + } + } + + @Override + public void rollbackNicForMigration( + VirtualMachineProfile src, + VirtualMachineProfile dst) { + for(NicProfile nicDst: dst.getNics()){ + NetworkVO network = _networksDao.findById(nicDst.getNetworkId()); + NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName()); + NicProfile nicSrc = findNicProfileById(src, nicDst.getId()); + ReservationContext src_context = new ReservationContextImpl(nicSrc.getReservationId(), null, null); + ReservationContext dst_context = new ReservationContextImpl(nicDst.getReservationId(), null, null); + + if(guru instanceof NetworkMigrationResponder){ + ((NetworkMigrationResponder) guru).rollbackMigration(nicDst, network, dst, src_context, dst_context); + } + for (NetworkElement element : _networkElements) { + if(element instanceof NetworkMigrationResponder){ + ((NetworkMigrationResponder) element).rollbackMigration(nicDst, network, dst, src_context, dst_context); + } + } + } + } + @Override @DB public void release(VirtualMachineProfile vmProfile, boolean forced) throws @@ -2952,7 +3272,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // the code would be triggered s_logger.debug("Cleaning up remote access vpns as a part of public IP id=" + ipId + " release..."); try { - _vpnMgr.destroyRemoteAccessVpn(ipId, caller); + _vpnMgr.destroyRemoteAccessVpnForIp(ipId, caller); } catch (ResourceUnavailableException e) { s_logger.warn("Unable to destroy remote access vpn for ip id=" + ipId + " as a part of ip release", e); success = false; diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 135fd290535..8971f8c163b 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -320,8 +320,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { } else { if (rulesRevoked) { // no active rules/revoked rules are associated with this public IP, so remove the - // association with the provider - ip.setState(State.Releasing); + // association with the provider + if (ip.isSourceNat()) { + s_logger.debug("Not releasing ip " + ip.getAddress().addr() + " as it is in use for SourceNat"); + } else { + ip.setState(State.Releasing); + } } else { if (ip.getState() == State.Releasing) { // rules are not revoked yet, so don't let the network service provider revoke the IP diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index ed9a8c4ece7..1533ca9bc4f 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -39,6 +39,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.vpc.dao.VpcDao; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -184,32 +185,6 @@ import com.cloud.vm.dao.NicSecondaryIpDao; import com.cloud.vm.dao.NicSecondaryIpVO; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.vm.*; -import com.cloud.vm.dao.*; -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; -import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.InvalidParameterException; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.*; /** @@ -315,6 +290,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Inject AccountGuestVlanMapDao _accountGuestVlanMapDao; @Inject + VpcDao _vpcDao; + @Inject NetworkACLDao _networkACLDao; int _cidrLimit; @@ -527,22 +504,23 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + Account caller = UserContext.current().getCaller(); + long callerUserId = UserContext.current().getCallerUserId(); + DataCenter zone = _configMgr.getZone(zoneId); + if (networkId != null) { Network network = _networksDao.findById(networkId); if (network == null) { throw new InvalidParameterValueException("Invalid network id is given"); } + if (network.getGuestType() == Network.GuestType.Shared) { - DataCenter zone = _configMgr.getZone(zoneId); if (zone == null) { throw new InvalidParameterValueException("Invalid zone Id is given"); } - // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' if (zone.getNetworkType() == NetworkType.Advanced) { if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - Account caller = UserContext.current().getCaller(); - long callerUserId = UserContext.current().getCallerUserId(); _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); if (s_logger.isDebugEnabled()) { s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); @@ -554,20 +532,67 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } } } + } else { + _accountMgr.checkAccess(caller, null, false, ipOwner); } - return allocateIP(ipOwner, false, zoneId); + return _networkMgr.allocateIp(ipOwner, false, caller, callerUserId, zone); } - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) + @Override + @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_ASSIGN, eventDescription = "allocating portable public Ip", create = true) + public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { Account caller = UserContext.current().getCaller(); - // check permissions - _accountMgr.checkAccess(caller, null, false, ipOwner); long callerUserId = UserContext.current().getCallerUserId(); DataCenter zone = _configMgr.getZone(zoneId); - return _networkMgr.allocateIp(ipOwner, isSystem, caller, callerUserId, zone); + if ((networkId == null && vpcId == null) && (networkId != null && vpcId != null)) { + throw new InvalidParameterValueException("One of Network id or VPC is should be passed"); + } + + if (networkId != null) { + Network network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + + if (network.getGuestType() == Network.GuestType.Shared) { + if (zone == null) { + throw new InvalidParameterValueException("Invalid zone Id is given"); + } + // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' + if (zone.getNetworkType() == NetworkType.Advanced) { + if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { + _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); + } + return _networkMgr.allocatePortableIp(ipOwner, caller, zoneId, networkId, null); + } else { + throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone" + + " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled"); + } + } + } + } + + if (vpcId != null) { + Vpc vpc = _vpcDao.findById(vpcId); + if (vpc != null) { + throw new InvalidParameterValueException("Invalid vpc id is given"); + } + } + + _accountMgr.checkAccess(caller, null, false, ipOwner); + + return _networkMgr.allocatePortableIp(ipOwner, caller, zoneId, null, null); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RELEASE, eventDescription = "disassociating portable Ip", async = true) + public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + return releaseIpAddressInternal(ipAddressId); } @Override @@ -810,9 +835,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } @Override - @DB @ActionEvent(eventType = EventTypes.EVENT_NET_IP_RELEASE, eventDescription = "disassociating Ip", async = true) public boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + return releaseIpAddressInternal(ipAddressId); + } + + @DB + private boolean releaseIpAddressInternal(long ipAddressId) throws InsufficientAddressCapacityException { Long userId = UserContext.current().getCallerUserId(); Account caller = UserContext.current().getCaller(); @@ -851,6 +880,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { boolean success = _networkMgr.disassociatePublicIpAddress(ipAddressId, userId, caller); if (success) { + if (!ipVO.isPortable()) { + return success; + } Long networkId = ipVO.getAssociatedWithNetworkId(); if (networkId != null) { Network guestNetwork = getNetwork(networkId); @@ -867,7 +899,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { return success; } - @Override @DB public Network getNetwork(long id) { diff --git a/server/src/com/cloud/network/addr/PublicIp.java b/server/src/com/cloud/network/addr/PublicIp.java index c753b4927c8..b18c6912003 100644 --- a/server/src/com/cloud/network/addr/PublicIp.java +++ b/server/src/com/cloud/network/addr/PublicIp.java @@ -220,6 +220,15 @@ public class PublicIp implements PublicIpAddress { return _addr.getVmIp(); } + @Override + public boolean isPortable() { + return _addr.isPortable(); + } + + public void setPortable(boolean portable) { + _addr.setPortable(portable); + } + public Long getIpMacAddress() { return _addr.getMacAddress(); } diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 8021e6f0074..19166787e9b 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -47,7 +47,9 @@ import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; +import com.cloud.network.NetworkMigrationResponder; import com.cloud.network.NetworkModel; +import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; @@ -85,9 +87,13 @@ import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; +import com.cloud.vm.NicVO; import com.cloud.vm.ReservationContext; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.UserVmDao; @@ -108,10 +114,12 @@ import java.util.Set; @Local(value = {NetworkElement.class, FirewallServiceProvider.class, DhcpServiceProvider.class, UserDataServiceProvider.class, StaticNatServiceProvider.class, LoadBalancingServiceProvider.class, - PortForwardingServiceProvider.class, IpDeployer.class, RemoteAccessVPNServiceProvider.class} ) + PortForwardingServiceProvider.class, IpDeployer.class, + RemoteAccessVPNServiceProvider.class, NetworkMigrationResponder.class} ) public class VirtualRouterElement extends AdapterBase implements VirtualRouterElementService, DhcpServiceProvider, UserDataServiceProvider, SourceNatServiceProvider, StaticNatServiceProvider, FirewallServiceProvider, - LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer { + LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, + NetworkMigrationResponder { private static final Logger s_logger = Logger.getLogger(VirtualRouterElement.class); protected static final Map> capabilities = setCapabilities(); @@ -130,6 +138,8 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl ConfigurationManager _configMgr; @Inject RulesManager _rulesMgr; + @Inject + UserVmManager _userVmMgr; @Inject UserVmDao _userVmDao; @@ -1024,7 +1034,6 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl // TODO Auto-generated method stub return null; } - private boolean canHandleLbRules(List rules) { Map lbCaps = this.getCapabilities().get(Service.Lb); if (!lbCaps.isEmpty()) { @@ -1039,5 +1048,60 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } } return true; + } + + @Override + public boolean prepareMigration(NicProfile nic, Network network, + VirtualMachineProfile vm, + DeployDestination dest, ReservationContext context) { + if (nic.getBroadcastType() != Networks.BroadcastDomainType.Pvlan) { + return true; + } + if (vm.getType() == Type.DomainRouter) { + assert vm instanceof DomainRouterVO; + DomainRouterVO router = (DomainRouterVO)vm.getVirtualMachine(); + _routerMgr.setupDhcpForPvlan(false, router, router.getHostId(), nic); + } else if (vm.getType() == Type.User){ + assert vm instanceof UserVmVO; + UserVmVO userVm = (UserVmVO)vm.getVirtualMachine(); + _userVmMgr.setupVmForPvlan(false, userVm.getHostId(), nic); + } + return true; + } + + @Override + public void rollbackMigration(NicProfile nic, Network network, + VirtualMachineProfile vm, + ReservationContext src, ReservationContext dst) { + if (nic.getBroadcastType() != Networks.BroadcastDomainType.Pvlan) { + return; + } + if (vm.getType() == Type.DomainRouter) { + assert vm instanceof DomainRouterVO; + DomainRouterVO router = (DomainRouterVO)vm.getVirtualMachine(); + _routerMgr.setupDhcpForPvlan(true, router, router.getHostId(), nic); + } else if (vm.getType() == Type.User){ + assert vm instanceof UserVmVO; + UserVmVO userVm = (UserVmVO)vm.getVirtualMachine(); + _userVmMgr.setupVmForPvlan(true, userVm.getHostId(), nic); + } + } + + @Override + public void commitMigration(NicProfile nic, Network network, + VirtualMachineProfile vm, + ReservationContext src, ReservationContext dst) { + if (nic.getBroadcastType() != Networks.BroadcastDomainType.Pvlan) { + return; + } + if (vm.getType() == Type.DomainRouter) { + assert vm instanceof DomainRouterVO; + DomainRouterVO router = (DomainRouterVO)vm.getVirtualMachine(); + _routerMgr.setupDhcpForPvlan(true, router, router.getHostId(), nic); + } else if (vm.getType() == Type.User){ + assert vm instanceof UserVmVO; + UserVmVO userVm = (UserVmVO)vm.getVirtualMachine(); + _userVmMgr.setupVmForPvlan(true, userVm.getHostId(), nic); + } } } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 520dd763667..0118ca534e1 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -1902,6 +1902,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements String name = cmd.getLoadBalancerRuleName(); String keyword = cmd.getKeyword(); Long instanceId = cmd.getVirtualMachineId(); + Long networkId = cmd.getNetworkId(); Map tags = cmd.getTags(); Account caller = UserContext.current().getCaller(); @@ -1922,6 +1923,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); + sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); if (instanceId != null) { SearchBuilder lbVMSearch = _lb2VmMapDao.createSearchBuilder(); @@ -1979,6 +1981,10 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (zoneId != null) { sc.setJoinParameters("ipSearch", "zoneId", zoneId); } + + if (networkId != null) { + sc.setParameters("networkId", networkId); + } if (tags != null && !tags.isEmpty()) { int count = 0; diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index 9852c47dc85..72fddf4f87d 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -33,7 +33,6 @@ import com.cloud.user.User; import com.cloud.uservm.UserVm; import com.cloud.utils.component.Manager; import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; import com.cloud.vm.VirtualMachineProfile; @@ -113,4 +112,5 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA boolean removeDhcpSupportForSubnet(Network network, List routers) throws ResourceUnavailableException; + boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Long hostId, NicProfile nic); } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index f5f99ede6fb..4e3b90383df 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2224,8 +2224,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return dhcpRange; } - private boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Nic nic) { - if (!nic.getBroadcastUri().getScheme().equals("pvlan")) { + @Override + public boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Long hostId, NicProfile nic) { + if (!nic.getBroadCastUri().getScheme().equals("pvlan")) { return false; } String op = "add"; @@ -2234,15 +2235,22 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } Network network = _networkDao.findById(nic.getNetworkId()); String networkTag = _networkModel.getNetworkTag(router.getHypervisorType(), network); - PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, nic.getBroadcastUri(), networkTag, router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); - Commands cmds = new Commands(cmd); + PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, nic.getBroadCastUri(), networkTag, router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); // In fact we send command to the host of router, we're not programming router but the host + Answer answer = null; try { - sendCommandsToRouter(router, cmds); + answer = _agentMgr.send(hostId, cmd); + } catch (OperationTimedoutException e) { + s_logger.warn("Timed Out", e); + return false; } catch (AgentUnavailableException e) { s_logger.warn("Agent Unavailable ", e); return false; } + + if (answer == null || !answer.getResult()) { + return false; + } return true; } @@ -2564,7 +2572,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (network.getTrafficType() == TrafficType.Guest) { guestNetworks.add(network); if (nic.getBroadcastUri().getScheme().equals("pvlan")) { - result = setupDhcpForPvlan(true, router, nic); + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 0, false, "pvlan-nic"); + result = setupDhcpForPvlan(true, router, router.getHostId(), nicProfile); } } } @@ -2601,8 +2610,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V List routerNics = _nicDao.listByVmId(profile.getId()); for (Nic nic : routerNics) { Network network = _networkModel.getNetwork(nic.getNetworkId()); - if (network.getTrafficType() == TrafficType.Guest && nic.getBroadcastUri().getScheme().equals("pvlan")) { - setupDhcpForPvlan(false, domR, nic); + if (network.getTrafficType() == TrafficType.Guest && nic.getBroadcastUri() != null && nic.getBroadcastUri().getScheme().equals("pvlan")) { + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 0, false, "pvlan-nic"); + setupDhcpForPvlan(false, domR, domR.getHostId(), nicProfile); } } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index c9b47b44bab..883455377f4 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -491,6 +491,49 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return false; } performedIpAssoc = true; + } else if (ipAddress.isPortable()) { + s_logger.info("Portable IP " + ipAddress.getUuid() + " is not associated with the network, so" + + "associate IP with the network " + networkId); + try { + // check if StaticNat service is enabled in the network + _networkModel.checkIpForService(ipAddress, Service.StaticNat, networkId); + + // associate portable IP to vpc, if network is part of VPC + if (network.getVpcId() != null) { + _vpcMgr.associateIPToVpc(ipId, network.getVpcId()); + } + + // associate portable IP with guest network + _networkMgr.associatePortableIPToGuestNetwork(ipId, networkId, false); + } catch (Exception e) { + s_logger.warn("Failed to associate portable id=" + ipId + " to network id=" + networkId + " as " + + "a part of enable static nat"); + return false; + } + performedIpAssoc = true; + } + } else if (ipAddress.getAssociatedWithNetworkId() != networkId) { + if (ipAddress.isPortable()) { + // check if destination network has StaticNat service enabled + _networkModel.checkIpForService(ipAddress, Service.StaticNat, networkId); + + // check if portable IP can be transferred across the networks + if (_networkMgr.isPortableIpTransferableFromNetwork(ipId, ipAddress.getAssociatedWithNetworkId() )) { + try { + _networkMgr.transferPortableIP(ipId, ipAddress.getAssociatedWithNetworkId(), networkId); + } catch (Exception e) { + s_logger.warn("Failed to associate portable id=" + ipId + " to network id=" + networkId + " as " + + "a part of enable static nat"); + return false; + } + } else { + throw new InvalidParameterValueException("Portable IP: " + ipId + " has associated services" + + "in network " + ipAddress.getAssociatedWithNetworkId() + " so can not be transferred to " + + " network " + networkId); + } + } else { + throw new InvalidParameterValueException("Invalid network Id=" + networkId + ". IP is associated with" + + " a different network than passed network id"); } } else { _networkModel.checkIpForService(ipAddress, Service.StaticNat, null); diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 4d5d98192fa..2b02a888de9 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -342,9 +342,7 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ //Check ofr valid action Allow/Deny if(action != null){ - try { - NetworkACLItem.Action.valueOf(action); - } catch (IllegalArgumentException ex) { + if(!("Allow".equalsIgnoreCase(action) || "Deny".equalsIgnoreCase(action))){ throw new InvalidParameterValueException("Invalid action. Allowed actions are Allow and Deny"); } } diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 062743b23af..9e7bb13b867 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -226,10 +226,10 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc } @Override @DB - public void destroyRemoteAccessVpn(long ipId, Account caller) throws ResourceUnavailableException { + public void destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException { RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId); if (vpn == null) { - s_logger.debug("vpn id=" + ipId + " does not exists "); + s_logger.debug("there are no Remote access vpns for public ip address id=" + ipId); return; } diff --git a/server/src/com/cloud/resource/DiscovererBase.java b/server/src/com/cloud/resource/DiscovererBase.java index b7c5b6f58de..0c9dd2551e5 100644 --- a/server/src/com/cloud/resource/DiscovererBase.java +++ b/server/src/com/cloud/resource/DiscovererBase.java @@ -129,6 +129,7 @@ public abstract class DiscovererBase extends AdapterBase implements Discoverer { params.put("max.template.iso.size", _configDao.getValue(Config.MaxTemplateAndIsoSize.toString())); params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString())); params.put(Config.XenMaxNics.toString().toLowerCase(), _configDao.getValue(Config.XenMaxNics.toString())); + params.put(Config.XenHeartBeatInterval.toString().toLowerCase(), _configDao.getValue(Config.XenHeartBeatInterval.toString())); return params; } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index e25cfbb89c0..837fdfb6477 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -484,7 +484,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, result.add(cluster); ClusterDetailsVO cluster_detail_cpu = new ClusterDetailsVO(clusterId, "cpuOvercommitRatio", Float.toString(cmd.getCpuOvercommitRatio())); - ClusterDetailsVO cluster_detail_ram = new ClusterDetailsVO(clusterId, "memoryOvercommitRatio", Float.toString(cmd.getMemoryOvercommitRaito())); + ClusterDetailsVO cluster_detail_ram = new ClusterDetailsVO(clusterId, "memoryOvercommitRatio", Float.toString(cmd.getMemoryOvercommitRatio())); _clusterDetailsDao.persist(cluster_detail_cpu); _clusterDetailsDao.persist(cluster_detail_ram); @@ -507,8 +507,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, _clusterDetailsDao.persist(cluster_detail_cpu); } - if (cmd.getMemoryOvercommitRaito().compareTo(1f) > 0) { - cluster_detail_ram = new ClusterDetailsVO(clusterId, "memoryOvercommitRatio", Float.toString(cmd.getMemoryOvercommitRaito())); + + if(cmd.getMemoryOvercommitRatio().compareTo(1f) > 0) { + cluster_detail_ram = new ClusterDetailsVO(clusterId, "memoryOvercommitRatio", Float.toString(cmd.getMemoryOvercommitRatio())); _clusterDetailsDao.persist(cluster_detail_ram); } diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 240464e4938..969bc6557e1 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -19,6 +19,11 @@ package com.cloud.server; import java.util.Date; import java.util.List; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; +import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.event.EventVO; @@ -100,4 +105,5 @@ public interface ManagementServer extends ManagementService, PluggableService { void resetEncryptionKeyIV(); public void enableAdminUser(String password); + } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 17f87a58774..95ef6f4ad8f 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -17,11 +17,7 @@ package com.cloud.server; import java.lang.reflect.Field; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.URI; import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; @@ -29,10 +25,8 @@ import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -43,12 +37,20 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.exception.*; +import com.cloud.vm.*; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ApiConstants; + +import com.cloud.event.ActionEventUtils; +import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; +import org.apache.cloudstack.api.command.admin.region.*; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd; import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd; import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd; @@ -122,9 +124,6 @@ import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; -import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; -import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; -import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.ListAlertsCmd; @@ -155,13 +154,7 @@ import org.apache.cloudstack.api.command.admin.storage.PreparePrimaryStorageForM import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd; import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; -import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; -import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; -import org.apache.cloudstack.api.command.admin.systemvm.MigrateSystemVMCmd; -import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; -import org.apache.cloudstack.api.command.admin.systemvm.StartSystemVMCmd; -import org.apache.cloudstack.api.command.admin.systemvm.StopSystemVmCmd; -import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.*; import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; import org.apache.cloudstack.api.command.admin.usage.AddTrafficMonitorCmd; import org.apache.cloudstack.api.command.admin.usage.AddTrafficTypeCmd; @@ -281,8 +274,6 @@ import org.apache.cloudstack.api.command.user.nat.DeleteIpForwardingRuleCmd; import org.apache.cloudstack.api.command.user.nat.DisableStaticNatCmd; import org.apache.cloudstack.api.command.user.nat.EnableStaticNatCmd; import org.apache.cloudstack.api.command.user.nat.ListIpForwardingRulesCmd; -import org.apache.cloudstack.api.command.user.network.*; - import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; @@ -404,14 +395,10 @@ import org.apache.cloudstack.api.command.user.vpn.RemoveVpnUserCmd; import org.apache.cloudstack.api.command.user.vpn.ResetVpnConnectionCmd; import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; -import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; @@ -463,16 +450,9 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.exception.StorageUnavailableException; import com.cloud.ha.HighAvailabilityManager; import com.cloud.host.DetailVO; import com.cloud.host.Host; @@ -514,7 +494,6 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.Upload; -import com.cloud.storage.Upload.Mode; import com.cloud.storage.UploadVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; @@ -534,7 +513,6 @@ import com.cloud.storage.upload.UploadMonitor; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; -import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.SSHKeyPair; @@ -566,17 +544,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.MacAddress; import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SSHKeysHelper; -import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.InstanceGroupVO; -import com.cloud.vm.SecondaryStorageVmVO; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.InstanceGroupDao; @@ -586,84 +554,14 @@ import com.cloud.vm.dao.VMInstanceDao; import edu.emory.mathcs.backport.java.util.Arrays; import edu.emory.mathcs.backport.java.util.Collections; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; -import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; -import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; -import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd; -import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; -import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd; -import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; -import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; -import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; -import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; -import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; -import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; -import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; -import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; + import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; -import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; -import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; -import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; -import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; -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.vm.AssignVMCmd; -import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; -import org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd; -import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; -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.MarkDefaultZoneForAccountCmd; -import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; -import org.apache.cloudstack.api.command.user.account.AddAccountToProjectCmd; -import org.apache.cloudstack.api.command.user.account.DeleteAccountFromProjectCmd; -import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; -import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; -import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; -import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd; -import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; -import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd; -import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; -import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd; -import org.apache.cloudstack.api.command.user.event.ListEventTypesCmd; -import org.apache.cloudstack.api.command.user.event.ListEventsCmd; -import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd; -import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd; -import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; -import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; -import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; -import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; -import org.apache.cloudstack.api.command.user.region.ListRegionsCmd; -import org.apache.cloudstack.api.command.user.region.ha.gslb.*; -import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd; -import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd; -import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd; -import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; -import org.apache.cloudstack.api.command.user.tag.CreateTagsCmd; -import org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd; -import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; -import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; -import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; -import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd; + public class ManagementServerImpl extends ManagerBase implements ManagementServer { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); @@ -787,6 +685,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject ConfigurationServer _configServer; + @Inject + UserVmManager _userVmMgr; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AlertChecker")); @@ -1156,17 +1056,16 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO vm = _vmInstanceDao.findById(vmId); if (vm == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find the VM with specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find the VM with given id"); throw ex; } if (vm.getState() != State.Running) { if (s_logger.isDebugEnabled()) { - s_logger.debug("VM is not Running, unable to migrate the vm" + vm); + s_logger.debug("VM is not running, cannot migrate the vm" + vm); } - InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, unable to" + - " migrate the vm with specified id"); + InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, cannot " + + "migrate the vm with specified id"); ex.addProxyObject(vm, vmId, "vmId"); throw ex; } @@ -2921,9 +2820,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(ListAffinityGroupsCmd.class); cmdList.add(UpdateVMAffinityGroupCmd.class); cmdList.add(ListAffinityGroupTypesCmd.class); - cmdList.add(ListNetworkIsolationMethodsCmd.class); + cmdList.add(CreatePortableIpRangeCmd.class); + cmdList.add(DeletePortableIpRangeCmd.class); + cmdList.add(ListPortableIpRangesCmd.class); cmdList.add(ListDeploymentPlannersCmd.class); cmdList.add(ReleaseHostReservationCmd.class); + cmdList.add(ScaleSystemVMCmd.class); cmdList.add(AddResourceDetailCmd.class); cmdList.add(RemoveResourceDetailCmd.class); cmdList.add(ListResourceDetailsCmd.class); @@ -3993,10 +3895,28 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } + @Override + public VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException, ConcurrentOperationException { + + boolean result = _userVmMgr.upgradeVirtualMachine(cmd.getId(), cmd.getServiceOfferingId()); + if(result){ + VirtualMachine vm = _vmInstanceDao.findById(cmd.getId()); + return vm; + }else{ + return null; + } + } + + @Override public VirtualMachine upgradeSystemVM(UpgradeSystemVMCmd cmd) { Long systemVmId = cmd.getId(); Long serviceOfferingId = cmd.getServiceOfferingId(); + return upgradeStoppedSystemVm(systemVmId, serviceOfferingId); + + } + + private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOfferingId){ Account caller = UserContext.current().getCaller(); VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 9af53ee73f0..e98939dd7ad 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -721,19 +721,19 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK); + Account owner = (caller.getId() == ownerId) ? caller : _accountMgr + .getActiveAccountById(ownerId); volume.setPoolId(null); volume.setDataCenterId(zoneId); volume.setPodId(null); volume.setAccountId(ownerId); - volume.setDomainId(((caller == null) ? Domain.ROOT_DOMAIN : caller - .getDomainId())); long diskOfferingId = _diskOfferingDao.findByUniqueName( "Cloud.com-Custom").getId(); volume.setDiskOfferingId(diskOfferingId); // volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date()); - volume.setDomainId((caller == null) ? Domain.ROOT_DOMAIN : caller + volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner .getDomainId()); volume.setFormat(ImageFormat.valueOf(format)); volume = _volsDao.persist(volume); @@ -891,14 +891,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { size = diskOffering.getDiskSize(); } - if(displayVolumeEnabled == null){ - displayVolumeEnabled = true; - } else{ - if(!_accountMgr.isRootAdmin(caller.getType())){ - throw new PermissionDeniedException( "Cannot update parameter displayvolume, only admin permitted "); - } - } - if (!validateVolumeSizeRange(size)) {// convert size from mb to gb // for validation throw new InvalidParameterValueException( @@ -930,6 +922,14 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { _accountMgr.checkAccess(caller, null, true, snapshotCheck); } + if(displayVolumeEnabled == null){ + displayVolumeEnabled = true; + } else{ + if(!_accountMgr.isRootAdmin(caller.getType())){ + throw new PermissionDeniedException( "Cannot update parameter displayvolume, only admin permitted "); + } + } + // Check that the resource limit for primary storage won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.primary_storage, new Long(size)); diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 3e3616fa96b..eaf9d250cee 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -1218,6 +1218,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, accountNames.add(acct.getAccountName()); } } + + // also add the owner if not public + if (!template.isPublicTemplate()) { + Account templateOwner = _accountDao.findById(template.getAccountId()); + accountNames.add(templateOwner.getAccountName()); + } + return accountNames; } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 4088f64f58b..7421422d294 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -54,9 +54,12 @@ import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.vo.ControlledViewEntity; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; +import com.cloud.configuration.ResourceCountVO; import com.cloud.configuration.ResourceLimit; +import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceCountDao; +import com.cloud.configuration.dao.ResourceLimitDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterVnetDao; @@ -229,6 +232,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M private AccountGuestVlanMapDao _accountGuestVlanMapDao; @Inject private DataCenterVnetDao _dataCenterVnetDao; + @Inject + private ResourceLimitService _resourceLimitMgr; + @Inject + private ResourceLimitDao _resourceLimitDao; private List _userAuthenticators; List _userPasswordEncoders; @@ -621,7 +628,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M try { for (RemoteAccessVpnVO vpn : remoteAccessVpns) { - _remoteAccessVpnMgr.destroyRemoteAccessVpn(vpn.getServerAddressId(), caller); + _remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller); } } catch (ResourceUnavailableException ex) { s_logger.warn("Failed to cleanup remote access vpn resources as a part of account id=" + accountId + " cleanup due to Exception: ", ex); @@ -714,6 +721,16 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M int vlansReleased = _accountGuestVlanMapDao.removeByAccountId(accountId); s_logger.info("deleteAccount: Released " + vlansReleased + " dedicated guest vlan ranges from account " + accountId); + // Update resource count for this account and for parent domains. + List resourceCounts = _resourceCountDao.listByOwnerId(accountId, ResourceOwnerType.Account); + for (ResourceCountVO resourceCount : resourceCounts) { + _resourceLimitMgr.decrementResourceCount(accountId, resourceCount.getType(), resourceCount.getCount()); + } + + // Delete resource count and resource limits entries set for this account (if there are any). + _resourceCountDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account); + _resourceLimitDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account); + return true; } catch (Exception ex) { s_logger.warn("Failed to cleanup account " + account + " due to ", ex); diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index dbcbe4ee431..c451041d951 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -16,11 +16,13 @@ // under the License. package com.cloud.user; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; import javax.ejb.Local; import javax.inject.Inject; -import javax.naming.ConfigurationException; import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd; import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd; @@ -29,8 +31,10 @@ import org.apache.cloudstack.region.RegionManager; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.ResourceLimit; import com.cloud.configuration.dao.ResourceCountDao; +import com.cloud.configuration.dao.ResourceLimitDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -49,7 +53,6 @@ import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.user.dao.AccountDao; import com.cloud.utils.Pair; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; @@ -82,6 +85,8 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom private ProjectManager _projectMgr; @Inject private RegionManager _regionMgr; + @Inject + private ResourceLimitDao _resourceLimitDao; @Override public Domain getDomain(long domainId) { @@ -329,6 +334,10 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom List accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domainId); if (accountsForCleanup.isEmpty()) { deleteDomainSuccess = _domainDao.remove(domainId); + + // Delete resource count and resource limits entries set for this domain (if there are any). + _resourceCountDao.removeEntriesByOwner(domainId, ResourceOwnerType.Domain); + _resourceLimitDao.removeEntriesByOwner(domainId, ResourceOwnerType.Domain); } else { s_logger.debug("Can't delete the domain yet because it has " + accountsForCleanup.size() + "accounts that need a cleanup"); } diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index cc1fffd780b..4dcfb73e2a1 100755 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -22,9 +22,7 @@ import java.util.Map; import com.cloud.agent.api.VmStatsEntry; import com.cloud.api.query.vo.UserVmJoinVO; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.Criteria; import com.cloud.user.Account; @@ -94,4 +92,7 @@ public interface UserVmManager extends VirtualMachineGuru, UserVmServi Pair> startVirtualMachine(long vmId, Long hostId, Map additionalParams) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean upgradeVirtualMachine(Long id, Long serviceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; + + boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 63947e1ad55..a28da884e57 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -1076,11 +1076,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Override @ActionEvent(eventType = EventTypes.EVENT_VM_SCALE, eventDescription = "scaling Vm") - public boolean - upgradeVirtualMachine(ScaleVMCmd cmd) throws InvalidParameterValueException, ResourceAllocationException { + public UserVm + upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{ Long vmId = cmd.getId(); Long newServiceOfferingId = cmd.getServiceOfferingId(); + boolean result = upgradeVirtualMachine(vmId, newServiceOfferingId); + if(result){ + return _vmDao.findById(vmId); + }else{ + return null; + } + + } + + @Override + public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{ Account caller = UserContext.current().getCaller(); // Verify input parameters @@ -1147,9 +1158,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } return success; - } + @Override public HashMap getVirtualMachineStatistics(long hostId, String hostName, List vmIds) throws CloudRuntimeException { @@ -2355,6 +2366,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } else { // verify permissions _accountMgr.checkAccess(caller, null, true, owner, ag); + // Root admin has access to both VM and AG by default, but + // make sure the owner of these entities is same + if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) { + if (ag.getAccountId() != owner.getAccountId()) { + throw new PermissionDeniedException("Affinity Group " + ag + + " does not belong to the VM's account"); + } + } } } } @@ -2783,8 +2802,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use return true; } - private boolean setupVmForPvlan(boolean add, Long hostId, NicVO nic) { - if (!nic.getBroadcastUri().getScheme().equals("pvlan")) { + @Override + public boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic) { + if (!nic.getBroadCastUri().getScheme().equals("pvlan")) { return false; } String op = "add"; @@ -2795,7 +2815,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use Network network = _networkDao.findById(nic.getNetworkId()); Host host = _hostDao.findById(hostId); String networkTag = _networkModel.getNetworkTag(host.getHypervisorType(), network); - PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, nic.getBroadcastUri(), networkTag, nic.getMacAddress()); + PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, nic.getBroadCastUri(), networkTag, nic.getMacAddress()); Answer answer = null; try { answer = _agentMgr.send(hostId, cmd); @@ -2878,7 +2898,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // In vmware, we will be effecting pvlan settings in portgroups in StartCommand. if (profile.getHypervisorType() != HypervisorType.VMware) { if (nic.getBroadcastUri().getScheme().equals("pvlan")) { - if (!setupVmForPvlan(true, hostId, nic)) { + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 0, false, "pvlan-nic"); + if (!setupVmForPvlan(true, hostId, nicProfile)) { return false; } } @@ -3019,8 +3040,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); if (network.getTrafficType() == TrafficType.Guest) { - if (nic.getBroadcastUri().getScheme().equals("pvlan")) { - setupVmForPvlan(false, vm.getHostId(), nic); + if (nic.getBroadcastUri() != null && nic.getBroadcastUri().getScheme().equals("pvlan")) { + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 0, false, "pvlan-nic"); + setupVmForPvlan(false, vm.getHostId(), nicProfile); } } } @@ -3190,7 +3212,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (vm == null || vm.getRemoved() != null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to find a virtual machine with specified vmId"); - ex.addProxyObject(vm, vmId, "vmId"); throw ex; } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 79c85830b9b..5dde7113906 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -36,6 +36,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -253,6 +254,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac protected ResourceLimitService _resourceLimitMgr; @Inject protected RulesManager rulesMgr; + @Inject + protected AffinityGroupVMMapDao _affinityGroupVMMapDao; protected List _planners; public List getPlanners() { @@ -355,7 +358,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (s_logger.isDebugEnabled()) { - s_logger.debug("Allocaing disks for " + vm); + s_logger.debug("Allocating disks for " + vm); } if (template.getFormat() == ImageFormat.ISO) { @@ -666,6 +669,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } + protected boolean areAffinityGroupsAssociated(VirtualMachineProfile vmProfile) { + VirtualMachine vm = vmProfile.getVirtualMachine(); + long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); + + if (vmGroupCount > 0) { + return true; + } + return false; + } + @Override public T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { @@ -797,7 +810,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac reuseVolume = false; continue; } - throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); + throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, + DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile)); } if (dest != null) { @@ -810,8 +824,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac Long cluster_id = dest.getCluster().getId(); ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id,"cpuOvercommitRatio"); ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id,"memoryOvercommitRatio"); - vmProfile.setcpuOvercommitRatio(Float.parseFloat(cluster_detail_cpu.getValue())); - vmProfile.setramOvercommitRatio(Float.parseFloat(cluster_detail_ram.getValue())); + vmProfile.setCpuOvercommitRatio(Float.parseFloat(cluster_detail_cpu.getValue())); + vmProfile.setMemoryOvercommitRatio(Float.parseFloat(cluster_detail_ram.getValue())); try { if (!changeState(vm, Event.OperationRetry, destHostId, work, Step.Prepare)) { @@ -1400,6 +1414,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE; } + VirtualMachineProfile vmSrc = new VirtualMachineProfileImpl(vm); + for(NicProfile nic: _networkMgr.getNicProfiles(vm)){ + vmSrc.addNic(nic); + } + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); _networkMgr.prepareNicForMigration(profile, dest); this.volumeMgr.prepareForMigration(profile, dest); @@ -1425,6 +1444,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new AgentUnavailableException("Operation timed out", dstHostId); } finally { if (pfma == null) { + _networkMgr.rollbackNicForMigration(vmSrc, profile); work.setStep(Step.Done); _workDao.update(work.getId(), work); } @@ -1433,10 +1453,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac vm.setLastHostId(srcHostId); try { if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) { + _networkMgr.rollbackNicForMigration(vmSrc, profile); s_logger.info("Migration cancelled because state has changed: " + vm); throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm); } } catch (NoTransitionException e1) { + _networkMgr.rollbackNicForMigration(vmSrc, profile); s_logger.info("Migration cancelled because " + e1.getMessage()); throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage()); } @@ -1488,6 +1510,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } finally { if (!migrated) { s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); + _networkMgr.rollbackNicForMigration(vmSrc, profile); _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone " + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed. Please check logs."); @@ -1502,6 +1525,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (NoTransitionException e) { s_logger.warn(e.getMessage()); } + }else{ + _networkMgr.commitNicForMigration(vmSrc, profile); } work.setStep(Step.Done); diff --git a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java index c4e8822c0d8..033daf33422 100644 --- a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java @@ -23,7 +23,7 @@ import java.util.Map; import com.cloud.agent.api.to.DiskTO; -import com.cloud.agent.api.to.VolumeTO; + import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; @@ -40,7 +40,7 @@ import com.cloud.user.dao.AccountDao; * */ public class VirtualMachineProfileImpl implements VirtualMachineProfile { - + T _vm; ServiceOfferingVO _offering; VMTemplateVO _template; @@ -55,7 +55,7 @@ public class VirtualMachineProfileImpl implements Virtua Float memoryOvercommitRatio = 1.0f; VirtualMachine.Type _type; - + public VirtualMachineProfileImpl(T vm, VMTemplateVO template, ServiceOfferingVO offering, Account owner, Map params) { _vm = vm; _template = template; @@ -68,25 +68,25 @@ public class VirtualMachineProfileImpl implements Virtua if (vm != null) _type = vm.getType(); } - + public VirtualMachineProfileImpl(T vm) { this(vm, null, null, null, null); } - + public VirtualMachineProfileImpl(VirtualMachine.Type type) { _type = type; } - + @Override public String toString() { return _vm.toString(); } - + @Override public T getVirtualMachine() { return _vm; } - + @Override public ServiceOffering getServiceOffering() { if (_offering == null) { @@ -94,17 +94,17 @@ public class VirtualMachineProfileImpl implements Virtua } return _offering; } - + @Override public void setParameter(Param name, Object value) { _params.put(name, value); } - - @Override + + @Override public void setBootLoaderType(BootloaderType bootLoader) { this._bootloader = bootLoader; } - + @Override public VirtualMachineTemplate getTemplate() { if (_template == null && _vm != null) { @@ -112,7 +112,7 @@ public class VirtualMachineProfileImpl implements Virtua } return _template; } - + @Override public HypervisorType getHypervisorType() { return _vm.getHypervisorType(); @@ -132,7 +132,7 @@ public class VirtualMachineProfileImpl implements Virtua public long getId() { return _vm.getId(); } - + @Override public String getUuid() { return _vm.getUuid(); @@ -141,48 +141,48 @@ public class VirtualMachineProfileImpl implements Virtua public void setNics(List nics) { _nics = nics; } - + public void setDisks(List disks) { _disks = disks; } - + @Override public List getNics() { return _nics; } - + @Override public List getDisks() { return _disks; } - + @Override public void addNic(int index, NicProfile nic) { _nics.add(index, nic); } - + @Override public void addDisk(int index, DiskTO disk) { _disks.add(index, disk); } - + @Override public StringBuilder getBootArgsBuilder() { return _bootArgs; } - + @Override public void addBootArgs(String... args) { for (String arg : args) { _bootArgs.append(arg).append(" "); } } - + @Override public VirtualMachine.Type getType() { return _type; } - + @Override public Account getOwner() { if (_owner == null) { @@ -190,12 +190,12 @@ public class VirtualMachineProfileImpl implements Virtua } return _owner; } - + @Override public String getBootArgs() { return _bootArgs.toString(); } - + static ServiceOfferingDao s_offeringDao; static VMTemplateDao s_templateDao; static AccountDao s_accountDao; @@ -219,12 +219,12 @@ public class VirtualMachineProfileImpl implements Virtua public Object getParameter(Param name) { return _params.get(name); } - + @Override public String getHostName() { return _vm.getHostName(); } - + @Override public String getInstanceName() { return _vm.getInstanceName(); @@ -234,7 +234,7 @@ public class VirtualMachineProfileImpl implements Virtua public BootloaderType getBootLoaderType() { return this._bootloader; } - + @Override public Map getParameters() { return _params; @@ -244,24 +244,23 @@ public class VirtualMachineProfileImpl implements Virtua _offering = offering; } - public void setcpuOvercommitRatio(Float cpuOvercommitRatio){ - this.cpuOvercommitRatio= cpuOvercommitRatio; + public void setCpuOvercommitRatio(Float cpuOvercommitRatio) { + this.cpuOvercommitRatio = cpuOvercommitRatio; } - public void setramOvercommitRatio(Float memoryOvercommitRatio){ - this.memoryOvercommitRatio= memoryOvercommitRatio; + public void setMemoryOvercommitRatio(Float memoryOvercommitRatio) { + this.memoryOvercommitRatio = memoryOvercommitRatio; } + @Override - public Float getCpuOvercommitRatio(){ + public Float getCpuOvercommitRatio() { return this.cpuOvercommitRatio; } @Override - public Float getMemoryOvercommitRatio(){ + public Float getMemoryOvercommitRatio() { return this.memoryOvercommitRatio; } - - } diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index fc2cfcf8d95..efe18c3b375 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -36,6 +36,7 @@ import com.cloud.deploy.DeploymentPlanner; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; import com.cloud.network.security.SecurityGroup; import com.cloud.user.Account; @@ -332,6 +333,14 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro } else { // verify permissions _accountMgr.checkAccess(caller, null, true, owner, ag); + // Root admin has access to both VM and AG by default, but make sure the + // owner of these entities is same + if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) { + if (ag.getAccountId() != owner.getAccountId()) { + throw new PermissionDeniedException("Affinity Group " + ag + + " does not belong to the VM's account"); + } + } } } _affinityGroupVMMapDao.updateMap(vmId, affinityGroupIds); diff --git a/server/src/org/apache/cloudstack/region/PortableIpDao.java b/server/src/org/apache/cloudstack/region/PortableIpDao.java new file mode 100755 index 00000000000..9f5341fb6ec --- /dev/null +++ b/server/src/org/apache/cloudstack/region/PortableIpDao.java @@ -0,0 +1,39 @@ +// 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.region; + +import java.util.List; + +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; +import com.cloud.utils.db.GenericDao; + +public interface PortableIpDao extends GenericDao { + + List listByRegionId(int regionId); + + List listByRangeId(long rangeId); + + List listByRangeIdAndState(long rangeId, PortableIp.State state); + + List listByRegionIdAndState(int regionId, PortableIp.State state); + + PortableIpVO findByIpAddress(String ipAddress); + + void unassignIpAddress(long ipAddressId); +} diff --git a/server/src/org/apache/cloudstack/region/PortableIpDaoImpl.java b/server/src/org/apache/cloudstack/region/PortableIpDaoImpl.java new file mode 100755 index 00000000000..488761bc35f --- /dev/null +++ b/server/src/org/apache/cloudstack/region/PortableIpDaoImpl.java @@ -0,0 +1,131 @@ +// 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.region; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.springframework.stereotype.Component; + +import com.cloud.dc.AccountVlanMapVO; +import com.cloud.dc.PodVlanMapVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.utils.Pair; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; + +@Component +@Local(value={PortableIpDao.class}) +public class PortableIpDaoImpl extends GenericDaoBase implements PortableIpDao { + + private final SearchBuilder listByRegionIDSearch; + private final SearchBuilder listByRangeIDSearch; + private final SearchBuilder listByRangeIDAndStateSearch; + private final SearchBuilder listByRegionIDAndStateSearch; + private final SearchBuilder findByIpAddressSearch; + + public PortableIpDaoImpl() { + listByRegionIDSearch = createSearchBuilder(); + listByRegionIDSearch.and("regionId", listByRegionIDSearch.entity().getRegionId(), SearchCriteria.Op.EQ); + listByRegionIDSearch.done(); + + listByRangeIDSearch = createSearchBuilder(); + listByRangeIDSearch.and("rangeId", listByRangeIDSearch.entity().getRangeId(), SearchCriteria.Op.EQ); + listByRangeIDSearch.done(); + + listByRangeIDAndStateSearch = createSearchBuilder(); + listByRangeIDAndStateSearch.and("rangeId", listByRangeIDAndStateSearch.entity().getRangeId(), SearchCriteria.Op.EQ); + listByRangeIDAndStateSearch.and("state", listByRangeIDAndStateSearch.entity().getState(), SearchCriteria.Op.EQ); + listByRangeIDAndStateSearch.done(); + + listByRegionIDAndStateSearch = createSearchBuilder(); + listByRegionIDAndStateSearch.and("regionId", listByRegionIDAndStateSearch.entity().getRangeId(), SearchCriteria.Op.EQ); + listByRegionIDAndStateSearch.and("state", listByRegionIDAndStateSearch.entity().getState(), SearchCriteria.Op.EQ); + listByRegionIDAndStateSearch.done(); + + findByIpAddressSearch = createSearchBuilder(); + findByIpAddressSearch.and("address", findByIpAddressSearch.entity().getAddress(), SearchCriteria.Op.EQ); + findByIpAddressSearch.done(); + } + + @Override + public List listByRegionId(int regionIdId) { + SearchCriteria sc = listByRegionIDSearch.create(); + sc.setParameters("regionId", regionIdId); + return listBy(sc); + } + + @Override + public List listByRangeId(long rangeId) { + SearchCriteria sc = listByRangeIDSearch.create(); + sc.setParameters("rangeId", rangeId); + return listBy(sc); + } + + @Override + public List listByRangeIdAndState(long rangeId, PortableIp.State state) { + SearchCriteria sc = listByRangeIDAndStateSearch.create(); + sc.setParameters("rangeId", rangeId); + sc.setParameters("state", state); + return listBy(sc); + } + + @Override + public List listByRegionIdAndState(int regionId, PortableIp.State state) { + SearchCriteria sc = listByRegionIDAndStateSearch.create(); + sc.setParameters("regionId", regionId); + sc.setParameters("state", state); + return listBy(sc); + } + + @Override + public PortableIpVO findByIpAddress(String ipAddress) { + SearchCriteria sc = findByIpAddressSearch.create(); + sc.setParameters("address", ipAddress); + return findOneBy(sc); + } + + @Override + public void unassignIpAddress(long ipAddressId) { + PortableIpVO address = createForUpdate(); + address.setAllocatedToAccountId(null); + address.setAllocatedInDomainId(null); + address.setAllocatedTime(null); + address.setState(PortableIp.State.Free); + address.setAssociatedWithNetworkId(null); + address.setAssociatedDataCenterId(null); + address.setAssociatedWithVpcId(null); + address.setPhysicalNetworkId(null); + update(ipAddressId, address); + } +} diff --git a/server/src/org/apache/cloudstack/region/PortableIpRangeDao.java b/server/src/org/apache/cloudstack/region/PortableIpRangeDao.java new file mode 100755 index 00000000000..85da6c0a87e --- /dev/null +++ b/server/src/org/apache/cloudstack/region/PortableIpRangeDao.java @@ -0,0 +1,30 @@ +// 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.region; + +import java.util.List; + +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; +import com.cloud.utils.db.GenericDao; + +public interface PortableIpRangeDao extends GenericDao { + + List listByRegionId(int regionId); + +} diff --git a/server/src/org/apache/cloudstack/region/PortableIpRangeDaoImpl.java b/server/src/org/apache/cloudstack/region/PortableIpRangeDaoImpl.java new file mode 100755 index 00000000000..496c9e6da40 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/PortableIpRangeDaoImpl.java @@ -0,0 +1,65 @@ +// 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.region; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.springframework.stereotype.Component; + +import com.cloud.dc.AccountVlanMapVO; +import com.cloud.dc.PodVlanMapVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.utils.Pair; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; + +@Component +@Local(value={PortableIpRangeDao.class}) +public class PortableIpRangeDaoImpl extends GenericDaoBase implements PortableIpRangeDao { + + private final SearchBuilder listByRegionIDSearch; + + public PortableIpRangeDaoImpl() { + listByRegionIDSearch = createSearchBuilder(); + listByRegionIDSearch.and("regionId", listByRegionIDSearch.entity().getRegionId(), SearchCriteria.Op.EQ); + listByRegionIDSearch.done(); + } + + @Override + public List listByRegionId(int regionIdId) { + SearchCriteria sc = listByRegionIDSearch.create(); + sc.setParameters("regionId", regionIdId); + return listBy(sc); + } +} diff --git a/server/src/org/apache/cloudstack/region/PortableIpRangeVO.java b/server/src/org/apache/cloudstack/region/PortableIpRangeVO.java new file mode 100644 index 00000000000..933fcc3d1d7 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/PortableIpRangeVO.java @@ -0,0 +1,119 @@ +// 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.region; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +@Entity +@Table(name="portable_ip_range") +public class PortableIpRangeVO implements PortableIpRange { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + Long id; + + @Column(name="uuid") + String uuid; + + @Column(name="region_id") + int regionId; + + @Column(name="vlan_id") + String vlan; + + @Column(name="gateway") + String gateway; + + @Column(name="netmask") + String netmask; + + @Column(name="start_ip") + String startIp; + + @Column(name="end_ip") + String endIp; + + public PortableIpRangeVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public PortableIpRangeVO(int regionId, String vlan, String gateway, String netmask, String startIp, String endIp) { + this.uuid = UUID.randomUUID().toString(); + this.regionId =regionId; + this.vlan = vlan; + this.gateway = gateway; + this.netmask = netmask; + this.startIp = startIp; + this.endIp = endIp; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return this.uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public String getVlanTag() { + return vlan; + } + + public void setVlanTag(String vlan) { + this.vlan = vlan; + } + + @Override + public String getGateway() { + return gateway; + } + + @Override + public String getNetmask() { + return netmask; + } + + @Override + public int getRegionId() { + return regionId; + } + + @Override + public String getIpRange() { + return startIp + "-" + endIp; + } +} diff --git a/server/src/org/apache/cloudstack/region/PortableIpVO.java b/server/src/org/apache/cloudstack/region/PortableIpVO.java new file mode 100644 index 00000000000..9a630094001 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/PortableIpVO.java @@ -0,0 +1,222 @@ +// 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.region; + +import java.util.Date; +import java.util.UUID; + +import javax.persistence.*; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +@Entity +@Table(name="portable_ip_address") +public class PortableIpVO implements PortableIp { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + Long id; + + @Column(name="region_id") + int regionId; + + @Column(name="allocated") + @Temporal(value=TemporalType.TIMESTAMP) + private Date allocatedTime; + + @Column(name="account_id") + private Long allocatedToAccountId = null; + + @Column(name="domain_id") + private Long allocatedInDomainId = null; + + @Column(name="state") + private State state; + + @Column(name="vlan") + String vlan; + + @Column(name="gateway") + String gateway; + + @Column(name="netmask") + String netmask; + + @Column(name="portable_ip_address") + String address; + + @Column(name="portable_ip_range_id") + private long rangeId; + + @Column(name="physical_network_id") + private Long physicalNetworkId; + + @Column(name="data_center_id") + private Long dataCenterId; + + @Column(name="network_id") + private Long networkId; + + @Column(name="vpc_id") + private Long vpcId; + + public PortableIpVO() { + + } + + public PortableIpVO(int regionId, Long rangeId, String vlan, String gateway, String netmask, String address) { + this.regionId =regionId; + this.vlan = vlan; + this.gateway = gateway; + this.netmask = netmask; + this.address = address; + state = State.Free; + this.rangeId = rangeId; + } + + @Override + public long getId() { + return id; + } + + @Override + public Long getAllocatedToAccountId() { + return allocatedToAccountId; + } + + public void setAllocatedToAccountId(Long accountId) { + this.allocatedToAccountId = accountId; + } + + @Override + public Long getAllocatedInDomainId() { + return allocatedInDomainId; + } + + public void setAllocatedInDomainId(Long domainId) { + this.allocatedInDomainId = domainId; + } + + @Override + public Date getAllocatedTime() { + return allocatedTime; + } + + public void setAllocatedTime(Date date) { + this.allocatedTime = date; + } + + @Override + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + @Override + public int getRegionId() { + return regionId; + } + + public void setRegionId(int regionId) { + this.regionId = regionId; + } + + @Override + public Long getAssociatedDataCenterId() { + return dataCenterId; + } + + public void setAssociatedDataCenterId(Long datacenterId) { + this.dataCenterId = datacenterId; + } + + @Override + public Long getAssociatedWithNetworkId() { + return networkId; + } + + public void setAssociatedWithNetworkId(Long networkId) { + this.networkId = networkId; + } + + @Override + public Long getAssociatedWithVpcId() { + return vpcId; + } + + public void setAssociatedWithVpcId(Long vpcId) { + this.vpcId = vpcId; + } + + @Override + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public void setPhysicalNetworkId(Long physicalNetworkId) { + this.physicalNetworkId = physicalNetworkId; + } + + @Override + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + @Override + public String getVlan() { + return vlan; + } + + public void setVlan(String vlan) { + this.vlan = vlan; + } + + @Override + public String getNetmask() { + return netmask; + } + + public void setNetmask(String netmask) { + this.netmask = netmask; + } + + @Override + public String getGateway() { + return gateway; + } + + public void setGateay(String gateway) { + this.gateway = gateway; + } + + Long getRangeId() { + return rangeId; + } + + public void setRangeId(Long rangeId) { + this.rangeId = rangeId; + } +} diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 87431ab54ab..e5d34fbacc7 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -75,7 +75,6 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.*; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; -import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; @@ -89,7 +88,6 @@ import java.util.List; import java.util.Map; import java.util.Set; - @Component @Local(value = { NetworkManager.class, NetworkService.class }) public class MockNetworkManagerImpl extends ManagerBase implements NetworkManager, NetworkService { @@ -106,6 +104,27 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } + @Override + public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException { + return null;// TODO Auto-generated method stub + } + + @Override + public IPAddressVO disassociatePortableIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException { + return null; // TODO Auto-generated method stub + } + + @Override + public boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId) { + return false; + } + + @Override + public void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException { + + } + @Override public boolean releaseIpAddress(long ipAddressId) { // TODO Auto-generated method stub @@ -258,12 +277,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - @Override - public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { - // TODO Auto-generated method stub - - } - @Override public boolean destroyNetwork(long networkId, ReservationContext context) { // TODO Auto-generated method stub @@ -861,6 +874,23 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } + @Override + public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) + throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { + return null;// TODO Auto-generated method stub + } + + @Override + public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, + InsufficientAddressCapacityException, ConcurrentOperationException { + return null; + } + + @Override + public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + return false;// TODO Auto-generated method stub + } + @Override public boolean isSecondaryIpSetForNic(long nicId) { // TODO Auto-generated method stub @@ -930,4 +960,27 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException { return null; //To change body of implemented methods use File | Settings | File Templates. } + + @Override + public void prepareNicForMigration( + VirtualMachineProfile vm, + DeployDestination dest) { + // TODO Auto-generated method stub + + } + + @Override + public void commitNicForMigration( + VirtualMachineProfile src, + VirtualMachineProfile dst) { + // TODO Auto-generated method stub + + } + + @Override + public void rollbackNicForMigration( + VirtualMachineProfile src, + VirtualMachineProfile dst) { + // TODO Auto-generated method stub + } } diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java index a88625a42fa..448a5dd9a21 100644 --- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java +++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java @@ -409,8 +409,8 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, } @Override - public boolean upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { - return false; //To change body of implemented methods use File | Settings | File Templates. + public UserVm upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + return null; //To change body of implemented methods use File | Settings | File Templates. } @@ -420,6 +420,11 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, return null; } + @Override + public boolean upgradeVirtualMachine(Long id, Long serviceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + @Override public void prepareStop(VirtualMachineProfile profile) { // TODO Auto-generated method stub @@ -450,4 +455,10 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, // TODO Auto-generated method stub return null; } + + @Override + public boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic) { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java index ba18fa1c11d..21b3590282d 100755 --- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -16,6 +16,44 @@ // under the License. package com.cloud.vpc; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import javax.naming.NamingException; + +import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; +import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; +import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; +import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; +import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd; +import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd; +import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd; +import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd; +import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd; +import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd; +import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd; +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.region.CreatePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.DeletePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.ListPortableIpRangesCmd; +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; +import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; +import org.springframework.stereotype.Component; + import com.cloud.configuration.Configuration; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.ConfigurationService; @@ -381,6 +419,26 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu return false; } + @Override + public PortableIpRange createPortableIpRange(CreatePortableIpRangeCmd cmd) throws ConcurrentOperationException { + return null;// TODO Auto-generated method stub + } + + @Override + public boolean deletePortableIpRange(DeletePortableIpRangeCmd cmd) { + return false;// TODO Auto-generated method stub + } + + @Override + public List listPortableIpRanges(ListPortableIpRangesCmd cmd) { + return null;// TODO Auto-generated method stub + } + + @Override + public List listPortableIps(long id) { + return null;// TODO Auto-generated method stub + } + /* (non-Javadoc) * @see com.cloud.utils.component.Manager#configure(java.lang.String, java.util.Map) */ @@ -431,7 +489,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu */ @Override public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, - boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) { + boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner, Map details) { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 3e6a08bdbf3..7129273a50c 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -63,7 +63,6 @@ import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.network.PublicIpAddress; import com.cloud.network.addr.PublicIp; -import com.cloud.network.dao.AccountGuestVlanMapVO; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; @@ -198,13 +197,36 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } + @Override + public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) + throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { + return null;// TODO Auto-generated method stub + } + @Override + public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, + InsufficientAddressCapacityException, ConcurrentOperationException { + return null; + } + @Override + public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + return false;// TODO Auto-generated method stub + } + @Override + public boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId) { + return false; + } + + @Override + public void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException, + InsufficientAddressCapacityException, ConcurrentOperationException { + } /* (non-Javadoc) - * @see com.cloud.network.NetworkService#releaseIpAddress(long) - */ + * @see com.cloud.network.NetworkService#releaseIpAddress(long) + */ @Override public boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { // TODO Auto-generated method stub @@ -823,18 +845,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#prepareNicForMigration(com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DeployDestination) - */ - @Override - public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { - // TODO Auto-generated method stub - - } - - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#shutdownNetwork(long, com.cloud.vm.ReservationContext, boolean) @@ -1112,13 +1122,20 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } + @Override + public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException { + return null;// TODO Auto-generated method stub + } - + @Override + public IPAddressVO disassociatePortableIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException { + return null;// TODO Auto-generated method stub + } /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#setupDns(com.cloud.network.Network, com.cloud.network.Network.Provider) - */ + * @see com.cloud.network.NetworkManager#setupDns(com.cloud.network.Network, com.cloud.network.Network.Provider) + */ @Override public boolean setupDns(Network network, Provider provider) { // TODO Auto-generated method stub @@ -1442,4 +1459,40 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } + + + + @Override + public void prepareNicForMigration( + VirtualMachineProfile vm, + DeployDestination dest) { + // TODO Auto-generated method stub + + } + + + + + + @Override + public void commitNicForMigration( + VirtualMachineProfile src, + VirtualMachineProfile dst) { + // TODO Auto-generated method stub + + } + + + + + + @Override + public void rollbackNicForMigration( + VirtualMachineProfile src, + VirtualMachineProfile dst) { + // TODO Auto-generated method stub + + } + + } diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index 8d502112e8d..f325c4af077 100644 --- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -420,4 +420,10 @@ VpcVirtualNetworkApplianceService { return null; } + @Override + public boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Long hostId, + NicProfile nic) { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java index f5cf4422c50..df15ceb860a 100644 --- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java +++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java @@ -19,6 +19,12 @@ package org.apache.cloudstack.networkoffering; import java.io.IOException; + +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.region.PortableIpDaoImpl; +import org.apache.cloudstack.region.dao.RegionDaoImpl; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; +import org.apache.cloudstack.test.utils.SpringUtils; import org.mockito.Mockito; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -29,11 +35,7 @@ import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; -import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; -import org.apache.cloudstack.test.utils.SpringUtils; - import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; import com.cloud.api.query.dao.UserAccountJoinDaoImpl; @@ -92,6 +94,7 @@ import com.cloud.projects.ProjectManager; import com.cloud.server.ConfigurationServer; import com.cloud.server.ManagementService; import com.cloud.service.dao.ServiceOfferingDaoImpl; +import com.cloud.service.dao.ServiceOfferingDetailsDaoImpl; import com.cloud.storage.dao.DiskOfferingDaoImpl; import com.cloud.storage.dao.S3DaoImpl; import com.cloud.storage.dao.SnapshotDaoImpl; @@ -114,6 +117,7 @@ import com.cloud.vm.dao.NicDaoImpl; import com.cloud.vm.dao.NicSecondaryIpDaoImpl; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDaoImpl; +import org.apache.cloudstack.region.PortableIpRangeDaoImpl; @Configuration @ComponentScan(basePackageClasses={ @@ -123,6 +127,7 @@ import com.cloud.vm.dao.VMInstanceDaoImpl; DomainDaoImpl.class, SwiftDaoImpl.class, ServiceOfferingDaoImpl.class, + ServiceOfferingDetailsDaoImpl.class, VlanDaoImpl.class, IPAddressDaoImpl.class, ResourceTagsDaoImpl.class, @@ -162,6 +167,9 @@ import com.cloud.vm.dao.VMInstanceDaoImpl; NetworkServiceMapDaoImpl.class, PrimaryDataStoreDaoImpl.class, StoragePoolDetailsDaoImpl.class, + PortableIpRangeDaoImpl.class, + RegionDaoImpl.class, + PortableIpDaoImpl.class, AccountGuestVlanMapDaoImpl.class }, includeFilters={@Filter(value=ChildTestConfiguration.Library.class, type=FilterType.CUSTOM)}, @@ -354,7 +362,7 @@ public class ChildTestConfiguration { public DataStoreManager dataStoreManager() { return Mockito.mock(DataStoreManager.class); } - + public static class Library implements TypeFilter { @Override diff --git a/services/secondary-storage/scripts/ssvm-check.sh b/services/secondary-storage/scripts/ssvm-check.sh index a4011647f07..7b83c989218 100644 --- a/services/secondary-storage/scripts/ssvm-check.sh +++ b/services/secondary-storage/scripts/ssvm-check.sh @@ -67,12 +67,12 @@ fi # check to see if we have the NFS volume mounted echo ================================================ -mount|grep -v sunrpc|grep nfs 1> /dev/null 2>&1 +mount|grep -v sunrpc|grep -v rpc_pipefs|grep nfs 1> /dev/null 2>&1 if [ $? -eq 0 ] then echo "NFS is currently mounted" # check for write access - for MOUNTPT in `mount|grep -v sunrpc|grep nfs| awk '{print $3}'` + for MOUNTPT in `mount|grep -v sunrpc|grep -v rpc_pipefs|grep nfs| awk '{print $3}'` do if [ $MOUNTPT != "/proc/xen" ] # mounted by xen then diff --git a/setup/db/db/schema-302to40.sql b/setup/db/db/schema-302to40.sql index f17f067c6ef..7fa73483db6 100644 --- a/setup/db/db/schema-302to40.sql +++ b/setup/db/db/schema-302to40.sql @@ -134,7 +134,7 @@ ALTER TABLE `cloud`.`account` ADD COLUMN `default_zone_id` bigint unsigned; ALTER TABLE `cloud`.`account` ADD CONSTRAINT `fk_account__default_zone_id` FOREIGN KEY `fk_account__default_zone_id`(`default_zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE; -DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); +DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM `cloud`.`storage_pool` WHERE removed IS NOT NULL); DROP TABLE IF EXISTS `cloud`.`cluster_vsm_map`; DROP TABLE IF EXISTS `cloud`.`virtual_supervisor_module`; @@ -179,14 +179,14 @@ CREATE TABLE `cloud`.`port_profile` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); +DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM `cloud`.`storage_pool` WHERE removed IS NOT NULL); ALTER TABLE `cloud`.`service_offering` MODIFY `nw_rate` smallint(5) unsigned DEFAULT '200' COMMENT 'network rate throttle mbits/s'; -- RBD Primary Storage pool support (commit: 406fd95d87bfcdbb282d65589ab1fb6e9fd0018a) -ALTER TABLE `storage_pool` ADD `user_info` VARCHAR( 255 ) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems' AFTER `host_address`; +ALTER TABLE `cloud`.`storage_pool` ADD `user_info` VARCHAR( 255 ) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems' AFTER `host_address`; -- Resource tags (commit: 62d45b9670520a1ee8b520509393d4258c689b50) CREATE TABLE `cloud`.`resource_tags` ( @@ -232,9 +232,9 @@ CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( -- Remove the unique constraint on physical_network_id, provider_name from physical_network_service_providers -- Because the name of this contraint is not set we need this roundabout way -- The key is also used by the foreign key constraint so drop and recreate that one -ALTER TABLE physical_network_service_providers DROP FOREIGN KEY fk_pnetwork_service_providers__physical_network_id; +ALTER TABLE `cloud`.`physical_network_service_providers` DROP FOREIGN KEY fk_pnetwork_service_providers__physical_network_id; -SET @constraintname = (select CONCAT(CONCAT('DROP INDEX ', A.CONSTRAINT_NAME), ' ON physical_network_service_providers' ) +SET @constraintname = (select CONCAT(CONCAT('DROP INDEX ', A.CONSTRAINT_NAME), ' ON cloud.physical_network_service_providers' ) from information_schema.key_column_usage A JOIN information_schema.key_column_usage B ON B.table_name = 'physical_network_service_providers' AND B.COLUMN_NAME = 'provider_name' AND A.COLUMN_NAME ='physical_network_id' AND B.CONSTRAINT_NAME=A.CONSTRAINT_NAME where A.table_name = 'physical_network_service_providers' LIMIT 1); @@ -243,7 +243,7 @@ PREPARE stmt1 FROM @constraintname; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; -AlTER TABLE physical_network_service_providers ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; +AlTER TABLE `cloud`.`physical_network_service_providers` ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; UPDATE `cloud`.`configuration` SET description='In second, timeout for creating volume from snapshot' WHERE name='create.volume.from.snapshot.wait'; ALTER TABLE `cloud`.`data_center` ADD COLUMN `is_local_storage_enabled` tinyint NOT NULL DEFAULT 0 COMMENT 'Is local storage offering enabled for this data center; 1: enabled, 0: not'; diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index b7b1c7a91dd..acc29a2eb7f 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -184,6 +184,7 @@ UPDATE `cloud`.`alert` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`async_job` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`cluster` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`data_center` set uuid=id WHERE uuid is NULL; +UPDATE `cloud`.`dc_storage_network_ip_range` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`disk_offering` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`domain` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`event` set uuid=id WHERE uuid is NULL; @@ -217,6 +218,7 @@ UPDATE `cloud`.`security_group` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`security_group_rule` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`snapshot_schedule` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`snapshots` set uuid=id WHERE uuid is NULL; +UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`static_routes` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`storage_pool` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`swift` set uuid=id WHERE uuid is NULL; @@ -1639,3 +1641,15 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Usage', 'DEFAULT', 'manageme INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (163, UUID(), 10, 'Ubuntu 12.04 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (164, UUID(), 10, 'Ubuntu 12.04 (64-bit)'); + +DROP TABLE IF EXISTS `cloud`.`netscaler_pod_ref`; +CREATE TABLE `cloud`.`netscaler_pod_ref` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `external_load_balancer_device_id` bigint unsigned NOT NULL COMMENT 'id of external load balancer device', + `pod_id` bigint unsigned NOT NULL COMMENT 'pod id', + PRIMARY KEY (`id`), + CONSTRAINT `fk_ns_pod_ref__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_ns_pod_ref__device_id` FOREIGN KEY (`external_load_balancer_device_id`) REFERENCES `external_load_balancer_devices`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'eip.use.multiple.netscalers' , 'false', 'Should be set to true, if there will be multiple NetScaler devices providing EIP service in a zone'); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 5ddf3b65112..fd2ac568cad 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -25,8 +25,8 @@ SET foreign_key_checks = 0; ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `max_hosts_per_cluster` int unsigned DEFAULT NULL COMMENT 'Max. hosts in cluster supported by hypervisor'; ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `storage_motion_supported` int(1) unsigned DEFAULT 0 COMMENT 'Is storage motion supported'; UPDATE `cloud`.`hypervisor_capabilities` SET `max_hosts_per_cluster`=32 WHERE `hypervisor_type`='VMware'; -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES ('XenServer', '6.1.0', 50, 1, 13, 1); -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES ('VMware', '5.1', 128, 0, 32); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES (UUID(), 'XenServer', '6.1.0', 50, 1, 13, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES (UUID(), 'VMware', '5.1', 128, 0, 32); DELETE FROM `cloud`.`configuration` where name='vmware.percluster.host.max'; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xen.nics.max', '7', 'Maximum allowed nics for Vms created on Xen'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.apiserver.address', 'http://localhost:8081', 'Specify the address at which the Midonet API server can be contacted (if using Midonet)'); @@ -481,13 +481,13 @@ ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `uuid` varchar(40) UNIQUE; -- START: support for LXC -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('LXC', 'default', 50, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'LXC', 'default', 50, 1); ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `lxc_network_label` varchar(255) DEFAULT 'cloudbr0' COMMENT 'The network name label of the physical device dedicated to this traffic on a LXC host'; UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC' WHERE name='hypervisor.list'; -INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) - VALUES (10, 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); +INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) + VALUES (10, UUID(), 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); ALTER TABLE `cloud`.`user_vm` MODIFY user_data TEXT(32768); @@ -526,6 +526,15 @@ CREATE TABLE `cloud`.`vm_snapshots` ( ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `vm_snapshot_enabled` tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Whether VM snapshot is supported by hypervisor'; UPDATE `cloud`.`hypervisor_capabilities` SET `vm_snapshot_enabled`=1 WHERE `hypervisor_type` in ('VMware', 'XenServer'); +CREATE TABLE `cloud`.`service_offering_details` ( + `id` bigint unsigned NOT NULL auto_increment, + `service_offering_id` bigint unsigned NOT NULL COMMENT 'service offering id', + `name` varchar(255) NOT NULL, + `value` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_service_offering_details__service_offering_id` FOREIGN KEY (`service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE, + CONSTRAINT UNIQUE KEY `uk_service_offering_id_name` (`service_offering_id`, `name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP VIEW IF EXISTS `cloud`.`user_vm_view`; CREATE VIEW `cloud`.`user_vm_view` AS @@ -1391,6 +1400,43 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'Netwo alter table `cloud_usage`.`usage_network_offering` add column nic_id bigint(20) unsigned NOT NULL; + +CREATE TABLE `cloud`.`portable_ip_range` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `uuid` varchar(40), + `region_id` int unsigned NOT NULL, + `vlan_id` varchar(255), + `gateway` varchar(255), + `netmask` varchar(255), + `start_ip` varchar(255), + `end_ip` varchar(255), + PRIMARY KEY (`id`), + CONSTRAINT `fk_portableip__region_id` FOREIGN KEY (`region_id`) REFERENCES `region`(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`portable_ip_address` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `account_id` bigint unsigned NULL, + `domain_id` bigint unsigned NULL, + `allocated` datetime NULL COMMENT 'Date portable ip was allocated', + `state` char(32) NOT NULL default 'Free' COMMENT 'state of the portable ip address', + `region_id` int unsigned NOT NULL, + `vlan` varchar(255), + `gateway` varchar(255), + `netmask` varchar(255), + `portable_ip_address` varchar(255), + `portable_ip_range_id` bigint unsigned NOT NULL, + `data_center_id` bigint unsigned NULL COMMENT 'zone to which portable IP is associated', + `physical_network_id` bigint unsigned NULL COMMENT 'physical network id in the zone to which portable IP is associated', + `network_id` bigint unsigned NULL COMMENT 'guest network to which portable ip address is associated with', + `vpc_id` bigint unsigned COMMENT 'vpc to which portable ip address is associated with', + PRIMARY KEY (`id`), + CONSTRAINT `fk_portable_ip_address__portable_ip_range_id` FOREIGN KEY (`portable_ip_range_id`) REFERENCES `portable_ip_range`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_portable_ip_address__region_id` FOREIGN KEY (`region_id`) REFERENCES `region`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `cloud`.`user_ip_address` ADD COLUMN is_portable int(1) unsigned NOT NULL default '0'; + DROP VIEW IF EXISTS `cloud`.`disk_offering_view`; CREATE VIEW `cloud`.`disk_offering_view` AS select @@ -1894,7 +1940,11 @@ CREATE TABLE `cloud`.`nic_ip_alias` ( alter table `cloud`.`vpc_gateways` add column network_acl_id bigint unsigned default 1 NOT NULL; update `cloud`.`vpc_gateways` set network_acl_id = 2; + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'VpcManager', 'blacklisted.routes', NULL, 'Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway'); + + -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; - +UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index b2038a9bd3b..a25e63688f3 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -561,7 +561,7 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): self.apiclient, self.services["account"] ) - self.debug("Created account: %s" % account_1.account.name) + self.debug("Created account: %s" % account_1.name) self.cleanup.append(account_1) account_2 = Account.create( self.apiclient, diff --git a/test/integration/component/test_custom_hostname.py b/test/integration/component/test_custom_hostname.py new file mode 100644 index 00000000000..e5452141d9c --- /dev/null +++ b/test/integration/component/test_custom_hostname.py @@ -0,0 +1,369 @@ +# 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 user provide hostname cases +""" +#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 * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test user provided hostname Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "administrator@clogeny.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "user": { + "email": "administrator@clogeny.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "password", + }, + "disk_offering": { + "displaytext": "Tiny Disk Offering", + "name": "Tiny Disk Offering", + "disksize": 1 + }, + "volume": { + "diskname": "Test Volume", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + } + + +class TestInstanceNameFlagTrue(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestInstanceNameFlagTrue, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, default template + cls.zone = get_zone(cls.api_client, cls.services) + cls.services["mode"] = cls.zone.networktype + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + # Create domains, account etc. + cls.domain = get_domain( + cls.api_client, + cls.services + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + 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, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(configuration='vm.instancename.flag') + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + def test_01_user_provided_hostname(self): + """ Verify user provided hostname to an instance + """ + + # Validate the following + # 1. Set the vm.instancename.flag to true. Hostname and displayname + # should be user provided display name + # 2. Give the user provided user name. Internal name should be + # i---display name + + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.debug( + "Checking if the virtual machine is created properly or not?") + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List vms should return a valid name" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm state should be running after deployment" + ) + self.debug("vm.displayname: %s, original: %s" % + (vm.displayname, + self.services["virtual_machine"]["displayname"])) + self.assertEqual( + vm.displayname, + self.services["virtual_machine"]["displayname"], + "Vm display name should match the given name" + ) + + # Fetch account ID and VMID from database to check internal name + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + account_id = qresult[0] + + self.debug("select id from vm_instance where uuid = '%s';" % vm.id) + + qresultset = self.dbclient.execute( + "select id from vm_instance where uuid = '%s';" % + vm.id) + + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + self.debug("Query result: %s" % qresult) + vmid = qresult[0] + + #internal Name = i---Display name + internal_name = "i-" + str(account_id) + "-" + str(vmid) + "-" + vm.displayname + self.debug("Internal name: %s" % internal_name) + self.assertEqual( + vm.instancename, + internal_name, + "VM internal name should match with that of the format" + ) + return + + @attr(configuration='vm.instancename.flag') + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + def test_02_instancename_from_default_configuration(self): + """ Verify for globally set instancename + """ + + # Validate the following + # 1. Set the vm.instancename.flag to true. Hostname and displayname + # should be user provided display name + # 2. Dont give the user provided user name. Internal name should be + # i--- in global config + + # Removing display name from config + del self.services["virtual_machine"]["displayname"] + self.debug("Deploying VM in account: %s" % self.account.account.name) + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.debug( + "Checking if the virtual machine is created properly or not?") + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List vms should retuen a valid name" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm state should be running after deployment" + ) + self.assertEqual( + vm.displayname, + vm.id, + "Vm display name should not match the given name" + ) + # Fetch account ID and VMID from database to check internal name + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + account_id = qresult[0] + + self.debug("select id from vm_instance where uuid = '%s';" % vm.id) + + qresultset = self.dbclient.execute( + "select id from vm_instance where uuid = '%s';" % + vm.id) + + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + self.debug("Query result: %s" % qresult) + vmid = qresult[0] + + self.debug("Fetching the global config value for instance.name") + configs = Configurations.list( + self.apiclient, + name="instance.name", + listall=True + ) + + config = configs[0] + instance_name = config.value + self.debug("Instance.name: %s" % instance_name) + + #internal Name = i--- Instance_name + internal_name = "i-" + str(account_id) + "-" + str(vmid) + "-" + instance_name + self.assertEqual( + vm.instancename, + internal_name, + "VM internal name should match with that of the format" + ) + return diff --git a/test/integration/component/test_high_availability.py b/test/integration/component/test_high_availability.py index 12753c1707f..cd2dfcea559 100644 --- a/test/integration/component/test_high_availability.py +++ b/test/integration/component/test_high_availability.py @@ -220,7 +220,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) vms = VirtualMachine.list( @@ -248,7 +248,7 @@ class TestHighAvailability(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -264,7 +264,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) @@ -372,7 +372,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) vms = VirtualMachine.list( @@ -424,7 +424,7 @@ class TestHighAvailability(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -464,7 +464,7 @@ class TestHighAvailability(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -513,7 +513,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) vms = VirtualMachine.list( @@ -615,7 +615,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) vms = VirtualMachine.list( @@ -643,7 +643,7 @@ class TestHighAvailability(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -659,7 +659,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) @@ -833,7 +833,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) vms = VirtualMachine.list( @@ -952,7 +952,7 @@ class TestHighAvailability(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -990,7 +990,7 @@ class TestHighAvailability(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1037,7 +1037,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) vms = VirtualMachine.list( diff --git a/test/integration/component/test_host_high_availability.py b/test/integration/component/test_host_high_availability.py index 7a3f62a520f..8c66d175dd7 100644 --- a/test/integration/component/test_host_high_availability.py +++ b/test/integration/component/test_host_high_availability.py @@ -190,7 +190,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_with_ha.id ) vms = VirtualMachine.list( @@ -235,7 +235,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_with_ha.id ) @@ -289,7 +289,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_without_ha.id ) @@ -358,7 +358,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_with_ha.id ) @@ -464,7 +464,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_with_ha.id ) @@ -573,7 +573,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_with_ha.id ) @@ -705,7 +705,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering_without_ha.id ) diff --git a/test/integration/component/test_implicit_planner.py b/test/integration/component/test_implicit_planner.py new file mode 100644 index 00000000000..ffcd248b462 --- /dev/null +++ b/test/integration/component/test_implicit_planner.py @@ -0,0 +1,232 @@ +# 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 Storage motion +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.remoteSSHClient import remoteSSHClient +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from nose.plugins.attrib import attr +#Import System modules +import time + +_multiprocess_shared_ = True +class Services: + """Test VM Life Cycle Services + """ + + def __init__(self): + self.services = { + "disk_offering":{ + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "password", + }, + "small": + # Create a small virtual machine instance with disk offering + { + "displayname": "testserver", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offerings": + { + "implicitplanner": + { + # Small service offering ID to for change VM + # service offering from medium to small + "name": "Implicit Strict", + "displaytext": "Implicit Strict", + "cpunumber": 1, + "cpuspeed": 500, + "memory": 512, + "deploymentplanner": "ImplicitDedicationPlanner" + } + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "passwordenabled": True, + }, + "diskdevice": '/dev/xvdd', + # Disk device where ISO is attached to instance + "mount_dir": "/mnt/tmp", + "sleep": 60, + "timeout": 10, + #Migrate VM to hostid + "ostype": 'CentOS 5.3 (64-bit)', + # CentOS 5.3 (64-bit) + } + +class TestImplicitPlanner(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestImplicitPlanner, cls).getClsTestClient().getApiClient() + cls.services = Services().services + + # Get Zone, Domain and templates + domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=domain.id + ) + + cls.small_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["implicitplanner"] + ) + + cls._cleanup = [ + cls.small_offering, + cls.account + ] + + @classmethod + def tearDownClass(cls): + cls.api_client = super(TestImplicitPlanner, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.api_client, cls._cleanup) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created ISOs + cleanup_resources(self.apiclient, self.cleanup) + return + + # This test requires multi host and at least one host which is empty (no vms should + # be running on that host). It uses an implicit planner to deploy instances and the + # instances of a new account should go to an host that doesn't have vms of any other + # account. + @attr(tags = ["advanced", "basic", "multihosts", "implicitplanner"]) + def test_01_deploy_vm_with_implicit_planner(self): + """Test implicit planner is placing vms of an account on implicitly dedicated hosts. + """ + # Validate the following + # 1. Deploy a vm using implicit planner. It should go on to a + # host that is empty (not running vms of any other account) + # 2. Deploy another vm it should get deployed on the same host. + + #create a virtual machine + virtual_machine_1 = VirtualMachine.create( + self.api_client, + self.services["small"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.small_offering.id, + mode=self.services["mode"] + ) + + list_vm_response_1 = list_virtual_machines( + self.apiclient, + id=virtual_machine_1.id + ) + self.assertEqual( + isinstance(list_vm_response_1, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + list_vm_response_1, + None, + "Check virtual machine is listVirtualMachines" + ) + + vm_response_1 = list_vm_response_1[0] + + self.assertEqual( + vm_response_1.id, + virtual_machine_1.id, + "Check virtual machine ID of VM" + ) + + virtual_machine_2 = VirtualMachine.create( + self.api_client, + self.services["small"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.small_offering.id, + mode=self.services["mode"] + ) + + list_vm_response_2 = list_virtual_machines( + self.apiclient, + id=virtual_machine_2.id + ) + self.assertEqual( + isinstance(list_vm_response_2, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + list_vm_response_2, + None, + "Check virtual machine is listVirtualMachines" + ) + + vm_response_2 = list_vm_response_2[0] + + self.assertEqual( + vm_response_2.id, + virtual_machine_2.id, + "Check virtual machine ID of VM" + ) + + self.assertEqual( + vm_response_1.hostid, + vm_response_2.hostid, + "Check both vms have the same host id" + ) + return \ No newline at end of file diff --git a/test/integration/component/test_ldap.py b/test/integration/component/test_ldap.py new file mode 100644 index 00000000000..1b933dbccf7 --- /dev/null +++ b/test/integration/component/test_ldap.py @@ -0,0 +1,365 @@ +# 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 for LDAP Config +""" + + +#!/usr/bin/env python + +import marvin +from marvin import cloudstackTestCase +from marvin.cloudstackTestCase import * +import unittest +import hashlib +import random +from marvin.cloudstackAPI import * +from marvin.cloudstackAPI import login +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from nose.plugins.attrib import attr +import urllib + + + +class Services: + """Test LDAP Configuration + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "test", + "lastname": "t", + "username": "test", + "password": "password", + }, + "ldapCon_1":#valid values&Query filter as email. + { + "ldapHostname": "10.147.38.163", + "port": "389", + "binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com", + "bindpass": "aaaa_1111", + "queryfilter": "(&(mail=%e))", + "searchbase": "CN=Users,DC=hyd-qa,DC=com", + "ldapusername": "test", + "ldappasswd": "aaaa_1111" + }, + "ldapCon_2": ##valid values&Query filter as displayName. + { + "ldapHostname": "10.147.38.163", + "port": "389", + "binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com", + "bindpass": "aaaa_1111", + "queryfilter": "(&(displayName=%u))", + "searchbase": "CN=Users,DC=hyd-qa,DC=com", + "ldapusername": "test", + "ldappasswd": "aaaa_1111" + }, + "ldapCon_3": #Configuration with missing parameters value(queryfilter) + { + "ldapHostname": "10.147.38.163", + "port": "389", + "binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com", + "bindpass": "aaaa_1111", + "queryfilter": "", + "searchbase": "CN=Users,DC=hyd-qa,DC=com", + "ldapusername": "test", + "ldappasswd": "aaaa_1111" + }, + + "ldapCon_4": #invalid configuration-wrong query filter + { + "ldapHostname": "10.147.38.163", + "port": "389", + "binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com", + "bindpass": "aaaa_1111", + "queryfilter": "(&(displayName=%p))", + "searchbase":"CN=Users,DC=hyd-qa,DC=com", + "ldapusername": "test", + "ldappasswd": "aaaa_1111" + }, + "ldapCon_5": #Configuration with invalid ldap credentials + { + "ldapHostname": "10.147.38.163", + "port": "389", + "binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com", + "bindpass": "aaaa_1111", + "queryfilter": "(&(displayName=%u))", + "searchbase": "CN=Users,DC=hyd-qa,DC=com", + "ldapusername": "test", + "ldappasswd": "aaaa" + } + + + + } + + +class TestLdap(cloudstackTestCase): + """ + This test perform registering ldap configuration details in CS and create a user[ldap user] in CS + and validate user credentials against LDAP server:AD + """ + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestLdap, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + cls.account = cls.services["account"] + cls._cleanup = [] + + + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + #print "tear down class" + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as tde: + raise Exception("Warning: Exception during cleanup : %s" % tde) + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + + self.acct = createAccount.createAccountCmd() + self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1 + self.acct.firstname = self.services["account"]["firstname"] + self.acct.lastname = self.services["account"]["lastname"] + self.acct.password = self.services["account"]["password"] + self.acct.username = self.services["account"]["username"] + self.acct.email = self.services["account"]["email"] + self.acct.account = self.services["account"]["username"] + self.acct.domainid = 1 + # mapping ldap user by creating same user in cloudstack + + self.acctRes = self.apiclient.createAccount(self.acct) + + + return + + def tearDown(self): + + try: + #Clean up, terminate the created accounts, domains etc + + deleteAcct = deleteAccount.deleteAccountCmd() + deleteAcct.id = self.acctRes.id + + acct_name=self.acctRes.name + + self.apiclient.deleteAccount(deleteAcct) + + self.debug("Deleted the the following account name %s:" %acct_name) + #delete only if ldapconfig registered in CS + if(self.ldapconfRes): + deleteldapconfg=ldapRemove.ldapRemoveCmd() + res=self.apiclient.ldapRemove(deleteldapconfg) + + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + + def test_01_configLDAP(self): + ''' + This test is to verify ldapConfig API with valid values.(i.e query fileter as email) + ''' + # 1. This test covers ldapConfig & login API with valid ldap credentials.. + # require ldap configuration:ldapCon_1 + + self.debug("start test") + + self.ldapconfRes=self._testldapConfig(self.services["ldapCon_1"]) + + if(self.ldapconfRes==1): + + + self.debug("configure ldap successful") + + #validating the user credentials with ldap Server + loginRes = self.chkLogin(self.services["ldapCon_1"]["ldapusername"], self.services["ldapCon_1"]["ldappasswd"]) + self.assertEquals(loginRes,1,"ldap Authentication failed") + + else: + + self.debug("LDAP Configuration failed with exception") + + self.assertEquals(self.ldapconfRes,1,"ldapConfig API failed") + + + self.debug("end test") + + + def test_02_configLDAP(self): + ''' + This test is to verify ldapConfig API with valid values.(i.e query fileter as displayName) + ''' + + # 1. This test covers ldapConfig & login API with valid ldap credentials. + # 2. require ldap configuration:ldapCon_2 + + self.debug("start test") + self.ldapconfRes=self._testldapConfig(self.services["ldapCon_2"]) + self.assertEquals(self.ldapconfRes,1,"ldapConfig API failed") + if(self.ldapconfRes==1): + self.debug("configure ldap successful") + #validating the user credentials with ldap Server + loginRes = self.chkLogin(self.services["ldapCon_2"]["ldapusername"], self.services["ldapCon_2"]["ldappasswd"]) + self.assertEquals(loginRes,1,"ldap Authentication failed") + else: + self.debug("LDAP Configuration failed with exception") + self.debug("end test") + + + def test_03_configLDAP(self): + + ''' + This test is to verify ldapConfig API with missing config parameters value(i.queryfilter) + ''' + + # 1. Issue ldapConfig API with no ldap config parameter value and check behavior + # 2. require ldap configuration:ldapCon_3 + + self.debug("start test...") + self.ldapconfRes=self._testldapConfig(self.services["ldapCon_3"]) + self.assertEquals(self.ldapconfRes,0,"LDAP configuration successful with invalid value.API failed") + self.debug("end test") + + def test_04_configLDAP(self): + ''' + This test is to verify ldapConfig API with invalid configuration values(by passing wrong query filter) + ''' + # 1. calling ldapConfig API with invalid query filter value and check behavior + # 2. require ldap configuration:ldapCon_4 + + self.debug("start test...") + self.ldapconfRes=self._testldapConfig(self.services["ldapCon_4"]) + self.assertEquals(self.ldapconfRes,0,"API failed") + + + + def test_05_configLDAP(self): + + ''' + This test is to verify login API functionality by passing wrong ldap credentials + ''' + # 1.This script first configure the ldap and validates the user credentials using login API + # 2. require ldap configuration:ldapCon_5 + + + self.debug("start test") + self.ldapconfRes=self._testldapConfig(self.services["ldapCon_5"]) + self.assertEquals(self.ldapconfRes,1,"API failed") + #validating the cloudstack user credentials with ldap Server + loginRes = self.chkLogin(self.services["ldapCon_5"]["ldapusername"], self.services["ldapCon_5"]["ldappasswd"]) + self.assertNotEqual(loginRes,1,"login API failed") + self.debug("end test") + + def test_06_removeLDAP(self): + ''' + This test is to verify ldapRemove API functionality + ''' + # 1. This script fist configures ldap and removes the configured ldap values + # 2. require ldap configuration:ldapCon_1 + + + self.debug("start test") + self.ldapconfRes=self._testldapConfig(self.services["ldapCon_1"]) + if(self.ldapconfRes==1): + self.debug("ldap configured successfully") + deleteldapconfg=ldapRemove.ldapRemoveCmd() + res=self.apiclient.ldapRemove(deleteldapconfg) + self.debug("ldap removed successfully") + self.ldapconfRes=0 + else: + + self.debug("LDAP Configuration failed with exception") + self.assertEquals(self.ldapconfRes,0,"ldapconfig API failed") + self.debug("end test") + + def _testldapConfig(self,ldapSrvD): + + """ + + :param ldapSrvD + + + """ + #This Method takes dictionary as parameter, + # reads the ldap configuration values from the passed dictionary and + # register the ldapconfig detail in cloudstack + # & return true or false based on ldapconfig API response + + self.debug("start ldapconfig test") + #creating the ldapconfig cmd object + lpconfig = ldapConfig.ldapConfigCmd() + #Config the ldap server by assigning the ldapconfig dict variable values to ldapConfig object + lpconfig.hostname = ldapSrvD["ldapHostname"] + lpconfig.port = ldapSrvD["port"] + lpconfig.binddn = ldapSrvD["binddn"] + lpconfig.bindpass = ldapSrvD["bindpass"] + lpconfig.searchbase = ldapSrvD["searchbase"] + lpconfig.queryfilter = ldapSrvD["queryfilter"] + + #end of assigning the variables + + #calling the ldapconfig Api + self.debug("calling ldapconfig API") + try: + lpconfig1 = self.apiclient.ldapConfig(lpconfig) + self.debug("ldapconfig API succesfful") + return 1 + except Exception, e: + self.debug("ldapconfig API failed %s" %e) + return 0 + + def chkLogin(self, username, password): + """ + + :param username: + :param password: + + """ + self.debug("login test") + + try: + login1 = login.loginCmd() + login1.username = username + login1.password = password + loginRes = self.apiclient.login(login1) + self.debug("login response %s" % loginRes) + if loginRes is None: + self.debug("login not successful") + else: + self.debug("login successful") + return 1 + + except Exception, p: + self.debug("login operation failed %s" %p) + self.debug("end of Login") diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 17ddfc67da5..9184dca5202 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -193,7 +193,7 @@ class TestProjectLimits(cloudstackTestCase): # Also, verify resource limits for the project are independent of # account resource limits # 3. Increase Projects Resources limits above domains limit. Verify - # project can’t have more resources than domain level limit allows. + # project can't have more resources than domain level limit allows. # 4. Create Resource more than its set limit for a project. Verify # resource allocation should fail giving proper message @@ -312,6 +312,7 @@ class TestProjectLimits(cloudstackTestCase): max=2 ) with self.assertRaises(Exception): + max_value = 3 self.debug( "Attempting to update project: %s resource limit to: %s" % ( project.id, @@ -321,7 +322,7 @@ class TestProjectLimits(cloudstackTestCase): update_resource_limit( self.apiclient, resource.resourcetype, - max=3, + max=max_value, projectid=project.id ) return diff --git a/test/integration/component/test_projects.py b/test/integration/component/test_projects.py index f013e99a0dd..e1975cf5295 100644 --- a/test/integration/component/test_projects.py +++ b/test/integration/component/test_projects.py @@ -782,8 +782,8 @@ class TestProjectOwners(cloudstackTestCase): project = Project.create( self.apiclient, self.services["project"], - account=self.admin.account.name, - domainid=self.admin.account.domainid + account=self.admin.name, + domainid=self.admin.domainid ) self.cleanup.append(project) # Cleanup created project at end of test @@ -815,20 +815,20 @@ class TestProjectOwners(cloudstackTestCase): "Check project name from list response" ) self.debug("Adding %s user to project: %s" % ( - self.new_admin.account.name, + self.new_admin.name, project.name )) # Add user to the project project.addAccount( self.apiclient, - self.new_admin.account.name, + self.new_admin.name, ) # listProjectAccount to verify the user is added to project or not accounts_reponse = Project.listAccounts( self.apiclient, projectid=project.id, - account=self.new_admin.account.name, + account=self.new_admin.name, ) self.debug(accounts_reponse) self.assertEqual( @@ -853,14 +853,14 @@ class TestProjectOwners(cloudstackTestCase): # Update the project with new admin project.update( self.apiclient, - account=self.new_admin.account.name + account=self.new_admin.name ) # listProjectAccount to verify the user is new admin of the project accounts_reponse = Project.listAccounts( self.apiclient, projectid=project.id, - account=self.new_admin.account.name, + account=self.new_admin.name, ) self.debug(accounts_reponse) self.assertEqual( @@ -886,7 +886,7 @@ class TestProjectOwners(cloudstackTestCase): accounts_reponse = Project.listAccounts( self.apiclient, projectid=project.id, - account=self.admin.account.name, + account=self.admin.name, ) self.debug(accounts_reponse) self.assertEqual( @@ -923,8 +923,8 @@ class TestProjectOwners(cloudstackTestCase): project = Project.create( self.apiclient, self.services["project"], - account=self.admin.account.name, - domainid=self.admin.account.domainid + account=self.admin.name, + domainid=self.admin.domainid ) # Cleanup created project at end of test self.cleanup.append(project) @@ -965,20 +965,20 @@ class TestProjectOwners(cloudstackTestCase): "Check project name from list response" ) self.debug("Adding %s user to project: %s" % ( - self.new_admin.account.name, + self.new_admin.name, project.name )) # Add user to the project project.addAccount( self.apiclient, - self.new_admin.account.name, + self.new_admin.name, ) # listProjectAccount to verify the user is added to project or not accounts_reponse = Project.listAccounts( self.apiclient, projectid=project.id, - account=self.new_admin.account.name, + account=self.new_admin.name, ) self.debug(accounts_reponse) self.assertEqual( @@ -1000,18 +1000,18 @@ class TestProjectOwners(cloudstackTestCase): "Newly added user is not added as a regular user" ) self.debug("Updating project with new Admin: %s" % - self.new_admin.account.name) + self.new_admin.name) # Update the project with new admin project.update( self.apiclient, - account=self.new_admin.account.name + account=self.new_admin.name ) # listProjectAccount to verify the user is new admin of the project accounts_reponse = Project.listAccounts( self.apiclient, projectid=project.id, - account=self.new_admin.account.name, + account=self.new_admin.name, ) self.assertEqual( isinstance(accounts_reponse, list), @@ -1106,7 +1106,7 @@ class TestProjectOwners(cloudstackTestCase): accounts_reponse = Project.listAccounts( self.apiclient, projectid=project.id, - account=self.new_admin.account.name, + account=self.new_admin.name, ) self.assertEqual( isinstance(accounts_reponse, list), diff --git a/test/integration/component/test_redundant_router.py b/test/integration/component/test_redundant_router.py index 8885241ef7b..a87818a4ccb 100644 --- a/test/integration/component/test_redundant_router.py +++ b/test/integration/component/test_redundant_router.py @@ -331,7 +331,7 @@ class TestCreateRvRNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -375,7 +375,7 @@ class TestCreateRvRNetwork(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -538,7 +538,7 @@ class TestCreateRvRNetworkNonDefaultGuestCidr(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, guestcidr=' 192.168.2.0/23' @@ -593,7 +593,7 @@ class TestCreateRvRNetworkNonDefaultGuestCidr(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -760,7 +760,7 @@ class TestRVRInternals(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -804,7 +804,7 @@ class TestRVRInternals(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -1019,7 +1019,7 @@ class TestRedundancy(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -1031,7 +1031,7 @@ class TestRedundancy(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network.id)] ) @@ -1572,7 +1572,7 @@ class TestRedundancy(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network.id)] ) @@ -1712,7 +1712,7 @@ class TestApplyAndDeleteNetworkRulesOnRvR(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -1756,7 +1756,7 @@ class TestApplyAndDeleteNetworkRulesOnRvR(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -1801,7 +1801,7 @@ class TestApplyAndDeleteNetworkRulesOnRvR(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -1870,7 +1870,7 @@ class TestApplyAndDeleteNetworkRulesOnRvR(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -1902,7 +1902,7 @@ class TestApplyAndDeleteNetworkRulesOnRvR(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2037,7 +2037,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -2081,7 +2081,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -2126,7 +2126,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2142,7 +2142,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): self.apiclient, publicipid=public_ip.ipaddress.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) except Exception as e: self.fail("Failed to create VPN for account: %s - %s" % ( @@ -2154,7 +2154,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): username="root", password="password", account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) except Exception as e: self.fail("Failed to create VPN user: %s" % e) @@ -2163,7 +2163,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): remote_vpns = Vpn.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, publicipid=public_ip.ipaddress.id, listall=True ) @@ -2184,7 +2184,7 @@ class TestEnableVPNOverRvR(cloudstackTestCase): remote_vpns = Vpn.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, publicipid=public_ip.ipaddress.id, listall=True ) @@ -2306,7 +2306,7 @@ class TestNetworkRulesMasterDownDeleteNetworkRules(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -2350,7 +2350,7 @@ class TestNetworkRulesMasterDownDeleteNetworkRules(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -2412,7 +2412,7 @@ class TestNetworkRulesMasterDownDeleteNetworkRules(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2481,7 +2481,7 @@ class TestNetworkRulesMasterDownDeleteNetworkRules(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2513,7 +2513,7 @@ class TestNetworkRulesMasterDownDeleteNetworkRules(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2694,7 +2694,7 @@ class TestApplyDeleteNetworkRulesRebootRouter(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -2738,7 +2738,7 @@ class TestApplyDeleteNetworkRulesRebootRouter(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -2790,7 +2790,7 @@ class TestApplyDeleteNetworkRulesRebootRouter(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2851,7 +2851,7 @@ class TestApplyDeleteNetworkRulesRebootRouter(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -2872,7 +2872,7 @@ class TestApplyDeleteNetworkRulesRebootRouter(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -3058,7 +3058,7 @@ class TestRestartRvRNetworkWithoutCleanup(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -3102,7 +3102,7 @@ class TestRestartRvRNetworkWithoutCleanup(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -3279,7 +3279,7 @@ class TestRestartRvRNetworkWithCleanup(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -3323,7 +3323,7 @@ class TestRestartRvRNetworkWithCleanup(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -3500,7 +3500,7 @@ class TestDeleteRvRNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -3544,7 +3544,7 @@ class TestDeleteRvRNetwork(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -3719,7 +3719,7 @@ class TestNetworkGCRvR(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -3763,7 +3763,7 @@ class TestNetworkGCRvR(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -3999,7 +3999,7 @@ class TestApplyRulesRestartRvRNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -4043,7 +4043,7 @@ class TestApplyRulesRestartRvRNetwork(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -4095,7 +4095,7 @@ class TestApplyRulesRestartRvRNetwork(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -4156,7 +4156,7 @@ class TestApplyRulesRestartRvRNetwork(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -4177,7 +4177,7 @@ class TestApplyRulesRestartRvRNetwork(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.debug("Associated %s with network %s" % ( @@ -4439,7 +4439,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=network_off_vr.id, zoneid=self.zone.id ) @@ -4471,7 +4471,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -4500,7 +4500,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -4528,7 +4528,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -4574,7 +4574,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -4606,7 +4606,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -4635,7 +4635,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -4676,7 +4676,7 @@ class TestUpgradeDowngradeRVR(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -4808,7 +4808,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -4852,7 +4852,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -4972,7 +4972,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -5016,7 +5016,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -5208,7 +5208,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -5265,7 +5265,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)], hostid=host.id @@ -5449,7 +5449,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) @@ -5506,7 +5506,7 @@ class TestRVRWithDiffEnvs(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)], hostid=host.id diff --git a/test/integration/component/test_stopped_vm.py b/test/integration/component/test_stopped_vm.py index 10e3d4d0b83..f1096919824 100644 --- a/test/integration/component/test_stopped_vm.py +++ b/test/integration/component/test_stopped_vm.py @@ -188,7 +188,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id, mode=self.zone.networktype @@ -242,7 +242,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=True, diskofferingid=self.disk_offering.id, @@ -299,7 +299,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, diskofferingid=self.disk_offering.id, @@ -332,7 +332,7 @@ class TestDeployVM(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -389,7 +389,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, diskofferingid=self.disk_offering.id, @@ -426,7 +426,7 @@ class TestDeployVM(cloudstackTestCase): self.services["volume"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) self.debug("Created volume in account: %s" % self.account.name) @@ -457,7 +457,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, diskofferingid=self.disk_offering.id, @@ -494,7 +494,7 @@ class TestDeployVM(cloudstackTestCase): self.services["volume"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) self.debug("Created volume in account: %s" % self.account.name) @@ -570,7 +570,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, diskofferingid=self.disk_offering.id, @@ -607,7 +607,7 @@ class TestDeployVM(cloudstackTestCase): self.services["volume"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) self.debug("Created volume in account: %s" % self.account.name) @@ -653,7 +653,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, diskofferingid=self.disk_offering.id, @@ -689,7 +689,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["iso"], account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Successfully created ISO with ID: %s" % iso.id) @@ -746,7 +746,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, ) @@ -782,7 +782,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id ) @@ -819,7 +819,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, type='DATADISK', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -943,7 +943,7 @@ class TestDeployHaEnabledVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id, startvm=False @@ -990,7 +990,7 @@ class TestDeployHaEnabledVM(cloudstackTestCase): self.apiclient, self.services["iso"], account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) try: # Dowanload the ISO @@ -1007,7 +1007,7 @@ class TestDeployHaEnabledVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, templateid=self.iso.id, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id, @@ -1057,7 +1057,7 @@ class TestDeployHaEnabledVM(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id, startvm=False @@ -1175,7 +1175,7 @@ class TestRouterStateAfterDeploy(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id, startvm=False @@ -1210,7 +1210,7 @@ class TestRouterStateAfterDeploy(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1225,7 +1225,7 @@ class TestRouterStateAfterDeploy(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, diskofferingid=self.disk_offering.id, startvm=True @@ -1260,7 +1260,7 @@ class TestRouterStateAfterDeploy(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1295,7 +1295,7 @@ class TestRouterStateAfterDeploy(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertNotEqual( @@ -1397,7 +1397,7 @@ class TestDeployVMBasicZone(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=True, diskofferingid=self.disk_offering.id, @@ -1455,7 +1455,7 @@ class TestDeployVMBasicZone(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False, mode=self.zone.networktype @@ -1570,7 +1570,7 @@ class TestDeployVMFromTemplate(cloudstackTestCase): self.services["template"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) try: self.template.download(self.apiclient) @@ -1606,7 +1606,7 @@ class TestDeployVMFromTemplate(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, templateid=self.template.id, startvm=False, @@ -1744,7 +1744,7 @@ class TestVMAccountLimit(cloudstackTestCase): self.apiclient, 0, # Instance account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, max=1 ) self.debug( @@ -1756,7 +1756,7 @@ class TestVMAccountLimit(cloudstackTestCase): self.services["virtual_machine"], templateid=self.template.id, accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False ) @@ -1775,7 +1775,7 @@ class TestVMAccountLimit(cloudstackTestCase): self.services["virtual_machine"], templateid=self.template.id, accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False ) @@ -1861,7 +1861,7 @@ class TestUploadAttachVolume(cloudstackTestCase): self.services["volume"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Uploading the volume: %s" % volume.name) volume.wait_for_upload(self.apiclient) @@ -1878,7 +1878,7 @@ class TestUploadAttachVolume(cloudstackTestCase): self.services["virtual_machine"], templateid=self.template.id, accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, startvm=False ) @@ -1999,7 +1999,7 @@ class TestDeployOnSpecificHost(cloudstackTestCase): self.services["virtual_machine"], templateid=self.template.id, accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, hostid=host.id ) @@ -2013,7 +2013,7 @@ class TestDeployOnSpecificHost(cloudstackTestCase): id=vm.id, listall=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index ab5ab310094..12a586313f1 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -224,7 +224,7 @@ class TestResourceTags(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.zone.networktype ) @@ -280,7 +280,7 @@ class TestResourceTags(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -297,7 +297,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.cleanup.append(public_ip) @@ -346,7 +346,7 @@ class TestResourceTags(cloudstackTestCase): resourceType='LoadBalancer', key='LB', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, value=40 ) @@ -393,7 +393,7 @@ class TestResourceTags(cloudstackTestCase): resourceType='LoadBalancer', key='LB', account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( @@ -423,7 +423,7 @@ class TestResourceTags(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -440,7 +440,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.cleanup.append(public_ip) @@ -484,7 +484,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='portForwardingRule', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='PF', value=40 ) @@ -529,7 +529,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='portForwardingRule', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='PF', value=40 ) @@ -560,7 +560,7 @@ class TestResourceTags(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -577,7 +577,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.cleanup.append(public_ip) @@ -626,7 +626,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='FirewallRule', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='FW', value='40' ) @@ -671,7 +671,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='FirewallRule', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='FW', value='40' ) @@ -704,7 +704,7 @@ class TestResourceTags(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -721,7 +721,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id ) self.cleanup.append(public_ip) @@ -754,7 +754,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, public_ip.ipaddress.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) except Exception as e: @@ -792,7 +792,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='VPN', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='protocol', value='L2TP' ) @@ -823,7 +823,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='VPN', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='protocol', value='L2TP' ) @@ -863,7 +863,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -907,7 +907,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -978,7 +978,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='Template', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='OS', value='CentOS' ) @@ -1019,7 +1019,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='Template', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='OS', value='CentOS' ) @@ -1042,7 +1042,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, self.services["iso"], account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("ISO created with ID: %s" % iso.id) @@ -1070,7 +1070,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='ISO', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='OS', value='CentOS' ) @@ -1115,7 +1115,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='ISO', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='OS', value='CentOS' ) @@ -1141,7 +1141,7 @@ class TestResourceTags(cloudstackTestCase): self.services["volume"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) self.cleanup.append(volume) @@ -1162,7 +1162,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='volume', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1205,7 +1205,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='volume', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region' ) self.assertEqual( @@ -1262,7 +1262,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='snapshot', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='type', value='manual' ) @@ -1312,7 +1312,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='snapshot', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='type', value='manual' ) @@ -1337,7 +1337,7 @@ class TestResourceTags(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1363,7 +1363,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='Network', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1381,7 +1381,7 @@ class TestResourceTags(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True, key='region', value='India' @@ -1409,7 +1409,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='Network', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1479,7 +1479,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1516,7 +1516,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1550,7 +1550,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1596,7 +1596,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1642,7 +1642,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1691,7 +1691,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, self.services["project"], account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) # Cleanup created project at end of test self.cleanup.append(project) @@ -1758,7 +1758,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='project', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -1799,7 +1799,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, self.services["iso"], account=user_account.name, - domainid=user_account.account.domainid + domainid=user_account.domainid ) self.debug("ISO created with ID: %s" % iso.id) @@ -1827,7 +1827,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='ISO', account=user_account.name, - domainid=user_account.account.domainid, + domainid=user_account.domainid, key='region', ) @@ -1849,7 +1849,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='ISO', account=other_user_account.name, - domainid=other_user_account.account.domainid, + domainid=other_user_account.domainid, key='region', ) @@ -1884,7 +1884,7 @@ class TestResourceTags(cloudstackTestCase): self.apiclient, self.services["iso"], account=user_account.name, - domainid=user_account.account.domainid + domainid=user_account.domainid ) self.debug("ISO created with ID: %s" % iso.id) @@ -1912,7 +1912,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='ISO', account=user_account.name, - domainid=user_account.account.domainid, + domainid=user_account.domainid, key='region', ) @@ -2009,7 +2009,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -2042,7 +2042,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -2065,7 +2065,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -2103,7 +2103,7 @@ class TestResourceTags(cloudstackTestCase): self.services["volume"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) self.cleanup.append(volume) @@ -2124,7 +2124,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='volume', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', ) self.assertEqual( @@ -2152,7 +2152,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -2185,7 +2185,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -2246,7 +2246,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) @@ -2295,7 +2295,7 @@ class TestResourceTags(cloudstackTestCase): listall=True, resourceType='userVM', account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, key='region', value='India' ) diff --git a/test/integration/component/test_vpc.py b/test/integration/component/test_vpc.py index 83b913a8738..7dbe7c4bf91 100644 --- a/test/integration/component/test_vpc.py +++ b/test/integration/component/test_vpc.py @@ -316,7 +316,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -348,7 +348,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -373,7 +373,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -397,7 +397,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering_no_lb.id, zoneid=self.zone.id, gateway=gateway, @@ -432,7 +432,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -475,7 +475,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -500,7 +500,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -524,7 +524,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering_no_lb.id, zoneid=self.zone.id, gateway=gateway, @@ -575,7 +575,7 @@ class TestVPC(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -613,7 +613,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc_1) @@ -624,7 +624,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc_2) @@ -714,7 +714,7 @@ class TestVPC(cloudstackTestCase): supportedservices='Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', listall=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(vpcs, list), @@ -733,7 +733,7 @@ class TestVPC(cloudstackTestCase): restartrequired=True, listall=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) if vpcs is not None: for vpc in vpcs: @@ -748,7 +748,7 @@ class TestVPC(cloudstackTestCase): restartrequired=False, listall=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(vpcs, list), @@ -789,7 +789,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc_1) @@ -869,7 +869,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -898,7 +898,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering_no_lb.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -913,7 +913,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -927,7 +927,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -937,7 +937,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -949,7 +949,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -959,7 +959,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -970,7 +970,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1002,7 +1002,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1031,7 +1031,7 @@ class TestVPC(cloudstackTestCase): listall=True, isstaticnat=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(public_ips, list), @@ -1049,7 +1049,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, vpcid=vpc.id ) @@ -1068,7 +1068,7 @@ class TestVPC(cloudstackTestCase): accountid=self.account.name, networkid=network_2.id, vpcid=vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % ( @@ -1214,7 +1214,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1243,7 +1243,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering_no_lb.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1258,7 +1258,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -1272,7 +1272,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1282,7 +1282,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1294,7 +1294,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1304,7 +1304,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1315,7 +1315,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1347,7 +1347,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1376,7 +1376,7 @@ class TestVPC(cloudstackTestCase): listall=True, isstaticnat=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(public_ips, list), @@ -1394,7 +1394,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, vpcid=vpc.id ) @@ -1413,7 +1413,7 @@ class TestVPC(cloudstackTestCase): accountid=self.account.name, networkid=network_2.id, vpcid=vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % ( @@ -1558,7 +1558,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1574,7 +1574,7 @@ class TestVPC(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1590,7 +1590,7 @@ class TestVPC(cloudstackTestCase): src_nat_list = PublicIPAddress.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True, issourcenat=True, vpcid=vpc.id @@ -1614,7 +1614,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc_1) @@ -1628,7 +1628,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc_2) @@ -1642,7 +1642,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("%s" % vpc_3) except Exception as e: @@ -1677,7 +1677,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) self.network_offering = NetworkOffering.create( @@ -1701,7 +1701,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -1714,7 +1714,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -1729,7 +1729,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, zoneid=self.zone.id, accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -1823,7 +1823,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1852,7 +1852,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -1879,7 +1879,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkDomain=netdomain ) self.validate_vpc_network(vpc) @@ -1904,7 +1904,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -1917,7 +1917,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -2355,7 +2355,7 @@ class TestVPC(cloudstackTestCase): self.services["vpc"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.services["vpc_no_name"]["cidr"] = "10.1.1.1/16" @@ -2367,7 +2367,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) # Create VPC without zoneid param @@ -2377,7 +2377,7 @@ class TestVPC(cloudstackTestCase): self.services["vpc"], vpcofferingid=self.vpc_off.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) vpc_wo_cidr = {"name": "TestVPC_WO_CIDR", @@ -2392,7 +2392,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) @attr(tags=["advanced", "intervlan"]) @@ -2414,7 +2414,7 @@ class TestVPC(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -2439,7 +2439,7 @@ class TestVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -2671,7 +2671,7 @@ class TestVPCHostMaintenance(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc, state='Disabled') return @@ -2697,7 +2697,7 @@ class TestVPCHostMaintenance(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc, state='Disabled') interval = list_configurations( diff --git a/test/integration/component/test_vpc_host_maintenance.py b/test/integration/component/test_vpc_host_maintenance.py index 4c14f991954..1cce2764fe8 100644 --- a/test/integration/component/test_vpc_host_maintenance.py +++ b/test/integration/component/test_vpc_host_maintenance.py @@ -242,7 +242,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -258,7 +258,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -277,7 +277,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off_no_lb.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -288,7 +288,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_1.id, networkids=[str(cls.network_1.id)] ) @@ -297,7 +297,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_1.id, networkids=[str(cls.network_1.id)] ) @@ -305,14 +305,14 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_2.id, networkids=[str(cls.network_2.id)] ) routers = Router.list( cls.api_client, account=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, listall=True ) if isinstance(routers, list): @@ -376,7 +376,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_1.id, listall=True ) @@ -391,7 +391,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_2.id, listall=True ) @@ -441,7 +441,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -458,7 +458,7 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -618,7 +618,7 @@ class TestVPCNetworkRules(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -634,7 +634,7 @@ class TestVPCNetworkRules(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -653,7 +653,7 @@ class TestVPCNetworkRules(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off_no_lb.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -664,7 +664,7 @@ class TestVPCNetworkRules(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_1.id, networkids=[str(cls.network_1.id)] ) @@ -673,7 +673,7 @@ class TestVPCNetworkRules(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_2.id, networkids=[str(cls.network_1.id)] ) @@ -681,7 +681,7 @@ class TestVPCNetworkRules(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_1.id, networkids=[str(cls.network_2.id)] ) @@ -689,7 +689,7 @@ class TestVPCNetworkRules(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_2.id, networkids=[str(cls.network_2.id)] ) @@ -739,7 +739,7 @@ class TestVPCNetworkRules(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_1.id, listall=True ) @@ -754,7 +754,7 @@ class TestVPCNetworkRules(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_2.id, listall=True ) @@ -800,7 +800,7 @@ class TestVPCNetworkRules(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_1.id, vpcid=self.vpc.id ) @@ -825,7 +825,7 @@ class TestVPCNetworkRules(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_2.id, vpcid=self.vpc.id ) diff --git a/test/integration/component/test_vpc_network.py b/test/integration/component/test_vpc_network.py index 0adf9d7fcdc..c0c393c4ca1 100644 --- a/test/integration/component/test_vpc_network.py +++ b/test/integration/component/test_vpc_network.py @@ -333,7 +333,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -353,7 +353,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -426,7 +426,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -451,7 +451,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -497,7 +497,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -517,7 +517,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -588,7 +588,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -608,7 +608,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -646,7 +646,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -693,7 +693,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -744,7 +744,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -772,7 +772,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -821,7 +821,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -842,7 +842,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -890,7 +890,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -952,7 +952,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -976,7 +976,7 @@ class TestVPCNetwork(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1022,7 +1022,7 @@ class TestVPCNetwork(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1193,7 +1193,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1215,7 +1215,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.2.1.1', @@ -1255,7 +1255,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1277,7 +1277,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.2.1.1', @@ -1317,7 +1317,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1342,7 +1342,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1384,7 +1384,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1406,7 +1406,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1447,7 +1447,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1465,7 +1465,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1505,7 +1505,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1540,7 +1540,7 @@ class TestVPCNetworkRanges(cloudstackTestCase): self.apiclient, self.services["network"], accountid=account.name, - domainid=account.account.domainid, + domainid=account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1710,7 +1710,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1751,7 +1751,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_pf.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1765,7 +1765,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1774,7 +1774,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1785,7 +1785,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1804,7 +1804,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): accountid=self.account.name, networkid=network_1.id, vpcid=vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % ( @@ -1816,7 +1816,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1845,7 +1845,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): listall=True, isstaticnat=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(public_ips, list), @@ -1934,7 +1934,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -2003,7 +2003,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): ) self.debug("Checking if we can SSH into VM using NAT rule?") try: - ssh_3 = vm_3.get_ssh_client( + ssh_3 = vm_1.get_ssh_client( ipaddress=public_ip_3.ipaddress.ipaddress, reconnect=True, port=self.services["natrule"]["publicport"] @@ -2059,7 +2059,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -2099,7 +2099,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -2113,7 +2113,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -2182,7 +2182,7 @@ class TestVPCNetworkGc(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -2197,7 +2197,7 @@ class TestVPCNetworkGc(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -2208,7 +2208,7 @@ class TestVPCNetworkGc(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -2216,7 +2216,7 @@ class TestVPCNetworkGc(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -2224,7 +2224,7 @@ class TestVPCNetworkGc(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -2235,7 +2235,7 @@ class TestVPCNetworkGc(cloudstackTestCase): accountid=cls.account.name, networkid=cls.network_1.id, vpcid=cls.vpc.id, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) @@ -2243,7 +2243,7 @@ class TestVPCNetworkGc(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -2289,7 +2289,7 @@ class TestVPCNetworkGc(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) for vm in vms: @@ -2305,7 +2305,7 @@ class TestVPCNetworkGc(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) for vm in vms: @@ -2396,7 +2396,7 @@ class TestVPCNetworkGc(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -2515,7 +2515,7 @@ class TestVPCNetworkGc(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py index a24e8139b95..b4a66070d5b 100644 --- a/test/integration/component/test_vpc_network_lbrules.py +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -244,7 +244,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) return @@ -264,7 +264,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): def get_Router_For_VPC(self): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, ) self.assertEqual(isinstance(routers, list), True, @@ -287,7 +287,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, ) self.assertEqual(isinstance(routers, list), True, @@ -308,7 +308,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, zoneid=self.zone.id ) self.assertEqual(isinstance(routers, list), @@ -391,7 +391,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): public_ip = PublicIPAddress.create(self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=None, #network.id, vpcid=self.vpc.id ) @@ -420,7 +420,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) return vpc @@ -442,7 +442,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): obj_network = Network.create(self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway=gateway, @@ -460,7 +460,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)], hostid=host_id @@ -487,7 +487,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): accountid=self.account.name, networkid=network.id, vpcid=self.vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % (vmarray)) lb_rule.assign(self.apiclient, vmarray) diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py index aac956810d1..56792f49d00 100644 --- a/test/integration/component/test_vpc_network_pfrules.py +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -243,7 +243,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) return @@ -262,7 +262,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): def get_Router_For_VPC(self): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, ) self.assertEqual(isinstance(routers, list), True, @@ -285,7 +285,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, ) self.assertEqual(isinstance(routers, list), True, @@ -306,7 +306,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, zoneid=self.zone.id ) self.assertEqual(isinstance(routers, list), @@ -391,7 +391,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): public_ip = PublicIPAddress.create(self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=None, #network.id, vpcid=self.vpc.id ) @@ -420,7 +420,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) return vpc @@ -442,7 +442,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): obj_network = Network.create(self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway=gateway, @@ -460,7 +460,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)], hostid=host_id @@ -487,7 +487,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): accountid=self.account.name, networkid=network.id, vpcid=self.vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % (vmarray)) lb_rule.assign(self.apiclient, vmarray) diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py index 842d20ad089..aceca62d1fb 100644 --- a/test/integration/component/test_vpc_network_staticnatrule.py +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -243,7 +243,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): vpcofferingid=self.vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) return @@ -262,7 +262,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): def get_Router_For_VPC(self): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, ) self.assertEqual(isinstance(routers, list), True, @@ -285,7 +285,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, ) self.assertEqual(isinstance(routers, list), True, @@ -306,7 +306,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): routers = list_routers(self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, zoneid=self.zone.id ) self.assertEqual(isinstance(routers, list), @@ -391,7 +391,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): public_ip = PublicIPAddress.create(self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=None, #network.id, vpcid=self.vpc.id ) @@ -420,7 +420,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) return vpc @@ -442,7 +442,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): obj_network = Network.create(self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway=gateway, @@ -460,7 +460,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)], hostid=host_id @@ -487,7 +487,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): accountid=self.account.name, networkid=network.id, vpcid=self.vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % (vmarray)) lb_rule.assign(self.apiclient, vmarray) diff --git a/test/integration/component/test_vpc_offerings.py b/test/integration/component/test_vpc_offerings.py index 033a90522c4..4b9877506f2 100644 --- a/test/integration/component/test_vpc_offerings.py +++ b/test/integration/component/test_vpc_offerings.py @@ -315,7 +315,7 @@ class TestVPCOffering(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -340,7 +340,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -352,7 +352,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -363,7 +363,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -382,7 +382,7 @@ class TestVPCOffering(cloudstackTestCase): accountid=self.account.name, networkid=network.id, vpcid=vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Associating public IP for network: %s" % vpc.name) @@ -390,7 +390,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -438,7 +438,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -467,7 +467,7 @@ class TestVPCOffering(cloudstackTestCase): listall=True, isstaticnat=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(public_ips, list), @@ -485,7 +485,7 @@ class TestVPCOffering(cloudstackTestCase): # self.apiclient, # accountid=self.account.name, # zoneid=self.zone.id, -# domainid=self.account.account.domainid, +# domainid=self.account.domainid, # networkid=network.id, # vpcid=vpc.id # ) @@ -502,7 +502,7 @@ class TestVPCOffering(cloudstackTestCase): # self.apiclient, # publicipid=public_ip_4.ipaddress.id, # account=self.account.name, -# domainid=self.account.account.domainid, +# domainid=self.account.domainid, # networkid=network.id, # vpcid=vpc.id # ) @@ -516,7 +516,7 @@ class TestVPCOffering(cloudstackTestCase): # username="root", # password="password", # account=self.account.name, -# domainid=self.account.account.domainid +# domainid=self.account.domainid # ) # except Exception as e: # self.fail("Failed to create VPN user: %s" % e) @@ -525,7 +525,7 @@ class TestVPCOffering(cloudstackTestCase): # remote_vpns = Vpn.list( # self.apiclient, # account=self.account.name, -# domainid=self.account.account.domainid, +# domainid=self.account.domainid, # publicipid=public_ip_4.ipaddress.id, # listall=True # ) @@ -596,7 +596,7 @@ class TestVPCOffering(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -612,7 +612,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -626,7 +626,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -637,7 +637,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -715,7 +715,7 @@ class TestVPCOffering(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -731,7 +731,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -745,7 +745,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -756,7 +756,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -836,7 +836,7 @@ class TestVPCOffering(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -852,7 +852,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id, gateway=gateway, @@ -864,7 +864,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -875,7 +875,7 @@ class TestVPCOffering(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network.id, vpcid=vpc.id ) @@ -975,7 +975,7 @@ class TestVPCOffering(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("VPC network creation failed! (Test succeeded)") self.debug("Enabling the VPC offering created") @@ -989,7 +989,7 @@ class TestVPCOffering(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) diff --git a/test/integration/component/test_vpc_routers.py b/test/integration/component/test_vpc_routers.py index 55cb513130f..7dc95e826e3 100644 --- a/test/integration/component/test_vpc_routers.py +++ b/test/integration/component/test_vpc_routers.py @@ -214,7 +214,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls._cleanup.append(cls.service_offering) @@ -361,7 +361,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -436,7 +436,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -483,7 +483,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -499,7 +499,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -520,7 +520,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -548,7 +548,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -581,7 +581,7 @@ class TestVPCRoutersBasic(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) router = routers[0] @@ -639,7 +639,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -656,7 +656,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): cls.apiclient, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -668,7 +668,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): cls.apiclient, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -676,7 +676,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): cls.apiclient, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -686,7 +686,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): cls.apiclient, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -694,14 +694,14 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): vms = VirtualMachine.list( cls.apiclient, account=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, listall=True ) public_ip_1 = PublicIPAddress.create( cls.apiclient, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -727,7 +727,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): cls.apiclient, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -748,7 +748,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): listall=True, isstaticnat=True, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) # cls.assertEqual( # isinstance(public_ips, list), @@ -766,7 +766,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): cls.apiclient, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -779,7 +779,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): accountid=cls.account.name, networkid=cls.network_1.id, vpcid=cls.vpc.id, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) lb_rule.assign(cls.apiclient, [vm_3]) @@ -918,56 +918,19 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): self.debug("VPC network validated - %s" % network.name) return - try: - ssh_1 = self.vm_1.get_ssh_client( - ipaddress=self.public_ip_1.ipaddress.ipaddress) - self.debug("SSH into VM is successfully") - - self.debug("Verifying if we can ping to outside world from VM?") - # Ping to outsite world - res = ssh_1.execute("ping -c 1 www.google.com") - # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): - # icmp_req=1 ttl=57 time=25.9 ms - # --- www.l.google.com ping statistics --- - # 1 packets transmitted, 1 received, 0% packet loss, time 0ms - # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms - result = str(res) - self.assertEqual( - result.count("1 received"), - 1, - "Ping to outside world from VM should be successful" - ) - - self.debug("We should be allowed to ping virtual gateway") - self.debug("VM gateway: %s" % self.vm_1.nic[0].gateway) - - res = ssh_1.execute("ping -c 1 %s" % self.vm_1.nic[0].gateway) - self.debug("ping -c 1 %s: %s" % (self.vm_1.nic[0].gateway, res)) - - result = str(res) - self.assertEqual( - result.count("1 received"), - 1, - "Ping to VM gateway should be successful" - ) - except Exception as e: - self.fail("Failed to SSH into VM - %s, %s" % - (self.public_ip_1.ipaddress.ipaddress, e)) - return - def validate_network_rules(self): """ Validate network rules """ vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) public_ips = PublicIPAddress.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) for vm, public_ip in zip(vms, public_ips): @@ -1086,7 +1049,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1180,7 +1143,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1247,7 +1210,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1263,7 +1226,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1306,7 +1269,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1351,7 +1314,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1384,7 +1347,7 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) router = routers[0] diff --git a/test/integration/component/test_vpc_vm_life_cycle.py b/test/integration/component/test_vpc_vm_life_cycle.py index 13726c58ce4..7658bebe2e2 100644 --- a/test/integration/component/test_vpc_vm_life_cycle.py +++ b/test/integration/component/test_vpc_vm_life_cycle.py @@ -237,7 +237,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -253,7 +253,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -272,7 +272,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off_no_lb.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -283,7 +283,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -292,7 +292,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -300,7 +300,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_2.id)] ) @@ -309,7 +309,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -320,7 +320,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): accountid=cls.account.name, networkid=cls.network_1.id, vpcid=cls.vpc.id, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) @@ -328,7 +328,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -516,7 +516,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -966,7 +966,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -982,7 +982,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -1006,7 +1006,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.shared_nw_off.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -1017,7 +1017,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id), str(cls.network_2.id)] @@ -1027,7 +1027,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id), str(cls.network_2.id)] @@ -1036,7 +1036,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id), str(cls.network_2.id)] @@ -1045,7 +1045,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -1056,7 +1056,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): accountid=cls.account.name, networkid=cls.network_1.id, vpcid=cls.vpc.id, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2, cls.vm_3]) @@ -1064,7 +1064,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -1242,7 +1242,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1368,7 +1368,7 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1773,7 +1773,7 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -1789,7 +1789,7 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -1809,7 +1809,7 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off_no_lb.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -1965,7 +1965,7 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_1.id), str(self.network_2.id)] @@ -1990,7 +1990,7 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_1.id, listall=True ) @@ -2033,7 +2033,7 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_1.id)] ) @@ -2111,7 +2111,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -2127,7 +2127,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -2146,7 +2146,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off_no_lb.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -2157,7 +2157,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -2166,7 +2166,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_1.id)] ) @@ -2174,7 +2174,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, networkids=[str(cls.network_2.id)] ) @@ -2183,7 +2183,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -2194,7 +2194,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): accountid=cls.account.name, networkid=cls.network_1.id, vpcid=cls.vpc.id, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) @@ -2202,7 +2202,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -2405,7 +2405,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -2868,7 +2868,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, account=cls.account.name, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.nw_off = NetworkOffering.create( @@ -2884,7 +2884,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off.id, zoneid=cls.zone.id, gateway='10.1.1.1', @@ -2903,7 +2903,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, cls.services["network"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkofferingid=cls.nw_off_no_lb.id, zoneid=cls.zone.id, gateway='10.1.2.1', @@ -2914,7 +2914,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_1.id, networkids=[str(cls.network_1.id)] ) @@ -2923,7 +2923,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_1.id, networkids=[str(cls.network_1.id)] ) @@ -2931,7 +2931,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering_2.id, networkids=[str(cls.network_2.id)] ) @@ -2940,7 +2940,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -2951,7 +2951,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): accountid=cls.account.name, networkid=cls.network_1.id, vpcid=cls.vpc.id, - domainid=cls.account.account.domainid + domainid=cls.account.domainid ) cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) @@ -2959,7 +2959,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, networkid=cls.network_1.id, vpcid=cls.vpc.id ) @@ -3057,7 +3057,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_1.id, listall=True ) @@ -3072,7 +3072,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=self.network_2.id, listall=True ) @@ -3204,7 +3204,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( diff --git a/test/integration/component/test_vpc_vms_deployment.py b/test/integration/component/test_vpc_vms_deployment.py index 506ae348867..c49ef458a40 100644 --- a/test/integration/component/test_vpc_vms_deployment.py +++ b/test/integration/component/test_vpc_vms_deployment.py @@ -320,7 +320,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -339,7 +339,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -363,7 +363,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -378,7 +378,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.3.1', @@ -392,7 +392,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -404,7 +404,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -415,7 +415,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_3.id)] ) @@ -425,7 +425,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -468,7 +468,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, state="Running", listall=True ) @@ -535,7 +535,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -554,7 +554,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -578,7 +578,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -593,7 +593,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.3.1', @@ -607,7 +607,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -619,7 +619,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -630,7 +630,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_3.id)] ) @@ -640,7 +640,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -720,7 +720,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, state="Running", listall=True ) @@ -788,7 +788,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -807,7 +807,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -831,7 +831,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -846,7 +846,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.3.1', @@ -860,7 +860,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -872,7 +872,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -883,7 +883,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_3.id)] ) @@ -893,7 +893,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -965,7 +965,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.4.1', @@ -978,7 +978,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_4.id)] ) @@ -989,7 +989,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, state="Running", listall=True ) @@ -1057,7 +1057,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1076,7 +1076,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1100,7 +1100,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -1115,7 +1115,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.3.1', @@ -1129,7 +1129,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1141,7 +1141,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1152,7 +1152,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_3.id)] ) @@ -1162,7 +1162,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1236,7 +1236,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.4.1', @@ -1249,7 +1249,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_4.id)] ) @@ -1283,7 +1283,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, state="Running", listall=True ) @@ -1337,7 +1337,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1360,7 +1360,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.0.1', @@ -1399,7 +1399,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway=gateway, @@ -1417,7 +1417,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway=gateway, @@ -1436,7 +1436,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway=gateway, @@ -1453,7 +1453,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network.id)] ) @@ -1512,7 +1512,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1531,7 +1531,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1555,7 +1555,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -1569,7 +1569,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1578,7 +1578,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1590,7 +1590,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1599,7 +1599,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1609,7 +1609,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1650,7 +1650,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, listall=True ) @@ -1685,7 +1685,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, listall=True ) @@ -1704,7 +1704,7 @@ class TestVMDeployVPC(cloudstackTestCase): routers = Router.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1777,7 +1777,7 @@ class TestVMDeployVPC(cloudstackTestCase): vpcofferingid=vpc_off.id, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.validate_vpc_network(vpc) @@ -1796,7 +1796,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off.id, zoneid=self.zone.id, gateway='10.1.1.1', @@ -1820,7 +1820,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["network"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkofferingid=nw_off_no_lb.id, zoneid=self.zone.id, gateway='10.1.2.1', @@ -1834,7 +1834,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1843,7 +1843,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_1.id)] ) @@ -1855,7 +1855,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1864,7 +1864,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], accountid=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, networkids=[str(network_2.id)] ) @@ -1874,7 +1874,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, listall=True ) self.assertEqual( @@ -1895,7 +1895,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1927,7 +1927,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, vpcid=vpc.id ) @@ -1956,7 +1956,7 @@ class TestVMDeployVPC(cloudstackTestCase): listall=True, isstaticnat=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(public_ips, list), @@ -1974,7 +1974,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, vpcid=vpc.id ) @@ -1993,7 +1993,7 @@ class TestVMDeployVPC(cloudstackTestCase): accountid=self.account.name, networkid=network_2.id, vpcid=vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % ( @@ -2066,7 +2066,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, vpcid=vpc.id ) @@ -2098,7 +2098,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, vpcid=vpc.id ) @@ -2127,7 +2127,7 @@ class TestVMDeployVPC(cloudstackTestCase): listall=True, isstaticnat=True, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( isinstance(public_ips, list), @@ -2145,7 +2145,7 @@ class TestVMDeployVPC(cloudstackTestCase): self.apiclient, accountid=self.account.name, zoneid=self.zone.id, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_2.id, vpcid=vpc.id ) @@ -2164,7 +2164,7 @@ class TestVMDeployVPC(cloudstackTestCase): accountid=self.account.name, networkid=network_2.id, vpcid=vpc.id, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.debug("Adding virtual machines %s and %s to LB rule" % ( @@ -2339,7 +2339,7 @@ class TestVMDeployVPC(cloudstackTestCase): vms = VirtualMachine.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid, + domainid=self.account.domainid, networkid=network_1.id, listall=True ) @@ -2447,7 +2447,7 @@ class TestVMDeployVPC(cloudstackTestCase): networks = Network.list( self.apiclient, account=self.account.name, - domainid=self.account.account.domainid + domainid=self.account.domainid ) self.assertEqual( networks, diff --git a/test/integration/component/test_vpn_users.py b/test/integration/component/test_vpn_users.py index 8f08fa09c38..fe020d0f555 100644 --- a/test/integration/component/test_vpn_users.py +++ b/test/integration/component/test_vpn_users.py @@ -396,7 +396,7 @@ class TestVPNUsers(cloudstackTestCase): DomainName=self.account.domain) self.debug("Adding new user to VPN as a global admin: %s" % - admin.account.name) + admin.name) try: self.create_VPN_Users(api_client=api_client) except Exception as e: @@ -438,7 +438,7 @@ class TestVPNUsers(cloudstackTestCase): DomainName=self.account.domain) self.debug("Adding new user to VPN as a domain admin: %s" % - admin.account.name) + admin.name) try: self.create_VPN_Users(api_client=api_client) except Exception as e: diff --git a/test/integration/smoke/test_deploy_vm.py b/test/integration/smoke/test_deploy_vm.py index 5c8e0636cff..425aeb749d2 100644 --- a/test/integration/smoke/test_deploy_vm.py +++ b/test/integration/smoke/test_deploy_vm.py @@ -31,6 +31,8 @@ from marvin.integration.lib.utils import cleanup_resources #common - commonly used methods for all tests are listed here from marvin.integration.lib.common import get_zone, get_domain, get_template +from nose.plugins.attrib import attr + class TestData(object): """Test data object that is required to create resources """ @@ -94,6 +96,7 @@ class TestDeployVM(cloudstackTestCase): self.account ] + @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) def test_deploy_vm(self): """Test Deploy Virtual Machine diff --git a/test/integration/smoke/test_deploy_vm_with_userdata.py b/test/integration/smoke/test_deploy_vm_with_userdata.py index 8ca9bd05a2d..260106cbb0f 100644 --- a/test/integration/smoke/test_deploy_vm_with_userdata.py +++ b/test/integration/smoke/test_deploy_vm_with_userdata.py @@ -105,13 +105,13 @@ class TestDeployVmWithUserData(cloudstackTestCase): vms = list_virtual_machines( self.apiClient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + id=deployVmResponse.id ) self.assert_(len(vms) > 0, "There are no Vms deployed in the account %s" % self.account.name) vm = vms[0] self.assert_(vm.id == str(deployVmResponse.id), "Vm deployed is different from the test") self.assert_(vm.state == "Running", "VM is not in Running state") - self.cleanup.append(deployVmResponse) @attr(tags=["simulator", "devcloud", "basic", "advanced"]) def test_deployvm_userdata(self): @@ -129,13 +129,13 @@ class TestDeployVmWithUserData(cloudstackTestCase): vms = list_virtual_machines( self.apiClient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + id=deployVmResponse.id ) self.assert_(len(vms) > 0, "There are no Vms deployed in the account %s" % self.account.name) vm = vms[0] self.assert_(vm.id == str(deployVmResponse.id), "Vm deployed is different from the test") self.assert_(vm.state == "Running", "VM is not in Running state") - self.cleanup.append(deployVmResponse) @classmethod def tearDownClass(cls): diff --git a/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py b/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py index d904a4cb7d8..67532c78d0f 100644 --- a/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py +++ b/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py @@ -1,164 +1,250 @@ -# 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. - -#!/usr/bin/env python - -import marvin -from marvin import cloudstackTestCase -from marvin.cloudstackTestCase import * - -import unittest -import hashlib -import random - -class TestDeployVmWithVariedPlanners(cloudstackTestCase): - """ - This test tests that we can create serviceOfferings with different deployment Planners and deploy virtual machines into a user account - using these service offerings and builtin template - """ - def setUp(self): - """ - CloudStack internally saves its passwords in md5 form and that is how we - specify it in the API. Python's hashlib library helps us to quickly hash - strings as follows - """ - mdf = hashlib.md5() - mdf.update('password') - mdf_pass = mdf.hexdigest() - - self.apiClient = self.testClient.getApiClient() #Get ourselves an API client - - self.acct = createAccount.createAccountCmd() #The createAccount command - self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1 - self.acct.firstname = 'test' - self.acct.lastname = 'user' #What's up doc? - self.acct.username = 'testuser' - self.acct.password = mdf_pass #The md5 hashed password string - self.acct.email = 'test@domain.com' - self.acct.account = 'testacct' - self.acct.domainid = 1 #The default ROOT domain - self.acctResponse = self.apiClient.createAccount(self.acct) - # And upon successful creation we'll log a helpful message in our logs - # using the default debug logger of the test framework - self.debug("successfully created account: %s, id: \ - %s"%(self.acctResponse.name, \ - self.acctResponse.id)) - - #Create service offerings with varied planners - self.svcOfferingFirstFit = createServiceOffering.createServiceOfferingCmd() - self.svcOfferingFirstFit.name = 'Tiny Instance FirstFit' - self.svcOfferingFirstFit.displaytext = 'Tiny Instance with FirstFitPlanner' - self.svcOfferingFirstFit.cpuspeed = 100 - self.svcOfferingFirstFit.cpunumber = 1 - self.svcOfferingFirstFit.memory = 256 - self.svcOfferingFirstFit.deploymentplanner = 'FirstFitPlanner' - self.svcOfferingFirstFitResponse = self.apiClient.createServiceOffering(self.svcOfferingFirstFit) - - self.debug("successfully created serviceofferring name: %s, id: \ - %s, deploymentPlanner: %s"%(self.svcOfferingFirstFitResponse.name, \ - self.svcOfferingFirstFitResponse.id,self.svcOfferingFirstFitResponse.deploymentplanner)) - - #Create service offerings with varied planners - self.svcOfferingUserDispersing = createServiceOffering.createServiceOfferingCmd() - self.svcOfferingUserDispersing.name = 'Tiny Instance UserDispersing' - self.svcOfferingUserDispersing.displaytext = 'Tiny Instance with UserDispersingPlanner' - self.svcOfferingUserDispersing.cpuspeed = 100 - self.svcOfferingUserDispersing.cpunumber = 1 - self.svcOfferingUserDispersing.memory = 256 - self.svcOfferingUserDispersing.deploymentplanner = 'FirstFitPlanner' - self.svcOfferingUserDispersingResponse = self.apiClient.createServiceOffering(self.svcOfferingUserDispersing) - - self.debug("successfully created serviceofferring name: %s, id: \ - %s, deploymentPlanner: %s"%(self.svcOfferingUserDispersingResponse.name, \ - self.svcOfferingUserDispersingResponse.id,self.svcOfferingUserDispersingResponse.deploymentplanner)) - - def test_DeployVm(self): - """ - Let's start by defining the attributes of our VM that we will be - deploying on CloudStack. We will be assuming a single zone is available - and is configured and all templates are Ready - - The hardcoded values are used only for brevity. - """ - deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd() - deployVmCmd.zoneid = 1 - deployVmCmd.account = self.acct.account - deployVmCmd.domainid = self.acct.domainid - deployVmCmd.templateid = 5 #For default template- CentOS 5.6(64 bit) - deployVmCmd.serviceofferingid = self.svcOfferingFirstFitResponse.id - - deployVmResponse = self.apiClient.deployVirtualMachine(deployVmCmd) - self.debug("VM %s was deployed in the job %s"%(deployVmResponse.id, deployVmResponse.jobid)) - - # At this point our VM is expected to be Running. Let's find out what - # listVirtualMachines tells us about VMs in this account - - listVmCmd = listVirtualMachines.listVirtualMachinesCmd() - listVmCmd.id = deployVmResponse.id - listVmResponse = self.apiClient.listVirtualMachines(listVmCmd) - - self.assertNotEqual(len(listVmResponse), 0, "Check if the list API \ - returns a non-empty response") - - vm1 = listVmResponse[0] - - self.assertEqual(vm1.id, deployVmResponse.id, "Check if the VM returned \ - is the same as the one we deployed") - self.assertEqual(vm1.state, "Running", "Check if VM has reached \ - a state of running") - - - deployVm2Cmd = deployVirtualMachine.deployVirtualMachineCmd() - deployVm2Cmd.zoneid = 1 - deployVm2Cmd.account = self.acct.account - deployVm2Cmd.domainid = self.acct.domainid - deployVm2Cmd.templateid = 5 #For default template- CentOS 5.6(64 bit) - deployVm2Cmd.serviceofferingid = self.svcOfferingFirstFitResponse.id - - deployVm2Response = self.apiClient.deployVirtualMachine(deployVm2Cmd) - self.debug("VM %s was deployed in the job %s"%(deployVm2Response.id, deployVm2Response.jobid)) - - # At this point our VM is expected to be Running. Let's find out what - # listVirtualMachines tells us about VMs in this account - - listVm2Cmd = listVirtualMachines.listVirtualMachinesCmd() - listVm2Cmd.id = deployVm2Response.id - listVm2Response = self.apiClient.listVirtualMachines(listVm2Cmd) - self.assertNotEqual(len(listVm2Response), 0, "Check if the list API \ - returns a non-empty response") - vm2 = listVm2Response[0] - self.assertEqual(vm2.id, deployVm2Response.id, "Check if the VM returned \ - is the same as the one we deployed") - self.assertEqual(vm2.state, "Running", "Check if VM has reached \ - a state of running") - - - def tearDown(self): # Teardown will delete the Account as well as the VM once the VM reaches "Running" state - """ - And finally let us cleanup the resources we created by deleting the - account. All good unittests are atomic and rerunnable this way - """ - deleteAcct = deleteAccount.deleteAccountCmd() - deleteAcct.id = self.acctResponse.id - self.apiClient.deleteAccount(deleteAcct) - deleteSvcOfferingFirstFit = deleteServiceOffering.deleteServiceOfferingCmd() - deleteSvcOfferingFirstFit.id = self.svcOfferingFirstFitResponse.id - self.apiClient.deleteServiceOffering(deleteSvcOfferingFirstFit); - deleteSvcOfferingUserDispersing = deleteServiceOffering.deleteServiceOfferingCmd() - deleteSvcOfferingUserDispersing.id = self.svcOfferingUserDispersingResponse.id - self.apiClient.deleteServiceOffering(deleteSvcOfferingUserDispersing); - \ No newline at end of file +# 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. + +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering +from marvin.integration.lib.common import get_zone, get_domain, get_template, cleanup_resources + +from nose.plugins.attrib import attr + +class Services: + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Planner Service Offering", + "displaytext": "Planner Service Offering", + "cpunumber": 1, + "cpuspeed": 100, + # in MHz + "memory": 128, + # In MBs + }, + "ostype": 'CentOS 5.3 (64-bit)', + "virtual_machine": { + "hypervisor": "XenServer", + } + } + + +class TestDeployVmWithVariedPlanners(cloudstackTestCase): + """ Test to create services offerings for deployment planners + - firstfit, userdispersing + """ + + @classmethod + def setUpClass(cls): + cls.apiclient = super(TestDeployVmWithVariedPlanners, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient, cls.services) + cls.zone = get_zone(cls.apiclient, cls.services) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["template"] = cls.template.id + cls.services["zoneid"] = cls.zone.id + + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.name + cls.cleanup = [ + cls.account + ] + + @attr(tags=["simulator", "advanced", "basic", "sg"]) + def test_deployvm_firstfit(self): + """Test to deploy vm with a first fit offering + """ + #FIXME: How do we know that first fit actually happened? + self.service_offering_firstfit = ServiceOffering.create( + self.apiclient, + self.services["service_offering"], + deploymentplanner='FirstFitPlanner' + ) + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_firstfit.id, + templateid=self.template.id + ) + + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s"\ + % self.virtual_machine.id + ) + self.assertEqual( + isinstance(list_vms, list), + True, + "List VM response was not a valid list" + ) + self.assertNotEqual( + len(list_vms), + 0, + "List VM response was empty" + ) + + vm = list_vms[0] + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + @attr(tags=["simulator", "advanced", "basic", "sg"]) + def test_deployvm_userdispersing(self): + """Test deploy VMs using user dispersion planner + """ + self.service_offering_userdispersing = ServiceOffering.create( + self.apiclient, + self.services["service_offering"], + deploymentplanner='UserDispersingPlanner' + ) + + self.virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_userdispersing.id, + templateid=self.template.id + ) + self.virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_userdispersing.id, + templateid=self.template.id + ) + + list_vm_1 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_1.id) + list_vm_2 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_2.id) + self.assertEqual( + isinstance(list_vm_1, list), + True, + "List VM response was not a valid list" + ) + self.assertEqual( + isinstance(list_vm_2, list), + True, + "List VM response was not a valid list" + ) + vm1 = list_vm_1[0] + vm2 = list_vm_2[0] + self.assertEqual( + vm1.state, + "Running", + msg="VM is not in Running state" + ) + self.assertEqual( + vm2.state, + "Running", + msg="VM is not in Running state" + ) + self.assertNotEqual( + vm1.hostid, + vm2.hostid, + msg="VMs meant to be dispersed are deployed on the same host" + ) + + @attr(tags=["simulator", "advanced", "basic", "sg"]) + def test_deployvm_userconcentrated(self): + """Test deploy VMs using user concentrated planner + """ + self.service_offering_userconcentrated = ServiceOffering.create( + self.apiclient, + self.services["service_offering"], + deploymentplanner='UserConcentratedPodPlanner' + ) + + self.virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_userconcentrated.id, + templateid=self.template.id + ) + self.virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_userconcentrated.id, + templateid=self.template.id + ) + + list_vm_1 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_1.id) + list_vm_2 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_2.id) + self.assertEqual( + isinstance(list_vm_1, list), + True, + "List VM response was not a valid list" + ) + self.assertEqual( + isinstance(list_vm_2, list), + True, + "List VM response was not a valid list" + ) + vm1 = list_vm_1[0] + vm2 = list_vm_2[0] + self.assertEqual( + vm1.state, + "Running", + msg="VM is not in Running state" + ) + self.assertEqual( + vm2.state, + "Running", + msg="VM is not in Running state" + ) + self.assertNotEqual( + vm1.hostid, + vm2.hostid, + msg="VMs meant to be concentrated are deployed on the different hosts" + ) + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiclient, cls.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index ad4a8f280d1..c645d3b055d 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -202,11 +202,9 @@ class TestISO(cloudstackTestCase): cls.services["sourcezoneid"] = cls.zone.id #populate second zone id for iso copy cmd = listZones.listZonesCmd() - zones = cls.api_client.listZones(cmd) - if not isinstance(zones, list): + cls.zones = cls.api_client.listZones(cmd) + if not isinstance(cls.zones, list): raise Exception("Failed to find zones.") - if len(zones) >= 2: - cls.services["destzoneid"] = zones[1].id #Create an account, ISOs etc. cls.account = Account.create( @@ -484,6 +482,10 @@ class TestISO(cloudstackTestCase): #Validate the following #1. copy ISO should be successful and secondary storage # should contain new copied ISO. + if len(self.zones) <= 1: + self.skipTest("Not enough zones available to perform copy template") + + self.services["destzoneid"] = filter(lambda z: z.id != self.zone.id, self.zones)[0] self.debug("Copy ISO from %s to %s" % ( self.zone.id, diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 4a7bb44da2c..61ddf46e9ef 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -18,6 +18,7 @@ """ #Import Local Modules import marvin +from marvin.cloudstackException import cloudstackAPIException from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin import remoteSSHClient @@ -447,16 +448,14 @@ class TestPortForwarding(cloudstackTestCase): nat_rule.delete(self.apiclient) - list_nat_rule_response = list_nat_rules( + try: + list_nat_rule_response = list_nat_rules( self.apiclient, id=nat_rule.id ) + except cloudstackAPIException: + self.debug("Nat Rule is deleted") - self.assertEqual( - list_nat_rule_response, - None, - "Check Port Forwarding Rule is deleted" - ) # Check if the Public SSH port is inaccessible with self.assertRaises(Exception): self.debug( @@ -565,15 +564,14 @@ class TestPortForwarding(cloudstackTestCase): nat_rule.delete(self.apiclient) - list_nat_rule_response = list_nat_rules( + try: + list_nat_rule_response = list_nat_rules( self.apiclient, id=nat_rule.id ) - self.assertEqual( - list_nat_rule_response, - None, - "Check Port Forwarding Rule is deleted" - ) + except cloudstackAPIException: + self.debug("Nat Rule is deleted") + # Check if the Public SSH port is inaccessible with self.assertRaises(Exception): self.debug( @@ -785,7 +783,6 @@ class TestLoadBalancingRule(cloudstackTestCase): "SSH into VM (IPaddress: %s) & NAT Rule (Public IP: %s)" % (self.vm_1.ipaddress, src_nat_ip_addr.ipaddress) ) - ssh_1 = remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], @@ -1582,32 +1579,28 @@ class TestReleaseIP(cloudstackTestCase): "Check if disassociated IP Address is no longer available" ) + self.debug("List NAT Rule response" + str(list_nat_rule)) # ListPortForwardingRules should not list # associated rules with Public IP address - list_nat_rule = list_nat_rules( + try: + list_nat_rule = list_nat_rules( self.apiclient, id=self.nat_rule.id ) - self.debug("List NAT Rule response" + str(list_nat_rule)) - self.assertEqual( - list_nat_rule, - None, - "Check if PF rules are no longer available for IP address" - ) + except cloudstackAPIException: + self.debug("Port Forwarding Rule is deleted") # listLoadBalancerRules should not list # associated rules with Public IP address - list_lb_rule = list_lb_rules( + self.debug("List LB Rule response" + str(list_lb_rule)) + try: + list_lb_rule = list_lb_rules( self.apiclient, id=self.lb_rule.id ) - self.debug("List LB Rule response" + str(list_lb_rule)) - self.assertEqual( - list_lb_rule, - None, - "Check if LB rules for IP Address are no longer available" - ) + except cloudstackAPIException: + self.debug("Port Forwarding Rule is deleted") # SSH Attempt though public IP should fail with self.assertRaises(Exception): @@ -1720,16 +1713,9 @@ class TestDeleteAccount(cloudstackTestCase): account=self.account.name, domainid=self.account.domainid ) - self.assertEqual( - list_lb_reponse, - None, - "Check load balancing rule is properly deleted." - ) - except Exception as e: + except cloudstackAPIException: + self.debug("Port Forwarding Rule is deleted") - raise Exception( - "Exception raised while fetching LB rules for account: %s" % - self.account.name) # ListPortForwardingRules should not # list associated rules with deleted account try: @@ -1738,16 +1724,9 @@ class TestDeleteAccount(cloudstackTestCase): account=self.account.name, domainid=self.account.domainid ) - self.assertEqual( - list_nat_reponse, - None, - "Check load balancing rule is properly deleted." - ) - except Exception as e: + except cloudstackAPIException: + self.debug("NATRule is deleted") - raise Exception( - "Exception raised while fetching NAT rules for account: %s" % - self.account.name) #Retrieve router for the user account try: routers = list_routers( diff --git a/test/integration/smoke/test_nic.py b/test/integration/smoke/test_nic.py index bae6dfda15d..8e8d3407dfb 100644 --- a/test/integration/smoke/test_nic.py +++ b/test/integration/smoke/test_nic.py @@ -79,11 +79,35 @@ class Services: "PortForwarding": 'VirtualRouter', }, }, + "network_offering_shared": { + "name": 'Test Network offering shared', + "displaytext": 'Test Network offering Shared', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "traffictype": 'GUEST', + "specifyVlan" : "True", + "specifyIpRanges" : "True", + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter', + }, + }, "network": { "name": "Test Network", "displaytext": "Test Network", "acltype": "Account", }, + "network2": { + "name": "Test Network Shared", + "displaytext": "Test Network Shared", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype": "Account", + }, # ISO settings for Attach/Detach ISO tests "iso": { "displaytext": "Test ISO", @@ -176,6 +200,14 @@ class TestDeployVM(cloudstackTestCase): self.network_offering.update(self.apiclient, state='Enabled') # Enable Network offering self.services["network"]["networkoffering"] = self.network_offering.id + self.network_offering_shared = NetworkOffering.create( + self.apiclient, + self.services["network_offering_shared"], + ) + self.cleanup.insert(0, self.network_offering_shared) + self.network_offering_shared.update(self.apiclient, state='Enabled') # Enable Network offering + self.services["network2"]["networkoffering"] = self.network_offering_shared.id + ################ ### Test Network self.test_network = Network.create( @@ -185,6 +217,14 @@ class TestDeployVM(cloudstackTestCase): self.account.domainid, ) self.cleanup.insert(0, self.test_network) + self.test_network2 = Network.create( + self.apiclient, + self.services["network2"], + self.account.name, + self.account.domainid, + zoneid=self.services["network"]["zoneid"] + ) + self.cleanup.insert(0, self.test_network2) except Exception as ex: self.debug("Exception during NIC test SETUP!: " + str(ex)) self.assertEqual(True, False, "Exception during NIC test SETUP!: " + str(ex)) @@ -201,10 +241,10 @@ class TestDeployVM(cloudstackTestCase): accountid=self.account.name, domainid=self.account.domainid, serviceofferingid=self.service_offering.id, - mode=self.services['mode'] + mode=self.services['mode'], + networkids=[self.test_network.id] ) self.cleanup.insert(0, self.virtual_machine) - list_vm_response = list_virtual_machines( self.apiclient, id=self.virtual_machine.id @@ -256,7 +296,7 @@ class TestDeployVM(cloudstackTestCase): existing_nic_id = vm_response.nic[0].id # 1. add a nic - add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network.id) + add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network2.id) time.sleep(5) # now go get the vm list? @@ -308,8 +348,9 @@ class TestDeployVM(cloudstackTestCase): sawException = True self.assertEqual(sawException, True, "Make sure we cannot delete the default NIC") - - self.virtual_machine.remove_nic(self.apiclient, existing_nic_id) + self.virtual_machine.update_default_nic(self.apiclient, existing_nic_id) + time.sleep(5) + self.virtual_machine.remove_nic(self.apiclient, new_nic_id) time.sleep(5) list_vm_response = list_virtual_machines( diff --git a/test/integration/smoke/test_portable_publicip.py b/test/integration/smoke/test_portable_publicip.py new file mode 100644 index 00000000000..5b2fbc7e307 --- /dev/null +++ b/test/integration/smoke/test_portable_publicip.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python +# 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. + +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 * +from marvin import remoteSSHClient +from nose.plugins.attrib import attr + +class Services: + """Test Data + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + # in MHz + "memory": 128, + # In MBs + }, + "network_offering": { + "name": 'Test Network offering', + "displaytext": 'Test Network offering', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + }, + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + }, + "ostype": 'CentOS 5.3 (64-bit)', + "gateway" : "10.1.1.1", + "netmask" : "255.255.255.0", + "startip" : "10.1.1.10", + "endip" : "10.1.1.20", + "regionid" : "1", + "vlan" :"10", + "isportable" : "true", + "virtual_machine" : { + "affinity": { + "name": "webvms", + "type": "host anti-affinity", + }, + "hypervisor" : "XenServer", + } + } + +class TestPortablePublicIPRange(cloudstackTestCase): + + """ + This test validates functionality where + - admin can provision a portable public ip range + - list provisioned portable public ip range + - delete provisioned portable public ip range + """ + @classmethod + def setUpClass(cls): + cls.api_client = super(TestPortablePublicIPRange, 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", "basic", "advanced", "portablepublicip"]) + def test_createPortablePublicIPRange(self): + """ Test to create a portable public ip range + """ + self.debug("attempting to create a portable Public IP range") + self.portable_ip_range = PortablePublicIpRange.create( + self.api_client, + self.services + ) + self.debug("attempting to verify portable Public IP range is created") + list_portbale_ip_range_response = PortablePublicIpRange.list( + self.apiclient, + id=self.portable_ip_range.id + ) + self.portable_ip_range.delete(self.apiclient) + return + + +class TestPortablePublicIPAcquire(cloudstackTestCase): + """ + This test validates functionality where + - admin has provisioned a portable public ip range + - user can acquire portable ip from the provisioned ip range + """ + @classmethod + def setUpClass(cls): + cls.api_client = super(TestPortablePublicIPAcquire, 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.services["network"]["zoneid"] = cls.zone.id + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + + cls.services["network"]["networkoffering"] = cls.network_offering.id + cls.account_network = Network.create( + cls.api_client, + cls.services["network"], + cls.account.name, + cls.account.domainid + ) + cls._cleanup = [ + cls.account_network, + cls.network_offering, + 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", "basic", "advanced", "portablepublicip"]) + def test_createPortablePublicIPAcquire(self): + """ Test to acquire a provisioned public ip range + """ + self.debug("attempting to create a portable Public IP range") + self.portable_ip_range = PortablePublicIpRange.create( + self.api_client, + self.services + ) + + ip_address = PublicIPAddress.create(self.api_client, self.account.name, self.zone.id, self.account.domainid) + + self.portable_ip_range.delete(self.apiclient) + return \ No newline at end of file diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py index f2099ff432a..e1d78d99d15 100644 --- a/test/integration/smoke/test_public_ip_range.py +++ b/test/integration/smoke/test_public_ip_range.py @@ -52,11 +52,11 @@ class Services: "vlan": "4444", } -class TesDedicatePublicIPRange(cloudstackTestCase): +class TestDedicatePublicIPRange(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TesDedicatePublicIPRange, cls).getClsTestClient().getApiClient() + cls.api_client = super(TestDedicatePublicIPRange, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain cls.domain = get_domain(cls.api_client, cls.services) @@ -96,7 +96,7 @@ class TesDedicatePublicIPRange(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "publiciprange", "dedicate", "release"]) + @attr(tags = ["simulator", "advanced", "publiciprange", "dedicate", "release"]) def test_dedicatePublicIpRange(self): """Test public IP range dedication """ diff --git a/test/integration/smoke/test_pvlan.py b/test/integration/smoke/test_pvlan.py index 4eb76e1cdb7..0a427ba229d 100644 --- a/test/integration/smoke/test_pvlan.py +++ b/test/integration/smoke/test_pvlan.py @@ -41,6 +41,7 @@ class TestPVLAN(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() + @attr(tags = ["advanced"]) def test_create_pvlan_network(self): self.debug("Test create pvlan network") createNetworkCmd = createNetwork.createNetworkCmd() diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 9ec2e918c42..f6ca2790069 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -141,11 +141,17 @@ class TestRouterServices(cloudstackTestCase): # by checking status of dnsmasq process # Find router associated with user account - list_router_response = list_routers( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) + if self.zone.networktype == "Basic": + list_router_response = list_routers( + self.apiclient, + listall="true" + ) + else: + list_router_response = list_routers( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid + ) self.assertEqual( isinstance(list_router_response, list), True, diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index 382f56f8980..8b83f5e6e43 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -295,11 +295,9 @@ class TestTemplates(cloudstackTestCase): cls.services['mode'] = cls.zone.networktype #populate second zone id for iso copy cmd = listZones.listZonesCmd() - zones = cls.api_client.listZones(cmd) - if not isinstance(zones, list): + cls.zones = cls.api_client.listZones(cmd) + if not isinstance(cls.zones, list): raise Exception("Failed to find zones.") - if len(zones) >= 2: - cls.services["destzoneid"] = zones[1].id cls.disk_offering = DiskOffering.create( cls.api_client, @@ -664,6 +662,11 @@ class TestTemplates(cloudstackTestCase): # 1. copy template should be successful and # secondary storage should contain new copied template. + if len(self.zones) <= 1: + self.skipTest("Not enough zones available to perform copy template") + + self.services["destzoneid"] = filter(lambda z: z.id != self.services["sourcezoneid"], self.zones)[0] + self.debug("Copy template from Zone: %s to %s" % ( self.services["sourcezoneid"], self.services["destzoneid"] diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index 21c26357ab2..d52ed9b8df6 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -135,35 +135,34 @@ class TestDeployVM(cloudstackTestCase): cls.apiclient = super(TestDeployVM, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates domain = get_domain(cls.apiclient, cls.services) - zone = get_zone(cls.apiclient, cls.services) - cls.services['mode'] = zone.networktype + cls.zone = get_zone(cls.apiclient, cls.services) + cls.services['mode'] = cls.zone.networktype #If local storage is enabled, alter the offerings to use localstorage #this step is needed for devcloud - if zone.localstorageenabled == True: + if cls.zone.localstorageenabled == True: cls.services["service_offerings"]["tiny"]["storagetype"] = 'local' cls.services["service_offerings"]["small"]["storagetype"] = 'local' cls.services["service_offerings"]["medium"]["storagetype"] = 'local' template = get_template( cls.apiclient, - zone.id, + cls.zone.id, cls.services["ostype"] ) # Set Zones and disk offerings - cls.services["small"]["zoneid"] = zone.id + cls.services["small"]["zoneid"] = cls.zone.id cls.services["small"]["template"] = template.id - cls.services["medium"]["zoneid"] = zone.id + cls.services["medium"]["zoneid"] = cls.zone.id cls.services["medium"]["template"] = template.id - cls.services["iso"]["zoneid"] = zone.id + cls.services["iso"]["zoneid"] = cls.zone.id cls.account = Account.create( cls.apiclient, cls.services["account"], domainid=domain.id ) - cls.debug(str("============" )) cls.debug(cls.account.id) cls.service_offering = ServiceOffering.create( @@ -293,28 +292,28 @@ class TestVMLifeCycle(cloudstackTestCase): # Get Zone, Domain and templates domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = zone.networktype + cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype #if local storage is enabled, alter the offerings to use localstorage #this step is needed for devcloud - if zone.localstorageenabled == True: + if cls.zone.localstorageenabled == True: cls.services["service_offerings"]["tiny"]["storagetype"] = 'local' cls.services["service_offerings"]["small"]["storagetype"] = 'local' cls.services["service_offerings"]["medium"]["storagetype"] = 'local' template = get_template( cls.api_client, - zone.id, + cls.zone.id, cls.services["ostype"] ) # Set Zones and disk offerings - cls.services["small"]["zoneid"] = zone.id + cls.services["small"]["zoneid"] = cls.zone.id cls.services["small"]["template"] = template.id - cls.services["medium"]["zoneid"] = zone.id + cls.services["medium"]["zoneid"] = cls.zone.id cls.services["medium"]["template"] = template.id - cls.services["iso"]["zoneid"] = zone.id + cls.services["iso"]["zoneid"] = cls.zone.id # Create VMs, NAT Rules etc cls.account = Account.create( @@ -811,68 +810,76 @@ class TestVMLifeCycle(cloudstackTestCase): """Test migrate VM """ # Validate the following - # 1. Should be able to login to the VM. - # 2. listVM command should return this VM.State of this VM - # should be "Running" and the host should be the host - # to which the VM was migrated to + # 1. Environment has enough hosts for migration + # 2. DeployVM on suitable host (with another host in the cluster) + # 3. Migrate the VM and assert migration successful hosts = Host.list( - self.apiclient, - zoneid=self.medium_virtual_machine.zoneid, - type='Routing' - ) - + self.apiclient, + zoneid=self.zone.id, + type='Routing' + ) self.assertEqual( - isinstance(hosts, list), - True, - "Check the number of hosts in the zone" - ) + isinstance(hosts, list), + True, + "Check the number of hosts in the zone" + ) self.assertGreaterEqual( - len(hosts), - 2, - "Atleast 2 hosts should be present in a zone for VM migration" - ) - # Remove the host of current VM from the hosts list - hosts[:] = [host for host in hosts if host.id != self.medium_virtual_machine.hostid] + len(hosts), + 2, + "Atleast 2 hosts should be present for VM migration" + ) - host = hosts[0] + #identify suitable host + clusters = [h.clusterid for h in hosts] + #find hosts withe same clusterid + clusters = [cluster for index, cluster in enumerate(clusters) if clusters.count(cluster) > 1] + + if len(clusters) <= 1: + self.skipTest("Migration needs a cluster with at least two hosts") + + suitable_hosts = [host for host in hosts if host.clusterid == clusters[0]] + target_host = suitable_hosts[0] + migrate_host = suitable_hosts[1] + + #deploy VM on target host + self.vm_to_migrate = VirtualMachine.create( + self.api_client, + self.services["small"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.small_offering.id, + mode=self.services["mode"], + hostid=target_host.id + ) self.debug("Migrating VM-ID: %s to Host: %s" % ( - self.medium_virtual_machine.id, - host.id + self.vm_to_migrate.id, + migrate_host.id )) - cmd = migrateVirtualMachine.migrateVirtualMachineCmd() - cmd.hostid = host.id - cmd.virtualmachineid = self.medium_virtual_machine.id - self.apiclient.migrateVirtualMachine(cmd) + self.vm_to_migrate.migrate(self.api_client, migrate_host.id) list_vm_response = list_virtual_machines( self.apiclient, - id=self.medium_virtual_machine.id + id=self.vm_to_migrate.id ) - self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( list_vm_response, None, - "Check virtual machine is listVirtualMachines" + "Check virtual machine is listed" ) vm_response = list_vm_response[0] self.assertEqual( vm_response.id, - self.medium_virtual_machine.id, + self.vm_to_migrate.id, "Check virtual machine ID of migrated VM" ) self.assertEqual( vm_response.hostid, - host.id, + migrate_host.id, "Check destination hostID of migrated VM" ) return @@ -964,29 +971,25 @@ class TestVMLifeCycle(cloudstackTestCase): try: ssh_client = self.virtual_machine.get_ssh_client() - - cmds = [ - "mkdir -p %s" % self.services["mount_dir"], - "mount -rt iso9660 %s %s" \ - % ( - self.services["diskdevice"], - self.services["mount_dir"] - ), - ] - - for c in cmds: - res = ssh_client.execute(c) - - self.assertEqual(res, [], "Check mount is successful or not") - - c = "fdisk -l|grep %s|head -1" % self.services["diskdevice"] - res = ssh_client.execute(c) - #Disk /dev/xvdd: 4393 MB, 4393723904 bytes - except Exception as e: self.fail("SSH failed for virtual machine: %s - %s" % (self.virtual_machine.ipaddress, e)) + cmds = [ + "mkdir -p %s" % self.services["mount_dir"], + "mount -rt iso9660 %s %s" \ + % ( + self.services["diskdevice"], + self.services["mount_dir"] + ), + ] + for c in cmds: + res = ssh_client.execute(c) + self.assertEqual(res, [], "Check mount is successful or not") + c = "fdisk -l|grep %s|head -1" % self.services["diskdevice"] + res = ssh_client.execute(c) + #Disk /dev/xvdd: 4393 MB, 4393723904 bytes + # Res may contain more than one strings depending on environment # Split strings to form new list which is used for assertion on ISO size result = [] @@ -1015,7 +1018,6 @@ class TestVMLifeCycle(cloudstackTestCase): #Unmount ISO command = "umount %s" % self.services["mount_dir"] ssh_client.execute(command) - except Exception as e: self.fail("SSH failed for virtual machine: %s - %s" % (self.virtual_machine.ipaddress, e)) @@ -1027,7 +1029,6 @@ class TestVMLifeCycle(cloudstackTestCase): try: res = ssh_client.execute(c) - except Exception as e: self.fail("SSH failed for virtual machine: %s - %s" % (self.virtual_machine.ipaddress, e)) diff --git a/test/integration/smoke/test_vm_snapshots.py b/test/integration/smoke/test_vm_snapshots.py index 353d499f7a1..cca4cfb767f 100644 --- a/test/integration/smoke/test_vm_snapshots.py +++ b/test/integration/smoke/test_vm_snapshots.py @@ -1,308 +1,310 @@ -# 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. - -# 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 * -from marvin.remoteSSHClient import remoteSSHClient - -class Services: - """Test Snapshots Services - """ - - def __init__(self): - self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended for unique - # username - "password": "password", - }, - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 200, # in MHz - "memory": 256, # In MBs - }, - "server": { - "displayname": "TestVM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "mgmt_server": { - "ipaddress": '1.2.2.152', - "username": "root", - "password": "password", - "port": 22, - }, - "templates": { - "displaytext": 'Template', - "name": 'Template', - "ostype": "CentOS 5.3 (64-bit)", - "templatefilter": 'self', - }, - "test_dir": "/tmp", - "random_data": "random.data", - "snapshot_name":"TestSnapshot", - "snapshot_displaytext":"Test", - "ostype": "CentOS 5.3 (64-bit)", - "sleep": 60, - "timeout": 10, - "mode": 'advanced', # Networking mode: Advanced, Basic - } - -class TestVmSnapshot(cloudstackTestCase): - @classmethod - def setUpClass(cls): - cls.api_client = super(TestVmSnapshot, cls).getClsTestClient().getApiClient() - cls.services = Services().services - # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - - template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) - cls.services["domainid"] = cls.domain.id - cls.services["server"]["zoneid"] = cls.zone.id - cls.services["templates"]["ostypeid"] = template.ostypeid - cls.services["zoneid"] = cls.zone.id - - # Create VMs, NAT Rules etc - cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=cls.domain.id - ) - - cls.services["account"] = cls.account.name - - cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] - ) - cls.virtual_machine = VirtualMachine.create( - cls.api_client, - cls.services["server"], - templateid=template.id, - accountid=cls.account.name, - domainid=cls.account.domainid, - serviceofferingid=cls.service_offering.id, - mode=cls.services["mode"] - ) - cls.random_data_0 = random_gen(100) - cls._cleanup = [ - cls.service_offering, - 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, terminate the created instance, volumes and snapshots - cleanup_resources(self.apiclient, self.cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return - - @attr(tags=["advanced", "advancedns", "smoke"]) - def test_01_create_vm_snapshots(self): - - try: - # Login to VM and write data to file system - ssh_client = self.virtual_machine.get_ssh_client() - - cmds = [ - "echo %s > %s/%s" % (self.random_data_0, self.services["test_dir"], self.services["random_data"]), - "cat %s/%s" % (self.services["test_dir"], self.services["random_data"]) - ] - - for c in cmds: - self.debug(c) - result = ssh_client.execute(c) - self.debug(result) - - except Exception: - self.fail("SSH failed for Virtual machine: %s" % - self.virtual_machine.ipaddress) - self.assertEqual( - self.random_data_0, - result[0], - "Check the random data has be write into temp file!" - ) - - time.sleep(self.services["sleep"]) - - vm_snapshot = VmSnapshot.create( - self.apiclient, - self.virtual_machine.id, - "false", - self.services["snapshot_name"], - self.services["snapshot_displaytext"] - ) - self.assertEqual( - vm_snapshot.state, - "Ready", - "Check the snapshot of vm is ready!" - ) - return - - @attr(tags=["advanced", "advancedns", "smoke"]) - def test_02_revert_vm_snapshots(self): - try: - ssh_client = self.virtual_machine.get_ssh_client() - - cmds = [ - "rm -rf %s/%s" % (self.services["test_dir"], self.services["random_data"]), - "ls %s/%s" % (self.services["test_dir"], self.services["random_data"]) - ] - - for c in cmds: - self.debug(c) - result = ssh_client.execute(c) - self.debug(result) - - except Exception: - self.fail("SSH failed for Virtual machine: %s" % - self.virtual_machine.ipaddress) - - if str(result[0]).index("No such file or directory") == -1: - self.fail("Check the random data has be delete from temp file!") - - time.sleep(self.services["sleep"]) - - list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True) - - self.assertEqual( - isinstance(list_snapshot_response, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - list_snapshot_response, - None, - "Check if snapshot exists in ListSnapshot" - ) - - self.assertEqual( - list_snapshot_response[0].state, - "Ready", - "Check the snapshot of vm is ready!" - ) - - VmSnapshot.revertToSnapshot(self.apiclient,list_snapshot_response[0].id) - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.virtual_machine.id - ) - - self.assertEqual( - list_vm_response[0].state, - "Stopped", - "Check the state of vm is Stopped!" - ) - - cmd = startVirtualMachine.startVirtualMachineCmd() - cmd.id = list_vm_response[0].id - self.apiclient.startVirtualMachine(cmd) - - time.sleep(self.services["sleep"]) - - try: - ssh_client = self.virtual_machine.get_ssh_client(reconnect=True) - - cmds = [ - "cat %s/%s" % (self.services["test_dir"], self.services["random_data"]) - ] - - for c in cmds: - self.debug(c) - result = ssh_client.execute(c) - self.debug(result) - - except Exception: - self.fail("SSH failed for Virtual machine: %s" % - self.virtual_machine.ipaddress) - - self.assertEqual( - self.random_data_0, - result[0], - "Check the random data is equal with the ramdom file!" - ) - @attr(tags=["advanced", "advancedns", "smoke"]) - def test_03_delete_vm_snapshots(self): - - list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True) - - self.assertEqual( - isinstance(list_snapshot_response, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - list_snapshot_response, - None, - "Check if snapshot exists in ListSnapshot" - ) - """ - cmd = deleteVMSnapshot.deleteVMSnapshotCmd() - cmd.vmsnapshotid = list_snapshot_response[0].id - self.apiclient.deleteVMSnapshot(cmd) - """ - VmSnapshot.deleteVMSnapshot(self.apiclient,list_snapshot_response[0].id) - - time.sleep(self.services["sleep"]*3) - - list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True) - - self.assertEqual( - list_snapshot_response, - None, - "Check list vm snapshot has be deleted" - ) +# 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. + +# 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 * + +class Services: + """Test Snapshots Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 200, # in MHz + "memory": 256, # In MBs + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "mgmt_server": { + "ipaddress": '1.2.2.152', + "username": "root", + "password": "password", + "port": 22, + }, + "templates": { + "displaytext": 'Template', + "name": 'Template', + "ostype": "CentOS 5.3 (64-bit)", + "templatefilter": 'self', + }, + "test_dir": "/tmp", + "random_data": "random.data", + "snapshot_name":"TestSnapshot", + "snapshot_displaytext":"Test", + "ostype": "CentOS 5.3 (64-bit)", + "sleep": 60, + "timeout": 10, + "mode": 'advanced', # Networking mode: Advanced, Basic + } + +class TestVmSnapshot(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.api_client = super(TestVmSnapshot, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["server"]["zoneid"] = cls.zone.id + cls.services["templates"]["ostypeid"] = template.ostypeid + cls.services["zoneid"] = cls.zone.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + cls.random_data_0 = random_gen(100) + cls._cleanup = [ + cls.service_offering, + 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, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced", "advancedns", "smoke"]) + def test_01_create_vm_snapshots(self): + """Test to create VM snapshots + """ + + try: + # Login to VM and write data to file system + ssh_client = self.virtual_machine.get_ssh_client() + + cmds = [ + "echo %s > %s/%s" % (self.random_data_0, self.services["test_dir"], self.services["random_data"]), + "cat %s/%s" % (self.services["test_dir"], self.services["random_data"]) + ] + + for c in cmds: + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) + + except Exception: + self.fail("SSH failed for Virtual machine: %s" % + self.virtual_machine.ipaddress) + self.assertEqual( + self.random_data_0, + result[0], + "Check the random data has be write into temp file!" + ) + + time.sleep(self.services["sleep"]) + + vm_snapshot = VmSnapshot.create( + self.apiclient, + self.virtual_machine.id, + "false", + self.services["snapshot_name"], + self.services["snapshot_displaytext"] + ) + self.assertEqual( + vm_snapshot.state, + "Ready", + "Check the snapshot of vm is ready!" + ) + return + + @attr(tags=["advanced", "advancedns", "smoke"]) + def test_02_revert_vm_snapshots(self): + """Test to revert VM snapshots + """ + + try: + ssh_client = self.virtual_machine.get_ssh_client() + + cmds = [ + "rm -rf %s/%s" % (self.services["test_dir"], self.services["random_data"]), + "ls %s/%s" % (self.services["test_dir"], self.services["random_data"]) + ] + + for c in cmds: + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) + + except Exception: + self.fail("SSH failed for Virtual machine: %s" % + self.virtual_machine.ipaddress) + + if str(result[0]).index("No such file or directory") == -1: + self.fail("Check the random data has be delete from temp file!") + + time.sleep(self.services["sleep"]) + + list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True) + + self.assertEqual( + isinstance(list_snapshot_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + list_snapshot_response, + None, + "Check if snapshot exists in ListSnapshot" + ) + + self.assertEqual( + list_snapshot_response[0].state, + "Ready", + "Check the snapshot of vm is ready!" + ) + + VmSnapshot.revertToSnapshot(self.apiclient,list_snapshot_response[0].id) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.assertEqual( + list_vm_response[0].state, + "Stopped", + "Check the state of vm is Stopped!" + ) + + cmd = startVirtualMachine.startVirtualMachineCmd() + cmd.id = list_vm_response[0].id + self.apiclient.startVirtualMachine(cmd) + + time.sleep(self.services["sleep"]) + + try: + ssh_client = self.virtual_machine.get_ssh_client(reconnect=True) + + cmds = [ + "cat %s/%s" % (self.services["test_dir"], self.services["random_data"]) + ] + + for c in cmds: + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) + + except Exception: + self.fail("SSH failed for Virtual machine: %s" % + self.virtual_machine.ipaddress) + + self.assertEqual( + self.random_data_0, + result[0], + "Check the random data is equal with the ramdom file!" + ) + + @attr(tags=["advanced", "advancedns", "smoke"]) + def test_03_delete_vm_snapshots(self): + """Test to delete vm snapshots + """ + + list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True) + + self.assertEqual( + isinstance(list_snapshot_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + list_snapshot_response, + None, + "Check if snapshot exists in ListSnapshot" + ) + VmSnapshot.deleteVMSnapshot(self.apiclient,list_snapshot_response[0].id) + + time.sleep(self.services["sleep"]*3) + + list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True) + + self.assertEqual( + list_snapshot_response, + None, + "Check list vm snapshot has be deleted" + ) diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index f29410d0b29..60fbb80f0e7 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -54,19 +54,17 @@ class Services: "displaytext": "Tiny Instance", "cpunumber": 1, "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - "storagetype": "local" + "memory": 260 # In MBs + }, "disk_offering": { "displaytext": "Small", "name": "Small", - "storagetype": "local", "disksize": 1 }, 'resized_disk_offering': { "displaytext": "Resized", "name": "Resized", - "storagetype": "local", "disksize": 3 }, "volume_offerings": { @@ -153,7 +151,7 @@ class TestCreateVolume(cloudstackTestCase): self.dbclient = self.testClient.getDbConnection() self.cleanup = [] - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_01_create_volume(self): """Test Volume creation for all Disk Offerings (incl. custom) """ @@ -347,6 +345,7 @@ class TestVolumes(cloudstackTestCase): cls.custom_resized_disk_offering, cls.service_offering, cls.disk_offering, + cls.volume, cls.account ] @@ -360,14 +359,17 @@ class TestVolumes(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() + self.attached = False self.cleanup = [] def tearDown(self): #Clean up, terminate the created volumes + if self.attached: + self.virtual_machine.detach_volume(self.apiClient, self.volume) cleanup_resources(self.apiClient, self.cleanup) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_02_attach_volume(self): """Attach a created Volume to a Running VM """ @@ -382,7 +384,7 @@ class TestVolumes(cloudstackTestCase): self.virtual_machine.id )) self.virtual_machine.attach_volume(self.apiClient, self.volume) - + self.attached = True list_volume_response = list_volumes( self.apiClient, id=self.volume.id @@ -413,7 +415,7 @@ class TestVolumes(cloudstackTestCase): (self.virtual_machine.ipaddress, e)) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_03_download_attached_volume(self): """Download a Volume attached to a VM """ @@ -424,6 +426,8 @@ class TestVolumes(cloudstackTestCase): self.debug("Extract attached Volume ID: %s" % self.volume.id) + self.virtual_machine.attach_volume(self.apiClient, self.volume) + self.attached = True cmd = extractVolume.extractVolumeCmd() cmd.id = self.volume.id cmd.mode = "HTTP_DOWNLOAD" @@ -433,7 +437,7 @@ class TestVolumes(cloudstackTestCase): with self.assertRaises(Exception): self.apiClient.extractVolume(cmd) - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_04_delete_attached_volume(self): """Delete a Volume attached to a VM """ @@ -445,15 +449,16 @@ class TestVolumes(cloudstackTestCase): self.debug("Trying to delete attached Volume ID: %s" % self.volume.id) - + self.virtual_machine.attach_volume(self.apiClient, self.volume) + self.attached = True cmd = deleteVolume.deleteVolumeCmd() cmd.id = self.volume.id #Proper exception should be raised; deleting attach VM is not allowed #with self.assertRaises(Exception): - with self.assertRaises(cloudstackAPIException): + with self.assertRaises(Exception): self.apiClient.deleteVolume(cmd) - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_05_detach_volume(self): """Detach a Volume attached to a VM """ @@ -467,8 +472,9 @@ class TestVolumes(cloudstackTestCase): self.volume.id, self.virtual_machine.id )) - + self.virtual_machine.attach_volume(self.apiClient, self.volume) self.virtual_machine.detach_volume(self.apiClient, self.volume) + self.attached = False #Sleep to ensure the current state will reflected in other calls time.sleep(self.services["sleep"]) list_volume_response = list_volumes( @@ -494,7 +500,7 @@ class TestVolumes(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_06_download_detached_volume(self): """Download a Volume unattached to an VM """ @@ -503,6 +509,10 @@ class TestVolumes(cloudstackTestCase): self.debug("Extract detached Volume ID: %s" % self.volume.id) + self.virtual_machine.attach_volume(self.apiClient, self.volume) + self.virtual_machine.detach_volume(self.apiClient, self.volume) + self.attached = False + cmd = extractVolume.extractVolumeCmd() cmd.id = self.volume.id cmd.mode = "HTTP_DOWNLOAD" @@ -525,7 +535,7 @@ class TestVolumes(cloudstackTestCase): % (extract_vol.url, self.volume.id) ) - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_07_resize_fail(self): """Verify invalid options fail to Resize a volume""" # Verify the size is the new size is what we wanted it to be. @@ -540,7 +550,7 @@ class TestVolumes(cloudstackTestCase): response = self.apiClient.resizeVolume(cmd) except Exception as ex: #print str(ex) - if "HTTP Error 431:" in str(ex): + if "invalid" in str(ex): success = True self.assertEqual( success, @@ -554,7 +564,7 @@ class TestVolumes(cloudstackTestCase): try: response = self.apiClient.resizeVolume(cmd) except Exception as ex: - if "HTTP Error 431:" in str(ex): + if "invalid" in str(ex): success = True self.assertEqual( success, @@ -573,6 +583,7 @@ class TestVolumes(cloudstackTestCase): ) #attach the volume self.virtual_machine.attach_volume(self.apiClient, self.volume) + self.attached = True #stop the vm if it is on xenserver if self.services['hypervisor'].lower() == "xenserver": self.virtual_machine.stop(self.apiClient) @@ -600,10 +611,11 @@ class TestVolumes(cloudstackTestCase): True, "Verify the volume did not resize" ) - self.virtual_machine.detach_volume(self.apiClient, self.volume) - self.cleanup.append(self.volume) + if self.services['hypervisor'].lower() == "xenserver": + self.virtual_machine.start(self.apiClient) - @attr(tags = ["advanced", "advancedns", "smoke"]) + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_08_resize_volume(self): """Resize a volume""" # Verify the size is the new size is what we wanted it to be. @@ -613,6 +625,8 @@ class TestVolumes(cloudstackTestCase): self.virtual_machine.id )) self.virtual_machine.attach_volume(self.apiClient, self.volume) + self.attached = True + if self.services['hypervisor'].lower() == "xenserver": self.virtual_machine.stop(self.apiClient) self.debug("Resize Volume ID: %s" % self.volume.id) @@ -632,7 +646,7 @@ class TestVolumes(cloudstackTestCase): type='DATADISK' ) for vol in list_volume_response: - if vol.id == self.volume.id and vol.size == 3221225472L: + if vol.id == self.volume.id and vol.size == 3221225472L and vol.state == 'Ready': success = True if success: break @@ -646,10 +660,10 @@ class TestVolumes(cloudstackTestCase): "Check if the volume resized appropriately" ) - self.virtual_machine.detach_volume(self.apiClient, self.volume) - self.cleanup.append(self.volume) + if self.services['hypervisor'].lower() == "xenserver": + self.virtual_machine.start(self.apiClient) - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke","basic"]) def test_09_delete_detached_volume(self): """Delete a Volume unattached to an VM """ @@ -662,13 +676,23 @@ class TestVolumes(cloudstackTestCase): self.debug("Delete Volume ID: %s" % self.volume.id) + self.volume_1 = Volume.create( + self.api_client, + self.services, + account=self.account.name, + domainid=self.account.domainid + ) + + self.virtual_machine.attach_volume(self.apiClient, self.volume_1) + self.virtual_machine.detach_volume(self.apiClient, self.volume_1) + cmd = deleteVolume.deleteVolumeCmd() - cmd.id = self.volume.id + cmd.id = self.volume_1.id self.apiClient.deleteVolume(cmd) list_volume_response = list_volumes( self.apiClient, - id=self.volume.id, + id=self.volume_1.id, type='DATADISK' ) self.assertEqual( diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index c01bf475050..5d7e3be4e29 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -147,6 +147,7 @@ known_categories = { 'createCacheStore': 'Image Store', 'InternalLoadBalancer': 'Internal LB', 'DeploymentPlanners': 'Configuration', + 'PortableIp': 'Portable IP' } diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index b5ff5bf7b3f..e3977dcf7d4 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -43,10 +43,8 @@ class cloudConnection(object): self.securityKey = securityKey self.mgtSvr = mgtSvr self.port = port - if user: - self.user = user - if passwd: - self.passwd = passwd + self.user = user + self.passwd = passwd self.logging = logging self.path = path self.retries = 5 diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index ecdc8412fdb..ec1c34e12c7 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -685,6 +685,7 @@ class Volume: timeout = timeout - 1 return + @classmethod def migrate(cls, apiclient, **kwargs): """Migrate a volume""" cmd = migrateVolume.migrateVolumeCmd() @@ -1268,6 +1269,10 @@ class ServiceOffering: if "tags" in services: cmd.tags = services["tags"] + + if "deploymentplanner" in services: + cmd.deploymentplanner = services["deploymentplanner"] + # Service Offering private to that domain if domainid: cmd.domainid = domainid @@ -2126,6 +2131,42 @@ class PublicIpRange: cmd.id = self.vlan.id return apiclient.releasePublicIpRange(cmd) + +class PortablePublicIpRange: + """Manage portable public Ip Range""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services): + """Create portable public Ip Range""" + + cmd = createPortableIpRange.createPortableIpRangeCmd() + cmd.gateway = services["gateway"] + cmd.netmask = services["netmask"] + cmd.startip = services["startip"] + cmd.endip = services["endip"] + cmd.regionid = services["regionid"] + cmd.vlan = services["vlan"] + + return PortablePublicIpRange(apiclient.createVlanIpRange(cmd).__dict__) + + def delete(self, apiclient): + """Delete portable IpRange""" + + cmd = deletePortableIpRange.deletePortableIpRangeCmd() + cmd.id = self.id + apiclient.deletePortableIpRange(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """Lists all portable public IP ranges.""" + + cmd = listPortableIpRanges.listPortableIpRangesCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listPortableIpRanges(cmd)) + class SecondaryStorage: """Manage Secondary storage""" diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 9a08c4c56b1..9932cdc3aa6 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -144,6 +144,38 @@ }, + deploymentPlanner:{ + label:'Deployment Planner', + select:function(args){ + $.ajax({ + url:createURL('listDeploymentPlanners'), + dataType:'json', + success:function(json){ + var items=[]; + var plannerObjs = json.listdeploymentplannersresponse.deploymentPlanner; + $(plannerObjs).each(function(){ + items.push({id: this.name, description: this.name}); + }); + args.response.success({data: items}); + + + } + }); + } + }, + + plannerKey:{label:'Planner Key' , docID:'helpImplicitPlannerKey'}, + plannerMode:{ + label:'Planner Mode', + select:function(args){ + var items=[]; + items.push({id:'',description:''}); + items.push({id:'Strict', description:'Strict'}); + items.push({id:'Preffered', description:'Preffered'}); + args.response.success({data:items}); + } + }, + domainId: { label: 'label.domain', docID: 'helpComputeOfferingDomain', @@ -176,9 +208,15 @@ storageType: args.data.storageType, cpuNumber: args.data.cpuNumber, cpuSpeed: args.data.cpuSpeed, - memory: args.data.memory + memory: args.data.memory, + deploymentplanner: args.data.deploymentPlanner + }; - + var array1 =[]; + if(args.data.plannerMode != null && args.data.plannerKey !=""){ + array1.push("&serviceofferingdetails[0]." + args.data.plannerKey + "=" + args.data.plannerMode); + } + if(args.data.networkRate != null && args.data.networkRate.length > 0) { $.extend(data, { networkrate: args.data.networkRate @@ -216,7 +254,7 @@ } $.ajax({ - url: createURL('createServiceOffering'), + url: createURL('createServiceOffering' + array1.join("")), data: data, success: function(json) { var item = json.createserviceofferingresponse.serviceoffering; @@ -362,6 +400,7 @@ converter: cloudStack.converters.toBooleanText }, isvolatile:{ label:'Volatile' , converter: cloudStack.converters.toBooleanText }, + deploymentplanner:{label:'Deployment Planner'}, tags: { label: 'label.storage.tags' }, hosttags: { label: 'label.host.tags' }, domain: { label: 'label.domain' }, @@ -1122,7 +1161,8 @@ title: 'label.add.network.offering', preFilter: function(args) { var $availability = args.$form.find('.form-item[rel=availability]'); - var $serviceOfferingId = args.$form.find('.form-item[rel=serviceOfferingId]'); + var $lbType = args.$form.find('.form-item[rel=lbType]'); + var $systemOfferingForRouter = args.$form.find('.form-item[rel=systemOfferingForRouter]'); var $conservemode = args.$form.find('.form-item[rel=conservemode]'); var $serviceSourceNatRedundantRouterCapabilityCheckbox = args.$form.find('.form-item[rel="service.SourceNat.redundantRouterCapabilityCheckbox"]'); var hasAdvancedZones = false; @@ -1147,18 +1187,18 @@ //check whether to show or hide availability field var $sourceNATField = args.$form.find('input[name=\"service.SourceNat.isEnabled\"]'); var $guestTypeField = args.$form.find('select[name=guestIpType]'); - + + var $useVpc = args.$form.find('.form-item[rel=\"useVpc\"]'); + var $useVpcCb = $useVpc.find("input[type=checkbox]"); if($guestTypeField.val() == 'Shared') { //Shared network offering - args.$form.find('.form-item[rel=\"useVpc\"]').hide(); - - var $useVpcCb = args.$form.find('.form-item[rel=\"useVpc\"]').find("input[type=checkbox]"); + $useVpc.hide(); if($useVpcCb.is(':checked')) { //if useVpc is checked, $useVpcCb.removeAttr("checked"); //remove "checked" attribute in useVpc $useVpcCb.trigger("click"); //trigger useVpc.onChange() } } else { //Isolated network offering - args.$form.find('.form-item[rel=\"useVpc\"]').css('display', 'inline-block'); + $useVpc.css('display', 'inline-block'); } @@ -1170,7 +1210,14 @@ $availability.hide(); } - + //when useVpc is checked and service.Lb.isEnabled is checked + if($useVpcCb.is(':checked') && $("input[name='service.Lb.isEnabled']").is(":checked") == true) { + $lbType.css('display', 'inline-block'); + } + else { + $lbType.hide(); + } + //when service(s) has Virtual Router as provider..... var havingVirtualRouterForAtLeastOneService = false; $(serviceCheckboxNames).each(function(){ @@ -1185,10 +1232,10 @@ } }); if(havingVirtualRouterForAtLeastOneService == true) { - $serviceOfferingId.css('display', 'inline-block'); + $systemOfferingForRouter.css('display', 'inline-block'); } else { - $serviceOfferingId.hide(); + $systemOfferingForRouter.hide(); } @@ -1427,24 +1474,101 @@ label: 'VPC', docID: 'helpNetworkOfferingVPC', isBoolean: true, - onChange: function(args) { - var $checkbox = args.$checkbox; - var $selects = $checkbox.closest('form').find('.dynamic-input select'); - var $vpcOptions = $selects.find('option[value=VpcVirtualRouter]'); + onChange: function(args) { + var $vpc = args.$checkbox; + var $providers = $vpc.closest('form').find('.dynamic-input select'); + var $optionsOfProviders = $providers.find('option'); - if ($checkbox.is(':checked')) { - $vpcOptions.siblings().attr('disabled', true); - $selects.val('VpcVirtualRouter'); - } else { - $vpcOptions.siblings().attr('disabled', false); - $vpcOptions.attr('disabled', true); - $selects.each(function() { - $(this).val($(this).find('option:first')); - }); + //p.s. Netscaler is supported in both vpc and non-vpc + + if ($vpc.is(':checked')) { //*** vpc *** + $optionsOfProviders.each(function(index) { + if($(this).val() == 'InternalLbVm' || $(this).val() == 'VpcVirtualRouter' || $(this).val() == 'Netscaler') { + $(this).attr('disabled', false); + } + else { + $(this).attr('disabled', true); + } + }); + } + else { //*** non-vpc *** + $optionsOfProviders.each(function(index) { + if($(this).val() == 'InternalLbVm' || $(this).val() == 'VpcVirtualRouter') { + $(this).attr('disabled', true); + } + else { + $(this).attr('disabled', false); + } + }); } + + $providers.each(function() { + $(this).val($(this).find('option:first')); + }); + } }, - + + lbType: { //only shown when VPC is checked and LB service is checked + label: 'Load Balancer Type', + isHidden: true, + select: function(args) { + args.response.success({data: [ + {id: 'publicLb', description: 'Public LB'}, + {id: 'internalLb', description: 'Internal LB'} + ]}); + + args.$select.change(function() { + if($(this).is(':visible') == false) + return; //if lbType is not visible, do nothing. + + var $lbProvider = $(this).closest('form').find('.form-item[rel=\"service.Lb.provider\"]').find('select'); + var $lbProviderOptions = $lbProvider.find('option'); + + if($(this).val() == 'publicLb') { //disable all providers except the ones in lbProviderMap.publicLb.vpc => ["VpcVirtualRouter", "Netscaler"] + for(var i = 0; i < $lbProviderOptions.length; i++ ) { + var $option = $lbProviderOptions.eq(i); + var supportedProviders = lbProviderMap.publicLb.vpc; + var thisOpionIsSupported = false; + for(var k = 0; k < supportedProviders.length; k++ ) { + if($option.val() == supportedProviders[k]) { + thisOpionIsSupported = true; + break; + } + } + if(thisOpionIsSupported == true) { + $option.attr('disabled', false); + } + else { + $option.attr('disabled', true); + } + } + } + else if($(this).val() == 'internalLb') { //disable all providers except the ones in lbProviderMap.internalLb.vpc => ["InternalLbVm"] + for(var i = 0; i < $lbProviderOptions.length; i++ ) { + var $option = $lbProviderOptions.eq(i); + var supportedProviders = lbProviderMap.internalLb.vpc; + var thisOpionIsSupported = false; + for(var k = 0; k < supportedProviders.length; k++ ) { + if($option.val() == supportedProviders[k]) { + thisOpionIsSupported = true; + break; + } + } + if(thisOpionIsSupported == true) { + $option.attr('disabled', false); + } + else { + $option.attr('disabled', true); + } + } + } + + $lbProvider.val($lbProvider.find('option:first')); + }); + } + }, + supportedServices: { label: 'label.supported.services', @@ -1569,8 +1693,9 @@ }, //show or hide upon checked services and selected providers above (begin) - serviceOfferingId: { - label: 'label.system.offering', + systemOfferingForRouter: { + label: 'System Offering for Router', + isHidden: true, docID: 'helpNetworkOfferingSystemOffering', select: function(args) { $.ajax({ @@ -1616,9 +1741,9 @@ dependsOn: 'service.SourceNat.isEnabled', select: function(args) { args.response.success({ - data: [ - { id: 'perzone', description: 'Per zone'}, - { id: 'peraccount', description: 'Per account'} + data: [ + { id: 'peraccount', description: 'Per account'}, + { id: 'perzone', description: 'Per zone'} ] }); } @@ -1748,7 +1873,13 @@ inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'associatePublicIP'; inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = true; //because this checkbox's value == "on" serviceCapabilityIndex++; - } + } + else if((key == 'service.Lb.provider') && ("Lb" in serviceProviderMap) && (serviceProviderMap.Lb == "InternalLbVm")) { + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].service'] = 'lb'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'lbSchemes'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = 'internal'; + serviceCapabilityIndex++; + } } else if (value != '') { // Normal data inputData[key] = value; @@ -1788,26 +1919,22 @@ inputData['isPersistent'] = false; } else if (inputData['guestIpType'] == "Isolated") { //specifyVlan checkbox is shown - if (inputData['specifyVlan'] == 'on') { //specifyVlan checkbox is checked + inputData['specifyIpRanges'] = false; + + if (inputData['specifyVlan'] == 'on') { //specifyVlan checkbox is checked inputData['specifyVlan'] = true; - inputData['specifyIpRanges'] = true; - - - - } else { //specifyVlan checkbox is unchecked inputData['specifyVlan'] = false; - inputData['specifyIpRanges'] = false; + } - if(inputData['isPersistent'] == 'on') { //It is a persistent network - inputData['isPersistent'] = true; - } - else { //Isolated Network with Non-persistent network - inputData['isPersistent'] = false; - } - + if(inputData['isPersistent'] == 'on') { //It is a persistent network + inputData['isPersistent'] = true; + } + else { //Isolated Network with Non-persistent network + inputData['isPersistent'] = false; + } } @@ -1829,8 +1956,8 @@ if(args.$form.find('.form-item[rel=availability]').css("display") == "none") inputData['availability'] = 'Optional'; - if(args.$form.find('.form-item[rel=serviceOfferingId]').css("display") == "none") - delete inputData.serviceOfferingId; + if(args.$form.find('.form-item[rel=systemOfferingForRouter]').css("display") == "none") + delete inputData.systemOfferingForRouter; inputData['traffictype'] = 'GUEST'; //traffic type dropdown has been removed since it has only one option ('Guest'). Hardcode traffic type value here. diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js index 4a70ca1df7f..7c1aaf83c35 100755 --- a/ui/scripts/docs.js +++ b/ui/scripts/docs.js @@ -16,6 +16,15 @@ // under the License. cloudStack.docs = { + //Implicit Planner + + helpImplicitPlannerKey:{ + + desc:'Please provide a Planner key for the Implicit Planner you are going to use and then select its mode below .Eg - Planner Key :ImplicitDedicationMode', + externalLink:'' + + }, + //Delete/archive events helpEventsDeleteType:{ diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 6b310ce0e83..3eef1367e97 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -50,7 +50,7 @@ nicId: nic.id }, success: function(json) { - var nic = json.listnics.nic[0]; + var nic = json.listnicsresponse.nic[0]; var ips = nic.secondaryip ? nic.secondaryip : []; var ipSelection = []; diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 76f797cd220..c62229ca3be 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2709,6 +2709,362 @@ } }, + InternalLbVm: { + id: 'InternalLbVm', + label: 'InternalLbVm', + isMaximized: true, + type: 'detailView', + fields: { + name: { label: 'label.name' }, + ipaddress: { label: 'label.ip.address' }, + state: { label: 'label.status', indicator: { 'Enabled': 'on' } } + }, + tabs: { + network: { + title: 'label.network', + fields: [ + { + name: { label: 'label.name' } + }, + { + id: { label: 'label.id' }, + state: { label: 'label.state' }, + physicalnetworkid: { label: 'label.physical.network.ID' }, + destinationphysicalnetworkid: { label: 'label.destination.physical.network.id' }, + supportedServices: { label: 'label.supported.services' } + } + ], + dataProvider: function(args) { + refreshNspData("InternalLbVm"); + args.response.success({ + actionFilter: virtualRouterProviderActionFilter, + data: $.extend(nspMap["InternalLbVm"], { + supportedServices: nspMap["InternalLbVm"].servicelist.join(', ') + }) + }); + } + }, + + instances: { + title: 'label.instances', + listView: { + label: 'label.virtual.appliances', + id: 'internallbinstances', + fields: { + name: { label: 'label.name' }, + zonename: { label: 'label.zone' }, + routerType: { + label: 'label.type' + }, + state: { + converter: function(str) { + // For localization + return str; + }, + label: 'label.status', + indicator: { + 'Running': 'on', + 'Stopped': 'off', + 'Error': 'off' + } + } + }, + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + + var routers = []; + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + success: function(json) { + var items = json.listinternallbvmssresponse.internalloadbalancervm ? + json.listinternallbvmssresponse.internalloadbalancervm : []; + + $(items).map(function(index, item) { + routers.push(item); + }); + + // Get project routers + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"), + success: function(json) { + var items = json.listinternallbvmssresponse.internalloadbalancervm ? + json.listinternallbvmssresponse.internalloadbalancervm : []; + + $(items).map(function(index, item) { + routers.push(item); + }); + args.response.success({ + actionFilter: internallbinstanceActionfilter, + data: $(routers).map(mapRouterType) + }); + } + }); + } + }); + }, + detailView: { + name: 'Virtual applicance details', + actions: { + start: { + label: 'Start LB VM', + messages: { + confirm: function(args) { + return 'Please confirm you want to start LB VM'; + }, + notification: function(args) { + return 'Start LB VM'; + } + }, + action: function(args) { + $.ajax({ + url: createURL('startInternalLoadBalancerVM&id=' + args.context.internallbinstances[0].id), + dataType: 'json', + async: true, + success: function(json) { + var jid = json.startinternallbvmresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.internalloadbalancervm; + }, + getActionFilter: function() { + return internallbinstanceActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + stop: { + label: 'Stop LB VM', + createForm: { + title: 'Please confirm you want to stop LB VM', + desc: 'Stop LB VM', + fields: { + forced: { + label: 'force.stop', + isBoolean: true, + isChecked: false + } + } + }, + messages: { + notification: function(args) { + return 'Stop LB VM'; + } + }, + action: function(args) { + var array1 = []; + array1.push("&forced=" + (args.data.forced == "on")); + $.ajax({ + url: createURL('stopInternalLoadBalancerVM&id=' + args.context.internallbinstances[0].id + array1.join("")), + dataType: 'json', + async: true, + success: function(json) { + var jid = json.stopinternallbvmresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.internalloadbalancervm; + }, + getActionFilter: function() { + return internallbinstanceActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + preFilter: function(args) { + var hiddenFields = []; + if (!args.context.internallbinstances[0].project) { + hiddenFields.push('project'); + hiddenFields.push('projectid'); + } + if(selectedZoneObj.networktype == 'Basic') { + hiddenFields.push('publicip'); //In Basic zone, guest IP is public IP. So, publicip is not returned by listRouters API. Only guestipaddress is returned by listRouters API. + } + return hiddenFields; + }, + fields: [ + { + name: { label: 'label.name' }, + project: { label: 'label.project' } + }, + { + id: { label: 'label.id' }, + projectid: { label: 'label.project.id' }, + state: { label: 'label.state' }, + guestnetworkid: { label: 'label.network.id' }, + publicip: { label: 'label.public.ip' }, + guestipaddress: { label: 'label.guest.ip' }, + linklocalip: { label: 'label.linklocal.ip' }, + hostname: { label: 'label.host' }, + serviceofferingname: { label: 'label.compute.offering' }, + networkdomain: { label: 'label.network.domain' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' }, + created: { label: 'label.created', converter: cloudStack.converters.toLocalDate }, + isredundantrouter: { + label: 'label.redundant.router', + converter: cloudStack.converters.toBooleanText + }, + redundantRouterState: { label: 'label.redundant.state' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&id=" + args.context.internallbinstances[0].id), + dataType: 'json', + async: true, + success: function(json) { + var jsonObj = json.listinternallbvmssresponse.internalloadbalancervm[0]; + addExtraPropertiesToRouterInstanceObject(jsonObj); + args.response.success({ + actionFilter: internallbinstanceActionfilter, + data: jsonObj + }); + } + }); + } + }, + nics: { + title: 'label.nics', + multiple: true, + fields: [ + { + name: { label: 'label.name', header: true }, + type: { label: 'label.type' }, + traffictype: { label: 'label.traffic.type' }, + networkname: { label: 'label.network.name' }, + netmask: { label: 'label.netmask' }, + ipaddress: { label: 'label.ip.address' }, + id: { label: 'label.id' }, + networkid: { label: 'label.network.id' }, + isolationuri: { label: 'label.isolation.uri' }, + broadcasturi: { label: 'label.broadcast.uri' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&id=" + args.context.internallbinstances[0].id), + dataType: 'json', + async: true, + success: function(json) { + var jsonObj = json.listinternallbvmssresponse.internalloadbalancervm[0].nic; + + args.response.success({ + actionFilter: internallbinstanceActionfilter, + data: $.map(jsonObj, function(nic, index) { + var name = 'NIC ' + (index + 1); + if (nic.isdefault) { + name += ' (' + _l('label.default') + ')'; + } + return $.extend(nic, { + name: name + }); + }) + }); + } + }); + } + } + } + } + } + } + }, + actions: { + enable: { + label: 'label.enable.provider', + action: function(args) { + $.ajax({ + url: createURL("updateNetworkServiceProvider&id=" + nspMap["InternalLbVm"].id + "&state=Enabled"), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkserviceproviderresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + $(window).trigger('cloudStack.fullRefresh'); + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.confirm.enable.provider'; + }, + notification: function() { + return 'label.enable.provider'; + } + }, + notification: { poll: pollAsyncJobResult } + }, + disable: { + label: 'label.disable.provider', + action: function(args) { + $.ajax({ + url: createURL("updateNetworkServiceProvider&id=" + nspMap["InternalLbVm"].id + "&state=Disabled"), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkserviceproviderresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + $(window).trigger('cloudStack.fullRefresh'); + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.confirm.disable.provider'; + }, + notification: function() { + return 'label.disable.provider'; + } + }, + notification: { poll: pollAsyncJobResult } + } + } + }, + vpcVirtualRouter: { id: 'vpcVirtualRouterProviders', label: 'VPC Virtual Router', @@ -3317,7 +3673,7 @@ gslbprovider: { label: 'GSLB service', isBoolean: true, - isChecked: true + isChecked: false }, gslbproviderpublicip: { label: 'GSLB service Public IP' @@ -7009,7 +7365,7 @@ gslbprovider: { label: 'GSLB service', isBoolean: true, - isChecked: true + isChecked: false }, gslbproviderpublicip: { label: 'GSLB service Public IP' @@ -12356,6 +12712,19 @@ return allowedActions; } + var internallbinstanceActionfilter = function(args) { + var jsonObj = args.context.item; + var allowedActions = []; + + if (jsonObj.state == 'Running') { + allowedActions.push("stop"); + } + else if (jsonObj.state == 'Stopped') { + allowedActions.push("start"); + } + return allowedActions; + } + var systemvmActionfilter = function(args) { var jsonObj = args.context.item; var allowedActions = []; @@ -12437,6 +12806,9 @@ case "VirtualRouter": nspMap["virtualRouter"] = items[i]; break; + case "InternalLbVm": + nspMap["InternalLbVm"] = items[i]; + break; case "VpcVirtualRouter": nspMap["vpcVirtualRouter"] = items[i]; break; @@ -12513,6 +12885,15 @@ state: nspMap.midoNet? nspMap.midoNet.state : 'Disabled' } ); + + nspHardcodingArray.push( + { + id: 'InternalLbVm', + name: 'InternalLbVm', + state: nspMap.InternalLbVm ? nspMap.InternalLbVm.state : 'Disabled' + } + ); + nspHardcodingArray.push( { id: 'vpcVirtualRouter', diff --git a/ui/scripts/ui-custom/installWizard.js b/ui/scripts/ui-custom/installWizard.js index 86919f9fa41..9f1f4c761e5 100644 --- a/ui/scripts/ui-custom/installWizard.js +++ b/ui/scripts/ui-custom/installWizard.js @@ -298,6 +298,17 @@ * Layout/behavior for each step in wizard */ var steps = { + start: function(args) { + if (cloudStack.preInstall) { + return cloudStack.preInstall({ + complete: function() { + goTo('intro'); + } + }); + } + + return steps.intro(args); + }, intro: function(args) { var $intro = $('
').addClass('intro what-is-cloudstack'); var $title = $('
').addClass('title').html(_l('label.what.is.cloudstack')); @@ -775,7 +786,7 @@ } }; - var initialStep = steps.intro().addClass('step'); + var initialStep = steps.start().addClass('step'); showDiagram(''); diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index 85a89cb6951..12d78463079 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -664,7 +664,7 @@ gslbprovider: { label: 'GSLB service', isBoolean: true, - isChecked: true + isChecked: false }, gslbproviderpublicip: { label: 'GSLB service Public IP' diff --git a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java index 8bbe07c672c..337d444cbcc 100755 --- a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java +++ b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.persistence.Column; import javax.persistence.Transient; import net.sf.cglib.proxy.Factory; @@ -163,13 +164,16 @@ public class GenericSearchBuilder implements MethodInterceptor { set(fieldName); return null; } else { - name = name.toLowerCase(); - for (String fieldName : _attrs.keySet()) { - if (name.endsWith(fieldName.toLowerCase())) { - set(fieldName); - return null; - } - } + Column ann = method.getAnnotation(Column.class); + if (ann != null) { + String colName = ann.name(); + for (Map.Entry attr : _attrs.entrySet()) { + if (colName.equals(attr.getValue().columnName)) { + set(attr.getKey()); + return null; + } + } + } assert false : "Perhaps you need to make the method start with get or is?"; } } diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index 9551c262e54..37dcef382aa 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -1296,6 +1296,18 @@ public class NetUtils { return resultIp; } + public static boolean isValidVlan(String vlan) { + try { + int vnet = Integer.parseInt(vlan); + if (vnet < 0 || vnet > 4096) { + return false; + } + return true; + } catch (NumberFormatException e) { + return false; + } + } + public static URI generateUriForPvlan(String primaryVlan, String isolatedPvlan) { return URI.create("pvlan://" + primaryVlan + "-i" + isolatedPvlan); } @@ -1320,4 +1332,5 @@ public class NetUtils { } return null; } + }